...making Linux just a little more fun!

Unattended stream recording with MPlayer

By Silas Brown

The Linux movie player program MPlayer has an option to record an Internet-broadcast video stream for playing later. The recording can be done from the command line. This is useful for two reasons: (1) you can record at a time when you are too busy to watch, (2) if your Internet connection is poor for realtime video but reasonable for non-realtime bandwidth (some low-end cable connections are like this), then you might get better results by using ssh to log into a well-connected remote box, record the broadcast from there, and then download the resulting file in non-realtime (assuming the broadcast is short, otherwise this might not be practical).

However, many versions of MPlayer have trouble doing this unattended. Firstly, if the connection to the stream goes down for whatever reason, MPlayer makes no attempt to re-establish it, and secondly it's difficult to tell MPlayer when to stop recording (there are command-line timing options but they don't always work, and interrupt signals can be ignored).

One workaround is to write a script in Python (or some other language) that runs MPlayer inside a "pseudo-terminal" and control it via this terminal. The script can then take responsibility of restarting MPlayer if necessary, and sending a keystroke to close it down at the end.

The script below will do this. You will need to change the variables at the beginning (unless you want to record an episode of Shuowen Jiezi); it's probably a good idea to set the recording to start slightly before the scheduled start time and to finish slightly after the scheduled finishing time, just in case the studio doesn't keep perfect timing.

stream = "mms://65.49.26.231/suntv"
prefix = "/tmp/shuowenjiezi"
program_time = (20,05) # in your timezone
program_length_mins = 8

import pty, time, os, signal

t=time.localtime()
t = t[:3] + program_time + (0,) + t[6:]
startTime = time.mktime(t)
if time.time() > startTime:
    # missed today's program_time, wait for tomorrow
    startTime += 24*3600
endTime = startTime + program_length_mins*60

os.system("rm -f "+prefix+"*") # delete any previous recording
fileNo = 0

class TimeoutException: pass
handlingTimeout = False
def alarm(*args):
    if handlingTimeout: raise TimeoutException()
signal.signal(signal.SIGALRM, alarm)

print "Waiting to record %d minutes at %d:%02d" % ((program_length_mins,)+program_time)
time.sleep(max(0,startTime - time.time()))
while endTime > time.time():
    pid,fd = pty.fork()
    if pid==0: # child
        pty.spawn(["/bin/bash","-c","mplayer \"%s\" -dumpstream -dumpfile \"%s%02d.asf\"" % (stream,prefix,fileNo)])
        raise SystemExit # shouldn't get here
    print "mplayer started in background pty, monitoring"
    
    # Monitor the process, restarting if necessary, until time to finish:
    while os.waitpid(pid,os.WNOHANG)==(0,0) and endTime > time.time():
        # Need to read from fd to ensure its buffer is clear
        # but don't block on the reading - use signal to time out
        # (otherwise we might fail to stop the recording on time)
        signal.alarm(1)
        try:
            handlingTimeout = True
            os.read(fd,1024)
            handlingTimeout = False
        except TimeoutException: continue
        except OSError: continue
        time.sleep(1)
    fileNo += 1

print "Time to finish"
# Send it a Ctrl-C on the terminal
# (SIGINT doesn't always work, neither does -endpos)
os.write(fd,chr(3))
time.sleep(1) # just in case
os.close(fd)

Legal and traffic-flow issues

In countries that have television licensing, a license is usually needed to view or record any television broadcasts in any form, including over the Internet, provided that your reception occurs at the same time as the broadcast is being shown on air i.e. it is "live". (If the Internet stream is a second or two behind due to various packet delays, I think that would still count as "live".) The license is usually needed for the premises where the recording computer operates, which might be different from the premises where you will watch the result. The fact that the broadcast is coming from outside your country does not usually let you off (after all, people with normal televisions can't get out of it by promising to tune to foreign channels); however, it's possible that a license is not required if the on-air broadcast is completely unavailable in your country i.e. it cannot possibly be received even via satellite (so if it is carried by a satellite then that satellite had better not serve your side of the planet). This does not constitute legal advice; you need to check your local laws, and they might change.

You should also consider any network bandwidth regulations that you are subject to (some universities forbid unauthorized television downloads; you would need to ask permission). If you are using a remote computer to record the broadcast, you need to consider any relevant bandwidth restrictions from that computer also. Double-check the size of the stream's output files to make sure they are within reason.

Finally, remember that the recorded broadcast is almost certainly copyright and would be illegal to redistribute. The recording should be for yourself only.


Share

Talkback: Discuss this article with The Answer Gang


[BIO] Silas Brown is a legally blind computer scientist based in Cambridge UK. He has been using heavily-customised versions of Debian Linux since 1999.


Copyright © 2011, Silas Brown. Released under the Open Publication License unless otherwise noted in the body of the article.

Published in Issue 183 of Linux Gazette, February 2011

Tux