Solved

ffmpeg and php expert

Posted on 2008-09-29
15
1,415 Views
Last Modified: 2010-04-21
Hi,

      I have a php script which uses ffmpeg to convert the videos, it uses multi pass options and other technique to come up with a quality encode while keeping the size to minimum.

Problem i am having is that output flv file is giving shacking effect after every 3,4 seconds. I need help on someone who is really expert with using ffmpeg and php.

* Please note that all other aspects of the scripts are working, you will just need to find the setting which is causing this shacking picture problem and fix it.*

See the output here.
http://www.indianpad.in/video/912/Fermentation
http://www.indianpad.in/video/916/India-Driving

Stare at the video for continuous 20 seconds and you will see it shacks every 3,4 second.

I want you to check the script and see which settings is causing this, I do not want to change other things in the script. As it works perfect quality wise and size.

Thanks,
akiles
<?php
 

require('include/config.php');

require('include/function.php');
 

# Get arguments from the argv array.

# [1] ~= 47.flv

# [2] ~= 47

# [3] ~= /.../VDO_DIR/47.flv

$vid = $_SERVER['argv'][2];

$sourcefile = $_SERVER['argv'][3];
 

# Other variables.

$tempfile = "$config[FLVDO_DIR]/{$vid}x.flv";

$targetfile = "$config[FLVDO_DIR]/$vid.flv";

$logfile = "$config[LOG_DIR]/$vid.log";

$multipasslogfile = "$config[FLVDO_DIR]/$vid";
 

if ($sourcefile != '' && $vid != '') {

	$ffmpeg = new FFmpeg($config['ffmpeg'], $sourcefile, $tempfile);
 

	# Frame Size: The maximum size the encode video will have. Depending

	# on aspect ration, the encoded video will be fitted inside this frame,

	# or will be kept at its original size if it's smaller than this value.

	$ffmpeg->options->frame_size = $config['vresize_x'] . 'x' . $config['vresize_y'];
 

	# Quantizer Scale: Values between 1 and 16 are typical. 

	# The lower the value, the higher the quality the video will have.

	$ffmpeg->options->quantizer = 5;
 

	# Multipass Encoding: Enable / Disable 2 pass encoding.

	$ffmpeg->options->multipass = false;
 

	# Location to a log file FFmpeg can write to.

	$ffmpeg->options->multipass_log = $multipasslogfile;

	

	# ENCODE!

	$ffmpeg->encode_flv();
 

	# Get rid of the pass log file (FFmpeg appends "-0.log" to the given filename!).

	@unlink($multipasslogfile . '-0.log');

	

	# Inject metadata.

	exec("$config[metainject] -Uv $tempfile $targetfile");

	@unlink($tempfile);
 

	# Make thumbnails.

	video_to_frame($sourcefile, $vid);
 

	# If conversion went OK...

	if (file_exists($targetfile) && filesize($targetfile) > 0) {

		@unlink($logfile);
 

		if ($config['del_original_video'] == 1) {

			@chmod($sourcefile, 0777);

			@unlink($sourcefile);

		}

	}
 

	# Clean up.

	$picA = $config['TMP_DIR']. '/thumbs/' .$vid. '/00000001.jpg';

	$picB = $config['TMP_DIR']. '/thumbs/' .$vid. '/00000002.jpg';

	$picC = $config['TMP_DIR']. '/thumbs/' .$vid. '/00000003.jpg';

	$picD = $config['TMP_DIR']. '/thumbs/' .$vid. '/00000004.jpg';

	if(file_exists($picA)) @unlink($picA);

	if(file_exists($picB)) @unlink($picB);

	if(file_exists($picC)) @unlink($picC);

	if(file_exists($picD)) @unlink($picD);
 

	@rmdir($config['TMP_DIR']. '/thumbs/' .$vid);

}
 

class FFmpeg {

	var $source;

	var $target;
 

	var $ffmpeg;
 

	var $options;
 

	var $output;
 

	/**

	  * Constructor

	  *

	  * @params string $ffmpeg - Path to the FFmpeg executable.

	  * @params string $source - Path to the source video file.

	  * @params string $target - Path to the target FLV file.

	  */

	function FFmpeg($ffmpeg, $source, $target) {

		$this->source->path = $source;

		$this->target->path = $target;
 

		$this->ffmpeg = $ffmpeg;
 

		$this->options = new stdClass();
 

		register_shutdown_function(array($this, 'cleanup'));

	}
 

	/**

	  * Remove the log file (if any) on shutdown.

	  */

	function cleanup() {

		@unlink($this->options->multipass_log . '-0.log');

	}
 

	/**

	  * Calculate the required frame size for the video that would

	  * fit within the maximum size specified, and at the same time

	  * it will keep the appropriate ratio. Pixel and Device aspect

	  * ratios are respected, and the frame size returned will be for

	  * a video with 1:1 pixel ratio, and the same real ratio as the

	  * input video.

	  *

	  * @param string $maxframe - Maximum frame size. Ex: '320x240'.

	  * @return string - Fitted frame size. Ex: '320x180'.

	  */

	function calculate_size($maxframe) {

		# Identify the source (if it hasn't already).

		if (!$this->source->video) {

			$this->source = $this->identify($this->source);

		}
 

		$maxwidth = $this->normalize_size(array_shift(explode('x', $maxframe)));

		$maxheight = $this->normalize_size(array_pop(explode('x', $maxframe)));
 

		# Compare to source frame.

		if ($this->source->video->frame_size) {

			# Calculate the proper source frame (taking into account the pixel ratio).

			$framewidth = $this->normalize_size($this->source->video->frame_width * $this->source->video->pixel_ratio);

			$frameheight = $this->normalize_size($this->source->video->frame_height);

			$frameratio = $framewidth / $frameheight;
 

			# Check if that's smaller than the max frame, and if so, match it.

			if ($framewidth <= $maxwidth && $frameheight <= $maxheight) {

				$maxwidth = $this->normalize_size(min($maxwidth, $framewidth));

				$maxheight = $this->normalize_size(min($maxheight, $frameheight));

			}

			$maxratio = $maxwidth / $maxheight;
 

			# Adapt the size so it fits within this modified maximum size.

			if ($frameratio > $maxratio) {

				# The video is flatter/wider than the expected ratio. Fit the width and scale down the height;

				$width = $maxwidth;

				$height = $this->normalize_size($width / $this->source->video->device_ratio);

			} else {

				# The video is narrower/taller than the expected ratio. Fit the height and scale down the width;

				$height = $maxheight;

				$width = $this->normalize_size($height * $this->source->video->device_ratio);

			}
 

			# Return the adapted size.

			return $width . 'x' . $height;

		} else {

			# If the source frame size is unknown, just return the max frame,

			# and hope for the best (cross your fingers!).

			return $maxframe;

		}

	}
 

	/**

	  * Normalize a size coordinate, so it's always an even round number,

	  * as required by FFmpeg for all video sizes.

	  * Examples:

	  * 318.5 -> 318

	  * 319   -> 320

	  * 319.5 -> 320

	  * 320   -> 320

	  * 320.5 -> 320

	  * 321   -> 322

	  *

	  * @param float $size

	  * @return int

	  */

	function normalize_size($size) {

		return intval(2 * round($size / 2));

	}

	

	/**

	  * Encode to FLV. If multipass has been enabled,

	  * this same method will be called again with the second

	  * pass from within itself.

	  *

	  * @param int $pass - Pass number. Default: null - No need to worry about this, used internally only.

	  */

	function encode_flv($pass = null) {

		# Identify the source (if it hasn't already).

		if (!$this->source->container) {

			$this->source = $this->identify($this->source);

		}
 

		$options = array();
 

		# Input File

		$options['i'] = $this->source->path;
 

		# Overwrite Existing File

		$options['y'] = '';
 

		# No Verbosity.

		$options['v'] = 0;
 

		# Multi-Pass ?

		if ($this->options->multipass) {

			$options['pass'] = $pass ? $pass : 1;

			$options['passlogfile'] = $this->options->multipass_log;

		}
 

		# Audio

		if ($this->source->audio) {

			# Codec: Lame MP3

			$options['acodec'] = 'libmp3lame';
 

			# Sampling Rate: 22,050 Hz, unless source is less than that, then use 11,050.

			$options['ar'] = ($this->source->audio->frequency && $this->source->audio->frequency < 22050 ? 11025 : 22050);
 

			# Channels: mono

			$options['ac'] = 1;
 

			# Bitrate: 48k unless source is less than that, then use 24k.

			$options['ab'] = ($this->source->audio->bitrate && $this->source->audio->bitrate < 48 ? "24k" : "48k");

		}
 

		# Video

		if ($this->source->video) {

			# Codec: FLV, duh!

			$options['vcodec'] = 'flv';
 

			# Frame Size: 320x240 max, unless the source is smaller, then match it. Also scale accordingly through ratios.

			$options['s'] = $this->calculate_size($this->options->frame_size ? $this->options->frame_size : '320x240');
 

			# Frame Rate: 20 fps, unless the source is less than that, then match it.

			$options['r'] = ($this->source->video->framerate && $this->source->video->framerate < 20 ? $this->source->video->framerate : 20);
 

			# Frame Grouping (Keyframes): Every 2 seconds (will depend on framerate, since this must be number of frames).

			$options['g'] = 2 * $options['r'];

			

			# Video Quantizer: Compressor

			$options['qcomp'] = 0.6;

			

			# Video Quantizer: Blur

			$options['qblur'] = 1;
 

			# Video Quantizer: Scale

			$options['qscale'] = $this->options->quantizer ? $this->options->quantizer : 5;

			

			# Compensate Quantizer to Resolution:

			# (A 320x240 video will keep the same Q as entered above. Smaller videos will have a higher Q, and larger videos will have a smaller Q).

			$options['qscale'] *= pow((intval(array_shift(explode('x', $options['s']))) * intval(array_pop(explode('x', $options['s'])))) / (320*240), 0.5);
 

			# Clamp Quantizer to acceptable values (1-31):

			$options['qscale'] = max(1, min($options['qscale'], 31));
 

			$options['maxrate'] = '360k';

			$options['bufsize'] = '50k';
 

			# Other advanced options: Just do it!

			$options['flags'] = 'mv4+loop+gmc+mv0+umv+trell+aic+cbp+qprd'; 

				# FFmpeg r10937 complained about qpel not supported, so removing it.

				# original flags string was: 'mv4+qpel+loop+gmc+mv0+umv+trell+aic+cbp+qprd'

			$options['strict'] = 5;

			$options['pred'] = 3;

			$options['cmp'] = 3;

			$options['subcmp'] = 3;

			$options['mbcmp'] = 3;

			$options['ildctcmp'] = 3;

			$options['precmp'] = 3;

			$options['skipcmp'] = 3;

			$options['subq'] = 9;

			$options['coder'] = 5;

			$options['mbd'] = 2;

			$options['trellis'] = 10;

			$options['i_qfactor'] = 0.71;

			$options['flags2'] = 'mixed_refs+brdo+skiprd';

				# FFmpeg r10937 complained about non_linear_q not supported, so removing it.

				# original flags string was: 'mixed_refs+brdo+skiprd+non_linear_q'

			$options['partitions'] = 'parti4x4+parti8x8+partp4x4+partp8x8';

			$options['inter_matrix'] = '"16,18,20,22,24,26,28,30,18,20,22,24,26,28,30,32,20,22,24,26,28,30,32,34,22,24,26,30,32,32,34,36,24,26,28,32,34,34,36,38,26,28,30,32,34,36,38,40,28,30,32,34,36,38,42,42,30,32,34,36,38,40,42,44"';

		}

		

		# Run the FFmpeg with the options built above.

		$this->run($options, $this->target->path);
 

		# If multipass is enabled, this will call this method again

		# telling it to do the second pass now.

		if ($this->options->multipass && (!$pass || $pass == 1)) {

			$this->encode_flv(2);

		}

 	}
 

	/**

	  * Run FFmpeg with a set of options, and a target output file if needed.

	  *

	  * @param array $options - Array of options to pass as parameters. Ex: array('i' => 'v.avi', 'f' => 'flv').

	  * @param string $target - Path to the output target file. Leave null to not encode anything now.

	  * @return array - Array with the output of the command.

	  */

	function run($options, $target = null) {

		# Quote the paths, if any.

		if ($options['i']) {

			$options['i'] = '"' . $options['i'] . '"';

		}

		if ($target) {

			$target = '"' . $target . '"';

		}

		

		# Build a parameters string.

		$params = array();

		foreach ($options as $option => $value) {

			$params[] = "-$option $value";

		}

		if ($target) {

			$params[] = $target;

		}

		$params = implode(' ', $params);
 

		# The command to run, routing STDERR to STDOUT.

		$command = "$this->ffmpeg $params 2>&1";
 

		$this->output .= ">> $command \n\n";
 

		# CS: Log

		global $logfile;

		log_conversion($logfile, $command);
 

		exec($command, $output);
 

		# CS: Log

		log_conversion($logfile, implode("\n", $output));
 

		$this->output .= implode("\n", $output) . "\n\n";
 

		return $output;

	}
 

	/**

	  * Identify a video by parsing the information given by FFmpeg.

	  * The information will be stuffed into an object compatible with

	  * either $this->source or $this->target.

	  * 

	  * @param stdClass $object - The object to stuff info into.

	  * @return stdClass - The same object with all the info inserted.

	  */

	function identify($object) {

		$output = $this->run(array('i' => $object->path));
 

		$object->container = new stdClass();

		$object->video = new stdClass();

		$object->audio = new stdClass();
 

		if (is_array($output)) foreach ($output as $line) {

			$line = trim($line);

  

			# Parse File Container (1):

			if (preg_match('|^Input #([0-9]+), (.*?), from .*?|', $line, $m)) {

				# Parse Container:

				$object->container->stream = $m[1];

				$object->container->format = $m[2];

			}
 

			# Parse File Container (2):

			if (preg_match('|^Duration: ([0-9]+):([0-9]+):([0-9]+)[.]([0-9]+), start: ([0-9.]+), bitrate: (.*?)$|', $line, $m)) {

				# Parse Container:

				$object->container->length = floatval(intval(3600*intval($m[1]) + 60*intval($m[2]) + intval($m[3])) . '.' . (intval($m[4])));

				$object->container->start = floatval($m[5]);
 

				if (preg_match('|([0-9]+) kb/s|', $m[6], $mm)) {

					# Check if bitrate != 'N/A'

					$object->container->bitrate = intval($mm[1]);

				}

			}
 

			# Parse Audio Stream:

			if (preg_match('|^Stream #([0-9][.][0-9]).*?: Audio: (.*?)$|', $line, $m)) {

				# Parse Stream:

				$object->audio->stream = $m[1];
 

				$audio = explode(',', $m[2]);

				

				# Parse Codec:

				$object->audio->codec = trim(array_shift($audio));
 

				foreach ($audio as $element) {

					$element = trim($element);

					

					# Parse Frequency:

					if (preg_match('|([0-9]+) Hz|', $element, $mm)) {

						$object->audio->frequency = intval($mm[1]);

					}

					

					# Parse Bitrate:

					if (preg_match('|([0-9]+) kb/s|', $element, $mm)) {

						$object->audio->bitrate = intval($mm[1]);

					}
 

					# Parse Channels:

					if (preg_match('|stereo|', $element)) {

						$object->audio->channels = 2;

					} else if (preg_match('|mono|', $element)) {

						$object->audio->channels = 1;

					}

				}

			}
 

			# Parse Video Stream:

			if (preg_match('|^Stream #([0-9][.][0-9]).*?: Video: (.*?)$|', $line, $m)) {

				# Parse Stream:

				$object->video->stream = $m[1];
 

				$video = explode(',', $m[2]);

				

				# Parse Codec:

				$object->video->codec = trim(array_shift($video));
 

				# Parse Pixel Format:

				if (preg_match('|^yuv|', trim($video[0]))) {

					$object->video->pixelformat = trim(array_shift($video));

				}
 

				foreach ($video as $element) {

					$element = trim($element);
 

					# Parse Frame Size & Ratios:

					if (preg_match('|([0-9]+)x([0-9]+) \\[PAR ([0-9]+):([0-9]+) DAR ([0-9]+):([0-9]+)\\]|', $element, $mm)) {

						if (intval($mm[1]) > 0 && intval($mm[2]) > 0) {

							# Frame Size:

							$object->video->frame_width = intval($mm[1]);

							$object->video->frame_height = intval($mm[2]);

							$object->video->frame_size = intval($mm[1]) . 'x' . intval($mm[2]);

							

							# Pixel Aspect Ratio:

							if ((intval($mm[3]) == 0 && intval($mm[4]) == 1) || intval($mm[4]) <= 0) {

								# Pixel AR is undefined (says 0:1) or it's invalid, so it's safe to assume 1:1.

								$object->video->pixel_ratio = 1.0;

							} else {

								$object->video->pixel_ratio = (intval($mm[3]) / intval($mm[4]));

							}
 

							# Device Aspect Ratio:

							if ((intval($mm[5]) == 0 && intval($mm[6]) == 1) || intval($mm[6]) <= 0) {

								# Device AR is undefined (says 0:1) or it's invalid, so it's safe to assume it's the same as the frame.

								$object->video->device_ratio = $object->video->frame_width / $object->video->frame_height;

							} else {

								$object->video->device_ratio = (intval($mm[5]) / intval($mm[6]));

							}

						}

					}
 

					# Parse Bitrate:

					if (preg_match('|([0-9]+) kb/s|', $element, $mm)) {

						$object->video->bitrate = intval($mm[1]);

					}
 

					# Parse Framerate:

					if (preg_match('#([0-9.]+) ((tb)|(fps))[(]((r)|(c))[)]#', $element, $mm)) {

						$object->video->framerate = intval($mm[1]);

					}

				}

			}

		}
 

		return $object;

	}

}
 

?>

Open in new window

0
Comment
Question by:akiles99
  • 7
  • 6
  • 2
15 Comments
 
LVL 25

Expert Comment

by:Squinky
ID: 22605064
What you're seeing is normal for lossy video with keyframes. Every couple of seconds it encodes a full frame, and all the frames between them are just difference frames. After a while you can find that quality degrades. More keyframes makes for higher quality and better random-access performance, at the expense of data rate. In the driving example it would benefit from automatic keyframes (because the frame differences are generally small). I can't find an ffmpeg option for automatic keyframes, but you could try setting the -g option (gop length) to something like 60 or 100 to reduce keyframe rate. I also suggest you enable 2-pass encoding and increase the quality level a bit.
0
 

Author Comment

by:akiles99
ID: 22605543
setting the -g option (gop length) to something like 60 or 100.

But i cant find this in the code.
0
 
LVL 25

Expert Comment

by:Squinky
ID: 22605709
It's determined from frame rate in that ffmpeg class:

$options['g'] = 2 * $options['r'];

Try changing that to:

$options['g'] = 100;

As you make it bigger, the 'shaking' effect will happen less often, but you may find quality deteriorates and it will make it slower to jump to random points in the clip. You need to experiment with the quality setting at the same time.
0
 

Author Comment

by:akiles99
ID: 22605740
You need to experiment with the quality setting at the same time.

Please explain  this.
0
 
LVL 25

Accepted Solution

by:
Squinky earned 500 total points
ID: 22605785
By making keyframes further apart, quality may suffer, so you need to make the $ffmpeg->options->quantizer value smaller to improve image quality - try 3 or 4 and see how it looks. Reducing keyframe rate usually lowers data rate, so you can usually get away with increasing the quality a bit without an overall increase in data rate.
0
 

Author Comment

by:akiles99
ID: 22608718
I tried the two pass encoding but what happened was that it took around 30 mins to encode a 3 min video which i think will kill the server if i upload 20 videos a day only. Also first pass went pretty fine and while encoding the second pass i saw that output flv size isn't increasing and at the last it came out as 0byte flv.

Though script has 2 pass option and it worked when i used it previously.
0
 
LVL 25

Expert Comment

by:Squinky
ID: 22609744
Welcome to the world of video encoding. If you want it to look good, you have to spend more time on encoding, and good encoding takes time. Conversely, you can encode quickly if you can put up with it not looking so good. There is no magic solution. Why do you think most clips on youtube look so bad?

If anything, I'd expect the file to get smaller on the second pass. The first pass builds a data rate profile of the movie so that it knows in advance how much to compress each frame. The second pass can then fit the data rate much more accurately, resulting in higher quality, or more to the point, more efficient utilisation of the available data rate, i.e. the movie will stay the same size, but the compression quality will be better.

To answer your original question, just increasing that g parameter will make the 'shaking' effect happen less often. The tradeoff is that the overall video quality will generally be lower.
0
IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

 
LVL 25

Expert Comment

by:Squinky
ID: 22622561
With g=100 you should expect a forced keyframe every 4 sec at 25fps (slightly more often at 30fps), and that's pretty much what you're seeing. Without automatic keyframes all you can do is make g bigger to make the keyframe jump happen less often, but as I said this will make random access within the clip worse, and with a low quality setting the keyframe jump will be more obvious when it happens. Automatic keyframes means that it waits until there is a large change in the image (e.g. a cut to a different camera angle) and places a keyframe then. It seems that ffmpeg has no support for automatic keyframes, so if you want to avoid the problem properly, you just need to use a better encoder that does. Try something like Sorenson Squeeze.
0
 

Author Comment

by:akiles99
ID: 22622717
Would you mind giving me little more info on "Sorenson Squeeze" I heard this for the first time.

How does thin encoder works ? Can you make it work for clipshare ? Do I have to pay for license or you can arrange me encoder :P ? How is your experience with this product ? Can we upgrade/modify it at later stage if we need ? A little more detail will be appreciated.
0
 

Author Comment

by:akiles99
ID: 22622804
My purpose of making this custom ffmpeg script was to enhance the quality of encoded videos while keeping the size to as low as possible. Default clipshare conversion method uses mencoder and is not giving me better results.

Can you use the methodology i applied with this ffmpeg script to mencoder and modify it to produce better results ? I am attaching default clipshare convert script so that you can see how it works.
<?php

require('include/config.php');

require('include/function.php');
 

// Get arguments from the argv array 

$vdoname = $_SERVER['argv']['1']; 

$vid = $_SERVER['argv']['2']; 

$ff = $_SERVER['argv']['3']; 
 

if( ( $vdoname != '' ) && ( $vid != '' ) && ( $ff != '') ) {

    $ext                = strtolower(substr($vdoname, strrpos($vdoname, '.') + 1));

    $ofps               = ( $ext == 'wmv' ) ? '-ofps 25000/1001' : NULL;

    $mencoder_version   = '1.0rc1';

    exec($config['mencoder'], $mencoder_check);

    if ( isset($mencoder_check['0']) ) {

        if ( !strstr($mencoder_check['0'], 'MEncoder 1.0rc1') ) {

            $mencoder_version = '1.0rc2';

        }

    }

    $options            = ( $mencoder_version == '1.0rc1' ) ? '-lavfopts i_certify_that_my_video_stream_does_not_use_b_frames' : NULL;

        

	if( $config['vresize'] == 1) {

		$encodecommand="$config[mencoder] $config[VDO_DIR]/$vdoname -o $config[FLVDO_DIR]/".$vid."x.flv -of lavf -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=$config[vbitrate]:mbd=2:mv0:trell:v4mv:keyint=10:cbp:last_pred=3 -vop scale=$config[vresize_x]:$config[vresize_y] -srate $config[sbitrate] $options $ofps";

	} else {

		$encodecommand="$config[mencoder] $config[VDO_DIR]/$vdoname -o $config[FLVDO_DIR]/".$vid."x.flv -of lavf -oac mp3lame -lameopts abr:br=56 -ovc lavc -lavcopts vcodec=flv:vbitrate=$config[vbitrate]:mbd=2:mv0:trell:v4mv:keyint=10:cbp:last_pred=3 -srate $config[sbitrate] $options $ofps";

	}

	

	log_conversion($config['LOG_DIR']. '/' .$vid. '.log', $encodecommand);

	

	$ext = strtolower(substr($vdoname, strrpos($vdoname, '.') + 1));

	if ( $config['vresize'] != 1 && $ext == 'flv' )

		copy($ff, $config['FLVDO_DIR']. '/' .$vid. 'x.flv');

	else

		exec($encodecommand. ' 2>&1', $output);

	

	log_conversion($config['LOG_DIR']. '/' .$vid. '.log', implode("\n", $output));

	

	//update flv metatags

	exec($config['metainject']. ' -Uv ' .$config['FLVDO_DIR']. '/' .$vid. 'x.flv ' .$config['FLVDO_DIR']. '/' .$vid. '.flv');
 

	//remove temporary

	@unlink($config['FLVDO_DIR']. '/' .$vid. 'x.flv');
 

	//create thumbnails

	video_to_frame($ff, $vid);

	

	//delete log if conversion was successfuly

	if ( file_exists($config['FLVDO_DIR']. '/' .$vid. '.flv') && filesize($config['FLVDO_DIR']. '/' .$vid. '.flv') > 10 )

		@unlink($config['TMP_DIR']. '/logs/' .$vid. '.log');

	

	//delete original video

	if($config['del_original_video'] == 1)  {

    		if(filesize($config['FLVDO_DIR']. '/' .$vid. '.flv') > 100 && file_exists($config['FLVDO_DIR']. '/' .$vid. '.flv')) {

    			$del_upvid = $config['VDO_DIR']. '/' .$vdoname; 

    			@chmod($del_upvid, 0777); 

    			@unlink($del_upvid);

    		} 

	}
 

	// Delete Tmp Files

	$picA = $config['TMP_DIR']. '/thumbs/' .$vid. '/00000001.jpg';

	$picB = $config['TMP_DIR']. '/thumbs/' .$vid. '/00000002.jpg';

	$picC = $config['TMP_DIR']. '/thumbs/' .$vid. '/00000003.jpg';

	$picD = $config['TMP_DIR']. '/thumbs/' .$vid. '/00000004.jpg';

	if(file_exists($picA)) @unlink($picA);

	if(file_exists($picB)) @unlink($picB);

	if(file_exists($picC)) @unlink($picC);

	if(file_exists($picD)) @unlink($picD);
 

	@rmdir($config['TMP_DIR']. '/thumbs/' .$vid);

}

?>  

Open in new window

0
 
LVL 25

Expert Comment

by:Squinky
ID: 22623230
Sorenson Squeeze is a commercial product, but you should find it easier to use. http://www.sorensonmedia.com/products/?pageID=1&ppc=3

Much like ffmpeg, mencoder has options for keyframing. I'm busy right now, but you can look at the manual pages.
0
 

Expert Comment

by:agoel96
ID: 22656665
Squinky,

Is there a good commercial solution available for Linux?  

Are you familiar with mobile video formats?  It seems like you are a ffmpeg pro. Would you have time to take on some paid contract work?  If so, please email me at agoel96@gmail.com
0
 
LVL 25

Expert Comment

by:Squinky
ID: 22657566
I'm not really an ffmpeg expert, I just used to deal with lots of video for CD-ROM - in many ways video on the web is where video for CD was 12 years ago (though the codecs are better), and everyone is making the same mistakes all over again! As far as I can see, ffmpeg has no automatic keyframing control, though it's possibly something that can be imposed by higher-level apps that wrap its functionality.

The only formats I'd consider to be "mobile" are 3gpp and possibly H.264 on very new devices. I'd use quicktime for processing stuff just because the tools are generally very good and easy to use, and steer well clear of wmv.
0
 

Expert Comment

by:agoel96
ID: 22659090
Squinky, My need is to be able to take a source video and transcode it into a variety of mobile formats to support playback on most phones and carriers.

Would anyone here on EE have the expertise to assist or direct me somewhere? This would have to be a server-based solution because it needs to be automated.
0
 

Author Closing Comment

by:akiles99
ID: 31501296
Thanks
0

Featured Post

IT, Stop Being Called Into Every Meeting

Highfive is so simple that setting up every meeting room takes just minutes and every employee will be able to start or join a call from any room with ease. Never be called into a meeting just to get it started again. This is how video conferencing should work!

Join & Write a Comment

Popularity Can Be Measured Sometimes we deal with questions of popularity, and we need a way to collect opinions from our clients.  This article shows a simple teaching example of how we might elect a favorite color by letting our clients vote for …
Part of the Global Positioning System A geocode (https://developers.google.com/maps/documentation/geocoding/) is the major subset of a GPS coordinate (http://en.wikipedia.org/wiki/Global_Positioning_System), the other parts being the altitude and t…
The viewer will learn how to count occurrences of each item in an array.
The viewer will learn how to create a basic form using some HTML5 and PHP for later processing. Set up your basic HTML file. Open your form tag and set the method and action attributes.: (CODE) Set up your first few inputs one for the name and …

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now