mplayer-resume is a PHP shell script I wrote to resume playback of files through mplayer. It works using slave mode and LIRC with mplayer, which outputs the variables to stdout. The wrapper script then keeps these values, and uses them to jump to that last point.

Note that this code is an archived copy of the source code. It's unmaintained, but probably works.


MPlayer playback / resume position script

	This PHP script will save the playback position of a file
	you watch with MPlayer.  Once you start playing the same file
	again, it will resume from last playback position.

	The *only* way this script will work is if you pass the
	"get_time_pos" command to MPlayer through an input event,
	mapped by either LIRC or the keyboard.

	The script captures the output and saves it to a file in
	the playback directory for each media file.

	See for more
	commands that work on both backends.


	To execute this program, either call it using the PHP
	binary, or make it executable.	Whichever you like best. :)

	$ php mplayer-resume movie.avi

		# cp mplayer-resume /usr/local/bin/
		# chmod +x /usr/local/bin/mplayer-resume
		$ mplayer-resume --filename movie.avi

	The script should parse any arguments that you want to send
	mplayer at the same time, regardless of whether you start
	it as a standalone program or with php.

		$ mplayer-resume --filename movie.avi -vo xv

	With php:
		$ php mplayer-resume --filename movie.avi -vo xv


	mplayer-resume --filename <filename> [options] [mplayer options]

	As of v2.0, the syntax has changed.  Previously, mplayer-resume
	would attempt to guess the correct filename, but in cases of movies
	with spaces in the file, it would cause problems.  Now, you must
	define the filename manually with the --filename argument.

MPlayer optional arguments:

	You can still pass all the normal arguments you would normally use
	when running mplayer.  They will be passed to the command line
	after mplayer-resume has added it's own.

	$ mplayer-resume --filename "My movie.mkv" -vo xv -fs -ao sdl

	The *only* extra arguments that this script will add to your
	mplayer command is -ss to seek to resume a file, and
	-quiet so it can correctly grab the output.

	The script will also strip out any commands that are known to
	break the output.  Currently the only one being stripped is

Optional arguments:

	Currently, mplayer-resume only supports one extra argument, a 
	small feature added to the script to scratch a personal itch of mine.

	Passing --use-dir-conf to mplayer-resume will look for a file named
	"mplayer.conf" in the same directory of the filename you are playing,
	and if one exists, it will pass "-include <filename>" to the mplayer

	This is just a little workaround to add a feature that mplayer doesn't
	currently implement. :)


	Setup your ~/.lircrc file to do three things when you hit
	the stop button:

		1) Get the time position
		2) Get the filename
		3) Stop playing
	Here's an example configuration:

			prog = mplayer
			button = stop
			config = get_time_pos
			prog = mplayer
			button = stop
			config = get_filename
			prog = mplayer
			button = stop
			config = quit

	You can of course map any button on your remote that you'd like
	to use this function for.


	Map a key with ~/.mplayer/input.conf to run 'get_time_pos'

	Sample entry:

		g get_time_pos

	When you want to save the position, hit 'g', and then 'q'
	to quit playback.

	You can also do it manually using mplayer's slave mode,
	which is useful for debugging:

		$ mplayer -slave -quiet movie.avi


	This script will save a text file for each media file you
	watch using this script.  The text files are saved in the
	config variable $save_files_to defined in the script, which
	must be a directory that this script can read / write to.

	The script will try to automatically create a directory, and
	uses /home/username/.mplayer/resume/ by default.


	If you are using MythVideo ( and want to
	use mplayer-resume as your playback script instead of mplayer,
	it's easy to setup.

	From the main menu, go to:

		Video Settings
		Player Settings

	Change the entry for Default Player to:

		mplayer-resume %s

	Please note that you *do not* need to put quotes around the
	filename (as of v0.20.x), as MythTV will do it by itself.

	You can of course add any other extra MPlayer arguments as you
	normally may here.

		mplayer-resume -fs -vo xv -aspect 16/9 %s


	If your CLI version of PHP is dumping version information
	each time it runs, add -q to the top line to supress the

		#!/usr/bin/php -q


	Doesn't save cwd with the file, so you can only have one
	entry per filename


	If you get stuck, don't hesitate to contact me.
mplayer-resume 2.0
#!/usr/bin/env php
	// By default, save files in ~/.mplayer/playback/
	$home = getenv('HOME');
	$save_files_to = "$home/.mplayer/playback/";
	 * @author Steve Dibb <steve dot dibb at gmail dot com>
	 * @copyright public-domain
	 * @date 2009-08-11
	 * @version 2.0
	 * @homepage
	 * Run time dependencies:
	 * PHP >= 4.3.0 with CLI and PCRE -
	 * MPlayer -
	 * See README for documentation on usage
	 * Quick example: mplayer-resume --filename "movie.mkv"
	 * Sends a string to stdout with a terminating line break
	 * @param string
	 * @param boolean display "mplayer-resume:" before each string
	function stdout($str, $leading_string = true) {
		if(is_string($str)) {
			$str = rtrim($str);
				$str = "mplayer-resume: $str";
			fwrite(STDOUT, "$str\n");
			return true;
		} else
			return false;
	 * Sends a string to stderr with a terminating line break
	 * @param string
	function stderr($str) {
		if(is_string($str)) {
			$str = rtrim($str);
			fwrite(STDERR, "mplayer-resume: $str\n");
			return true;
		} else
			return false;
	 * Parse CLI arguments
	 * If a value is unset, it will be set to true
	 * @param $argc argument count (system variable)
	 * @param $argv argument array (system variable)
	 * @return array
	function parseArguments($argc, $argv) {
		$arr = array();
		if($argc > 1) {
			// Drop the binary command
			for($x = 0; $x < count($argv); $x++) {
				if(preg_match('/^--\w+/', $argv[$x]) > 0) {
					$argv[$x] = preg_replace('/^--/', '', $argv[$x]);
					$arr[$argv[$x]] = true;
				} elseif(in_array($argv[($x-1)], array_keys($arr))) {
					$arr[$argv[($x-1)]] = $argv[$x];
			return $arr;
			return array();
	// Get the mplayer-resume arguments (not mplayer's)
	$args = parseArguments($argc, $argv);
	if($args['help'] || !count($args) || is_bool($movie) || $argc === 1) {
		stdout("Usage:\tmplayer-resume --filename <filename> [options] [mplayer options]", false);
		stdout("", false);
		stdout("Basic options:", false);
		stdout("", false);
		stdout(" --filename <filename>\tFilename to play with MPlayer", false);
		stdout(" --help \t\tThis help output", false);
		stdout("", false);
		stdout("Extended options:", false);
		stdout("", false);
		stdout(" --use-dir-conf\t\tPass \"-include <dirname of filename>/mplayer.conf\" to", false);
		stdout("\t\t\tmplayer if config file exists in same directory of", false);
		stdout("\t\t\tmedia file.  Similar to -use-filedir-conf.", false);
		stdout("", false);
		stdout("Example: $ mplayer-resume --filename \"A Man For All Seasons.mkv\" -fs -ao alsa", false);
		stdout("", false);
		stdout("mplayer-resume works by capturing events sent to MPlayer's slave mode", false);
		stdout("when exiting.  You will need to setup your MPlayer configuration files", false);
		stdout("to send the correct events in slave mode before this script will work.", false);
		stdout("", false);
		stdout("See the webpage for documentation:", false);
		stdout("", false);
	// Movie filename (used internally)
 	$movie = $filename = $args['filename'];
 	// PHP doesn't parse ~ as $HOME, so fix it ourselves
 	if(substr($movie, 0, 1) === "~")
 		$movie = $home.substr($movie, 1);
 	// Filename (escaped, ready to send to mplayer)
 	$mplayer_filename = escapeshellarg($movie);
	// Check to see the config directory exists.  If not, try and create it.
	if(!is_dir($save_files_to)) {
		if(!mkdir($save_files_to)) {
			stderr("Please make sure the directory $save_files_to exists and is both readable and writable by this user");
	// Make sure I can save playback files
	if(!is_writable($save_files_to) || !is_readable($save_files_to)) {
		stderr("I can't read from and/or write to $save_files_to");
	// Correct *some* human error ;)
	if(substr($save_files_to, -1, 1) != '/')
		$save_files_to .= '/';
	// Drop the binary from list of arguments
	// Put the arguments back together again
	$str_args = implode(' ', $argv);
	// Drop the filename command
	$str_args = str_replace('--filename', '', $str_args);
	// Keep the movie filename separate from args
  	$str_args = str_replace($filename, '', $str_args);
	// Remove arguments which will break the script
	// -really-quiet means no output to our slave commands
	$str_args = str_replace('-really-quiet', '', $str_args);
	// Where the seek position will be saved
	$basename = basename($movie);
	$txt = $save_files_to.$basename.".txt";
	// If there is already a playback file, read it and start
	// from that position.
	if(file_exists($txt)) {
		$ss = trim(file_get_contents($txt));
		// One more check for garbage
		if(is_numeric($ss) && $ss > 0)
			$flags = " -ss $ss ";
	/** Custom MPlayer workarounds */
	$custom_flags = array();
	$str_custom_flags = "";
	// --use-dir-conf
	// This is similar to -use-filedir-conf in mplayer.  It checks
	// to see if an "mplayer.conf" file exists in the directory of the
	// media file, and includes that.
	if($args['use-dir-conf']) {
		$str_args = str_replace("--use-dir-conf", "", $str_args);
		$conf = dirname($movie)."/mplayer.conf";
			$custom_flags[] = "-include ".escapeshellarg("$conf");
 		$str_custom_flags = implode(" ", $custom_flags);
	// Build the execution string
	$exec = "mplayer $mplayer_filename -quiet ".escapeshellcmd("$flags $str_args")." $str_custom_flags";
	// Execute the command, save output to an array, and grab
	// return code to see if mplayer throws an error.
	exec($exec, $arr, $return);
	// If mplayer dies with a positive exit code, then it failed.
	// Don't write to or delete the saved position, and die
	// with the same exit code.
	if($return !== 0) {
		stderr("mplayer died unexpectedly");
	// If the file didn't even exist, mplayer will die, and so will me
	if(!file_exists($movie)) {
		stderr("Couldn't find the filename $movie");
	// Grep out the details we need from output
	$key_position = current(preg_grep('/^ANS_TIME_POSITION\b/', $arr));
	$key_filename = current(preg_grep('/^ANS_FILENAME\b/', $arr));
	// Get the position (in seconds) of the movie
	// Original format is ANS_TIME_POSITION=123.45
	$endpos = preg_replace('/^ANS_TIME_POSITION\=/', '', $key_position);
	// Get the filename of the movie we were playing
	// Original format is ANS_FILENAME='Your_Movie.avi'
	$slave_filename = preg_replace(
		array('/^ANS_FILENAME\=\'/', '/\'$/'), 
		array('', ''),
	// If we are playing from a playlist, then the two filenames
	// will not match.  Change the filename to be what we were
	// actually playing versus what we started out playing.
	if($slave_filename != $movie && !empty($slave_filename)) {
		$movie =& $slave_filename;
		$txt = $save_files_to.basename($movie).".txt";
	// If it's a negative value, that means you've seeked
	// past/to the end of the file, so just remove the old one.
	if($endpos < 1 && file_exists($txt))
	// No end position passed to mplayer-resume, so exit quietly
	elseif(empty($endpos)) {
		stderr("No end position sent to save.");
	// Save the (positive) playback position to the file
	else {
		// Generic error message, fix your stupid permissions
		$error_msg = "Cannot save file, please check write permissions for this user in $save_files_to";
		fwrite(fopen($txt, 'w'), $endpos) or stderr($error_msg);


2.0 (2009-08-11)
	- Add --filename argument to specify filename directly, instead
	  of trying to guess what it is.
	- Add optional argument --use-filedir-conf, to include mplayer.conf
	  in local directory, and pass -include mplayer.conf to mplayer.

1.6 (2008-12-16)

	- Check exit codes on mplayer, so that if mplayer quits
	  unexpectedly, mplayer-resume won't kill the resume point.
	- Send exit codes

1.5 (2008-01-12)
	- Allow spaces in filenames.  Use mplayer-resume "filename"
	- Get the filename from MPlayer on exit, and use that to save
	the file to.  Useful for playlists.  See README.

1.3 (2006-09-15)

	- Call env instead of php directly
	- Get $HOME environment variable to save files to


	- Documentation updates