function __buildVideo() { $extension = $this->_options['DecoderVideoExtensionInter']; $video_path = $this->_buildDir . 'build.' . $extension; $pre_cmds = array(); $cmds = array(); $switches = switchesFromString($this->_options['DecoderSwitchesInter']); // override any video codec set, since we're using intermediate video format //if (! empty($switches['vcodec'])) unset($switches['vcodec']); $options = ''; $options .= ' -r ' . $this->_options['DecoderFPS']; //if (empty($switches['vcodec'])) $options .= ' -vcodec ' . $this->_options['DecoderVideoCodec']; if (empty($switches['b'])) { $options .= ' -b ' . (empty($this->_options['DecoderVideoBitrateInter']) ? $this->_options['DecoderVideoBitrate'] : $this->_options['DecoderVideoBitrateInter']) . 'k'; } if ($switches) { $options .= ' ' . stringFromSwitches($switches); } $zero = floatval(0); $cur_time = $zero; $z = sizeof($this->__mashData['timespans']); for ($i = 0; $i < $z; $i++) { if (floatgtr($this->__mashData['timespans'][$i][0], $cur_time)) { // first timespan doesn't start where the last left off, so there is something between $visual_cmds = $this->__buildVisuals($cur_time, $this->__mashData['timespans'][$i][0]); $this->log('building visuals ' . print_r($visual_cmds, 1)); $cmds = array_merge($cmds, $visual_cmds); } $cmd = ''; $cmd .= $this->_options['PathFFmpeg']; $cur_time = $this->__mashData['timespans'][$i][1]; $cmd .= ' -i ' . $this->_buildDir . 'build/' . $i . '-%' . strlen($this->__mashData['timespan_frame_count']) . 'd.jpg'; $cmd .= ' -t ' . ($this->__mashData['timespans'][$i][1] - $this->__mashData['timespans'][$i][0]); $cmds[] = $cmd; //$this->log('building flash ' . $cmd); } if (!floatcmp($cur_time, $this->__mashData['duration'])) { // last timespan doesn't end the mash, so there is stuff after it $visual_cmds = $this->__buildVisuals($cur_time, $this->__mashData['duration']); //$this->log('building trailing visuals ' . print_r($visual_cmds, 1)); $cmds = array_merge($cmds, $visual_cmds); } $options .= ' -f ' . $this->_options['DecoderVideoFormatInter']; $options .= ' -vcodec ' . $this->_options['DecoderVideoCodecInter']; $options .= ' -an '; $z = sizeof($pre_cmds); for ($i = 0; $i < $z; $i++) { $cmd = $pre_cmds[$i]; $result = $this->_shellExecute($cmd); $this->_progressStep('BuildFile', round(($i + 1) * 50 / $z), 'Encoding Frames'); } $z = sizeof($cmds); $files = array(); for ($i = 0; $i < $z; $i++) { $result = ''; $file_name = $this->_buildDir . 'video_' . $i . '.' . $extension; $cmd = $cmds[$i]; $files[] = $file_name; /* // single pass $cmd .= $options . ' -y ' . $file_name; $result .= $this->_shellExecute($cmd); */ // double pass $cmd .= $options . ' -pass {pass} -passlogfile ' . $this->_buildDir . 'FFMPEG2passInter.txt -y ' . $file_name; $cmd1 = str_replace('{pass}', '1', $cmd); $cmd2 = str_replace('{pass}', '2', $cmd); $result .= $this->_shellExecute($cmd1); $result .= $this->_shellExecute($cmd2); if (!file_exists($file_name) || !@filesize($file_name)) { throw new RuntimeException('Could not execute build command: ' . $cmd . "\n" . $result); } // make sure intermediate file is the right dimensions $cmd = ''; $cmd .= $this->_options['PathFFmpeg'] . ' -f ' . $this->_options['DecoderVideoFormatInter']; // need to supply codec hint $cmd .= ' -vcodec ' . $this->_options['DecoderVideoCodecInter']; $cmd .= ' -i ' . $file_name; $response = $this->_shellExecute($cmd); if (!$response) { throw new RuntimeException('Could not create intermediate file ' . $i . ': ' . $cmd); } $int_dims = ffmpeg_info_from_string('dimensions', $response); if (!$int_dims) { throw new RuntimeException('Could not determing intermediate file dimensions ' . $i . ': ' . $cmd . "\n" . $response); } if ($this->_options['DecoderDimensions'] != $int_dims) { throw new RuntimeException('Inter dimensions do not equal output dimensions ' . $i . ' ' . $int_dims); } $this->_progressStep('BuildFile', round(($i + 1) * 50 / $z), 'Encoding Video'); } if ($files) { // concat the files if (sizeof($files) > 1) { $cmd = 'cat ' . join(' ', $files) . ' > ' . $video_path; $result = $this->_shellExecute($cmd, ' 2>&1', 1); if (!file_exists($video_path)) { throw new RuntimeException('Could not merge intermediate files: ' . $cmd . "\n" . $result); } } else { rename($files[0], $video_path); } } return $video_path; }
function __buildSequence($file_path) { $this->_progressStep('EncodeVideo', 5, 'Encoding Video'); if (isset($this->_options['EncoderExtension'])) { $options = array(); $orig_dimensions = get_file_info('dimensions', $file_path); if (!$orig_dimensions) { throw new RuntimeException('Could not read dimensions: ' . $file_path); } $target_dimensions = scale_proud($orig_dimensions, $this->_options['EncoderDimensions']); if (!$target_dimensions) { $target_dimensions = $this->_options['EncoderDimensions']; } $target_size = explode('x', $target_dimensions); $options['bitrate'] = round($this->_options['EncoderImageQuality'] / 100 * ($target_size[0] * $target_size[1] * 3 * $this->_options['EncoderFPS'] / 1024)); $options['dimensions'] = $target_dimensions; $options['dimensions_dir'] = $this->_options['EncoderDimensions']; $switches = switchesFromString($this->_options['EncoderSwitches']); $cached_frames = cache_file_frames($file_path, $this->_options['EncoderFPS'], 0, -1, $options, $switches, $this->_options['PathFFmpeg']); if (!$cached_frames) { throw new RuntimeException('Could not prepare to cache image sequence: ' . $file_path); } if (!empty($this->_options['Verbose']) && !empty($cached_frames['command'])) { $this->log($cached_frames['command'] . "\n" . $cached_frames['result']); } if (!$cached_frames['files']) { throw new RuntimeException('Could not cache image sequence: ' . $file_path); } $this->_progressStep('EncodeVideo', 100, 'Encoded Video'); } }