コード例 #1
0
ファイル: mime.video.php プロジェクト: kailIII/liberty
/**
 * Convert a stored video file to flashvideo
 *
 * @param array $pParamHash
 * @access public
 * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
 */
function mime_video_converter(&$pParamHash, $pOnlyGetParameters = FALSE)
{
    global $gBitSystem;
    // video conversion can take a while
    ini_set("max_execution_time", "1800");
    $ret = FALSE;
    if (@BitBase::verifyId($pParamHash['attachment_id'])) {
        // we might have some attachment preferences set if this is an update
        LibertyMime::expungeAttachmentPreferences($pParamHash['attachment_id']);
        // these are set in the liberty plugin admin screen
        $ffmpeg = trim($gBitSystem->getConfig('ffmpeg_path', shell_exec('which ffmpeg')));
        $width = trim($gBitSystem->getConfig('mime_video_width', 320));
        $begin = date('U');
        $log = $actionLog = array();
        if (!is_executable($ffmpeg)) {
            $log['time'] = date('Y-M-d - H:i:s O');
            $log['duration'] = 0;
            $log['message'] = 'ERROR: ffmpeg does not seem to be available on your system at: ' . $ffmpeg . ' Please set the path to ffmpeg in the liberty plugin administration screen.';
            $actionLog['log_message'] = "ERROR: ffmpeg does not seem to be available on your system at: '{$ffmpeg}' Please set the path to ffmpeg in the liberty plugin administration screen.";
        } else {
            // this is the codec we'll use - currently this might be: flv, h264, h264-2pass
            $codec = $gBitSystem->getConfig("mime_video_video_codec", "flv");
            $source = STORAGE_PKG_PATH . $pParamHash['upload']['dest_branch'] . $pParamHash['upload']['name'];
            $destPath = dirname($source);
            // set some default values if ffpeg-php isn't available or fails
            $default['aspect'] = 4 / 3;
            $default['video_width'] = $width;
            $default['video_height'] = round($width / 4 * 3);
            $default['size'] = "{$default['video_width']}x{$default['video_height']}";
            $default['offset'] = '00:00:10';
            if (extension_loaded('ffmpeg')) {
                // we silence these calls since they might spew errors
                $movie = @new ffmpeg_movie($source);
                $info = array('vcodec' => @$movie->getVideoCodec(), 'duration' => round(@$movie->getDuration()), 'width' => @$movie->getFrameWidth(), 'height' => @$movie->getFrameHeight(), 'video_bitrate' => @$movie->getVideoBitRate(), 'acodec' => @$movie->getAudioCodec(), 'audio_bitrate' => @$movie->getAudioBitRate(), 'audio_samplerate' => @$movie->getAudioSampleRate());
                // make sure audio sample rate is valid
                if (!empty($info['audio_samplerate']) && !in_array($info['audio_samplerate'], array(11025, 22050, 44100))) {
                    unset($info['audio_samplerate']);
                }
            } else {
                // alternative method using ffmpeg to fetch source dimensions
                $command = "{$ffmpeg} -i " . escapeshellarg($source) . ' 2>&1';
                exec($command, $output, $status);
                if (!preg_match('/Stream #(?:[0-9\\.]+)(?:.*)\\: Video: (?P<videocodec>.*) (?P<width>[0-9]*)x(?P<height>[0-9]*)/', implode('\\n', $output), $matches)) {
                    preg_match('/Could not find codec parameters \\(Video: (?P<videocodec>.*) (?P<width>[0-9]*)x(?P<height>[0-9]*)\\)/', implode('\\n', $output), $matches);
                }
                if (!empty($matches['width']) && !empty($matches['height'])) {
                    $info['width'] = $matches['width'];
                    $info['height'] = $matches['height'];
                }
            }
            // our player supports flv and h264 so we might as well use the default
            if (!$gBitSystem->isFeatureActive('mime_video_force_encode') && !empty($info) && ($info['vcodec'] == 'h264' && (empty($info['acodec']) || $info['acodec'] == 'mpeg4aac' || $info['acodec'] == 'aac') || $info['vcodec'] == 'flv' && (empty($info['acodec']) || $info['acodec'] == 'mp3'))) {
                // work out what the target filename is
                $extension = $info['vcodec'] == "flv" ? "flv" : "mp4";
                $dest_file = $destPath . "/flick.{$extension}";
                // if the video can be processed by ffmpeg-php, width and height are greater than 1
                if (!empty($info['width']) && $info['width'] > 1) {
                    $info['aspect'] = $info['width'] / $info['height'];
                    $info['offset'] = strftime("%T", round($info['duration'] / 5 - 60 * 60));
                } else {
                    $info = $default;
                }
                // store prefs and create thumbnails
                LibertyMime::expungeMetaData($pParamHash['attachment_id']);
                LibertyMime::storeMetaData($pParamHash['attachment_id'], 'Video', $info);
                mime_video_create_thumbnail($source, $info['offset']);
                if (!is_file($dest_file) && !link($source, $dest_file)) {
                    copy($source, $dest_file);
                }
                mime_video_fix_streaming($dest_file);
                $log['message'] = 'SUCCESS: Converted to flash video';
                $actionLog['log_message'] = "Video file was successfully uploaded and thumbnails extracted.";
                $ret = TRUE;
            } else {
                // work out what the target filename is
                $extension = $codec == "flv" ? "flv" : "mp4";
                $dest_file = $destPath . "/flick.{$extension}";
                // if the video can be processed by ffmpeg-php, width and height are greater than 1
                if (!empty($info['width']) && $info['width'] > 1) {
                    // reset some values to reduce video size
                    if ($info['width'] < $width) {
                        $width = $info['width'];
                    }
                    // here we calculate the size and aspect ratio of the output video
                    $size_ratio = $width / $info['width'];
                    $info['aspect'] = $info['width'] / $info['height'];
                    $info['video_width'] = $width;
                    $info['video_height'] = round($size_ratio * $info['height']);
                    // height of video needs to be an even number
                    if ($info['video_height'] % 2) {
                        $info['video_height']++;
                    }
                    $info['size'] = "{$info['video_width']}x{$info['video_height']}";
                } else {
                    $info = $default;
                }
                // transfer settings to vars for easy manipulation for various APIs of ffmpeg
                $audio_bitrate = $gBitSystem->getConfig('mime_video_audio_bitrate', 32000) / 1000 . 'kb';
                $audio_samplerate = $gBitSystem->getConfig('mime_video_audio_samplerate', 22050);
                $video_bitrate = $gBitSystem->getConfig('mime_video_video_bitrate', 160000) / 1000 . 'kb';
                $acodec_mp3 = $gBitSystem->getConfig('ffmpeg_mp3_lib', 'libmp3lame');
                $me_param = $gBitSystem->getConfig('ffmpeg_me_method', 'me');
                if ($codec == "h264") {
                    $parameters = " -i '{$source}'" . " -acodec libfaac" . " -ab {$audio_bitrate}" . " -ar {$audio_samplerate}" . " -vcodec libx264" . " -b {$video_bitrate}" . " -bt {$video_bitrate}" . " -s " . $info['size'] . " -aspect " . $info['aspect'] . " -flags +loop -cmp +chroma -refs 1 -coder 0 -me_range 16 -g 300 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -maxrate 10M -bufsize 10M -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -level 30" . " -partitions +parti4x4+partp8x8+partb8x8 -{$me_param} epzs -subq 5 -trellis 1" . " -y '{$dest_file}'";
                } elseif ($codec == "h264-2pass") {
                    // it is not possible to pass in the path for the x264 log file and it is always generated in the working dir.
                    $cwd = getcwd();
                    chdir(dirname($dest_file));
                    $passlogfile = dirname($dest_file) . "/ffmpeg2pass";
                    // pass 1
                    $parameters = " -i '{$source}'" . " -an" . " -pass 1" . " -passlogfile {$passlogfile}" . " -vcodec libx264" . " -b {$video_bitrate}" . " -bt {$video_bitrate}" . " -s " . $info['size'] . " -aspect " . $info['aspect'] . " -flags +loop -cmp +chroma -refs 1 -coder 0 -me_range 16 -g 300 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -bf 16 -maxrate 10M -bufsize 10M -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4 -level 30" . " -partitions 0 -{$me_param} epzs -subq 1 -trellis 0" . " -y '{$dest_file}'";
                    // pass 2
                    $parameters2 = " -i '{$source}'" . " -acodec libfaac" . " -ab {$audio_bitrate}" . " -ar {$audio_samplerate}" . " -pass 2" . " -passlogfile {$passlogfile}" . " -vcodec libx264" . " -b {$video_bitrate}" . " -bt {$video_bitrate}" . " -s " . $info['size'] . " -aspect " . $info['aspect'] . " -flags +loop -cmp +chroma -me_range 16 -g 250 -keyint_min 25 -sc_threshold 40 -i_qfactor 0.71 -rc_eq 'blurCplx^(1-qComp)' -qcomp 0.6 -qmin 10 -qmax 51 -qdiff 4" . " -partitions +parti8x8+parti4x4+partp8x8+partp4x4+partb8x8 -flags2 +brdo+dct8x8+wpred+bpyramid+mixed_refs -{$me_param} epzs -subq 7 -trellis 1 -refs 6 -bf 16 -directpred 3 -b_strategy 1 -bidir_refine 1 -coder 1" . " -y '{$dest_file}'";
                } else {
                    $parameters = " -i '{$source}'" . " -acodec {$acodec_mp3}" . " -ab {$audio_bitrate}" . " -ar {$audio_samplerate}" . " -f flv" . " -b {$video_bitrate}" . " -bt {$video_bitrate}" . " -s " . $info['size'] . " -aspect " . $info['aspect'] . " -y '{$dest_file}'";
                }
                if ($pOnlyGetParameters) {
                    return $parameters;
                } else {
                    // we keep the output of this that we can store it to the error file if we need to do so
                    $debug = shell_exec("{$ffmpeg} {$parameters} 2>&1");
                    if (!empty($parameters2)) {
                        $debug .= shell_exec("{$ffmpeg} {$parameters2} 2>&1");
                        // change back to whence we came
                        chdir($cwd);
                    }
                }
                // make sure the conversion was successfull
                if (is_file($dest_file) && filesize($dest_file) > 48) {
                    mime_video_fix_streaming($dest_file);
                    // try to work out a reasonable timepoint where to extract a screenshot
                    if (preg_match('!Duration: ([\\d:\\.]*)!', $debug, $time)) {
                        list($h, $m, $s) = explode(':', $time[1]);
                        $seconds = round(60 * 60 * (int) $h + 60 * (int) $m + (double) $s);
                        // we need to subract one hour from our time for strftime to return the correct value
                        $info['offset'] = strftime("%T", round($seconds / 5 - 60 * 60));
                    } else {
                        $info['offset'] = "00:00:10";
                    }
                    // store some video specific settings
                    LibertyMime::expungeMetaData($pParamHash['attachment_id']);
                    LibertyMime::storeMetaData($pParamHash['attachment_id'], 'Video', $info);
                    // since the flv conversion worked, we will create a preview screenshots to show.
                    mime_video_create_thumbnail($dest_file, $info['offset']);
                    $log['message'] = 'SUCCESS: Converted to flash video';
                    $actionLog['log_message'] = "Converted to flashvideo in " . (date('U') - $begin) . " seconds";
                    $ret = TRUE;
                } else {
                    // remove unsuccessfully converted file
                    @unlink($dest_file);
                    $log['message'] = "ERROR: The video you uploaded could not be converted by ffmpeg.\nDEBUG OUTPUT:\n\n" . $debug;
                    $actionLog['log_message'] = "Video could not be converted to flashvideo. An error dump was saved to: " . $destPath . '/error';
                    // write error message to error file
                    $h = fopen($destPath . "/error", 'w');
                    fwrite($h, "{$ffmpeg} {$parameters}\n\n{$debug}");
                    fclose($h);
                }
                @unlink($destPath . '/processing');
            }
        }
        $log['time'] = date('d/M/Y:H:i:s O');
        $log['duration'] = date('U') - $begin;
        // we'll insert some info into the database for reference
        $actionLog['content_id'] = $pParamHash['content_id'];
        $actionLog['title'] = "Uploaded file: {$pParamHash['upload']['name']} [Attchment ID: {$pParamHash['attachment_id']}]";
        // if this all goes t**s up, we'll know why
        $pParamHash['log'] = $log;
        // we'll add an entry in the action logs
        LibertyContent::storeActionLogFromHash(array('action_log' => $actionLog));
        // return the log
        $pParamHash['log'] = $log;
    }
    return $ret;
}
コード例 #2
0
ファイル: mime.audio.php プロジェクト: kailIII/liberty
/**
 * mime_audio_converter 
 * 
 * @param array $pParamHash 
 * @access public
 * @return TRUE on success, FALSE on failure - mErrors will contain reason for failure
 */
function mime_audio_converter(&$pParamHash)
{
    global $gBitSystem;
    // audio conversion can take a while
    ini_set("max_execution_time", "1800");
    $ret = FALSE;
    $log = array();
    $source = STORAGE_PKG_PATH . $pParamHash['upload']['dest_branch'] . $pParamHash['upload']['name'];
    $destPath = dirname($source);
    if (@BitBase::verifyId($pParamHash['attachment_id'])) {
        $pattern = "#.*\\.(mp3|m4a)\$#i";
        if (!$gBitSystem->isFeatureActive('mime_audio_force_encode') && preg_match($pattern, $pParamHash['upload']['name'])) {
            // make a copy of the original maintaining the original extension
            $dest_file = $destPath . '/bitverted.' . preg_replace($pattern, "\$1", strtolower($pParamHash['upload']['name']));
            if (!is_file($dest_file) && !link($source, $dest_file)) {
                copy($source, $dest_file);
            }
            $ret = TRUE;
        } else {
            // TODO: have a better mechanism of converting audio to mp3. ffmpeg works well as long as the source is 'perfect'
            //       there are many audiofiles that can't be read by ffmpeg but by other tools like flac, faac, oggenc
            //       mplayer is very good, but has a lot of dependencies and not many servers have it installed
            //       also, using mplayer is a 2 step process: decoding and encoding
            // if we convert audio, we always make an mp3
            $dest_file = $destPath . '/bitverted.mp3';
            if (!($ret = mime_audio_converter_ffmpeg($pParamHash, $source, $dest_file))) {
                // fall back to using slower mplayer / lame combo
                $ret = mime_audio_converter_mplayer_lame($pParamHash, $source, $dest_file);
            }
        }
        // if the conversion was successful, we'll copy the tags to the new mp3 file and import data to meta tables
        if ($ret == TRUE) {
            $log['success'] = 'Successfully converted to mp3 audio';
            // now that we have a new mp3 file, we might as well copy the tags accross in case someone downloads it
            require_once UTIL_PKG_PATH . 'getid3/getid3/getid3.php';
            $getID3 = new getID3();
            // we silence this since this will spew lots of ugly errors when using UTF-8 and some odd character in the file ID
            $meta = @$getID3->analyze($source);
            getid3_lib::CopyTagsToComments($meta);
            // write tags to new mp3 file
            if ($errors = mime_audio_update_tags($dest_file, $meta['comments'])) {
                $log['tagging'] = $errors;
            }
            // getID3 returns everything in subarrays - we want to store everything in [0]
            foreach ($meta['comments'] as $key => $comment) {
                $store[$key] = $comment[0];
            }
            $store['playtimeseconds'] = $meta['playtime_seconds'];
            $store['playtimestring'] = $meta['playtime_string'];
            // make sure we remove previous entries first
            LibertyMime::expungeMetaData($pParamHash['attachment_id']);
            if (!LibertyMime::storeMetaData($pParamHash['attachment_id'], 'ID3', $store)) {
                $log['store_meta'] = "There was a problem storing the meta data in the database";
            }
            // if we have an image in the id3v2 tag, we might as well do something with it
            // we'll simply use the first image we can find in the file
            if (!empty($meta['id3v2']['APIC'][0]['data'])) {
                $image = $meta['id3v2']['APIC'][0];
            } elseif (!empty($meta['id3v2']['PIC'][0]['data'])) {
                $image = $meta['id3v2']['PIC'][0];
            }
            if (!empty($image)) {
                // write the image to temp file for us to process
                $tmpfile = str_replace("//", "/", tempnam(TEMP_PKG_PATH, LIBERTY_PKG_NAME));
                if ($fp = fopen($tmpfile, 'w')) {
                    fwrite($fp, $image['data']);
                    fclose($fp);
                    $fileHash['type'] = $image['mime'];
                    $fileHash['source_file'] = $tmpfile;
                    $fileHash['dest_branch'] = $pParamHash['upload']['dest_branch'];
                    liberty_generate_thumbnails($fileHash);
                    // remove temp file
                    if (!empty($tmpfile) && is_file($tmpfile)) {
                        unlink($tmpfile);
                    }
                }
            }
            // TODO: when tags package is enabled add an option to add tags
            //       recommended tags might be artist and album
            // TODO: fetch album cover from amazon.com or musicbrainz.org
            //       fetch lyrics from lyricwiki.org
            //$item->mLogs['audio_converter'] = "Audio file was successfully converted to MP3.";
        }
    }
    // update log
    $pParamHash['log'] = array_merge($pParamHash['log'], $log);
    return $ret;
}