public function register() { $this->opo_config = Configuration::load(); $vs_external_app_config_path = $this->opo_config->get('external_applications'); $this->opo_external_app_config = Configuration::load($vs_external_app_config_path); $this->ops_path_to_ffmpeg = $this->opo_external_app_config->get('ffmpeg_app'); $this->ops_mediainfo_path = $this->opo_external_app_config->get('mediainfo_app'); $this->opb_mediainfo_available = caMediaInfoInstalled($this->ops_mediainfo_path); $this->opb_ffmpeg_available = caMediaPluginFFfmpegInstalled($this->ops_path_to_ffmpeg); $this->info["INSTANCE"] = $this; return $this->info; }
public function write($filepath, $mimetype, $pa_options = null) { if (!$this->handle) { return false; } if (!($ext = $this->info["EXPORT"][$mimetype])) { # this plugin can't write this mimetype return false; } # is mimetype valid? switch ($mimetype) { # ------------------------------------ case 'image/jpeg': $vn_preview_width = $this->properties["width"]; $vn_preview_height = $this->properties["height"]; if (caMediaPluginFFfmpegInstalled($this->ops_path_to_ffmpeg) && $this->handle["mime_type"] != "application/x-shockwave-flash") { if (($vn_start_secs = $this->properties["duration"] / 8) > 120) { $vn_start_secs = 120; // always take a frame from the first two minutes to ensure performance (ffmpeg gets slow if it has to seek far into a movie to extract a frame) } exec($this->ops_path_to_ffmpeg . " -i " . caEscapeShellArg($this->filepath) . " -f image2 -ss " . $vn_start_secs . " -t 0.04 -s {$vn_preview_width}x{$vn_preview_height} -y " . caEscapeShellArg($filepath . "." . $ext) . (caGetOSFamily() == OS_POSIX ? " 2> /dev/null" : ""), $va_output, $vn_return); if ($vn_return < 0 || $vn_return > 1 || !@filesize($filepath . "." . $ext)) { @unlink($filepath . "." . $ext); // try again, with -ss 1 (seems to work consistently on some files where other -ss values won't work) exec($this->ops_path_to_ffmpeg . " -i " . caEscapeShellArg($this->filepath) . " -f image2 -ss " . $vn_start_secs . " -t 1 -s {$vn_preview_width}x{$vn_preview_height} -y " . caEscapeShellArg($filepath . "." . $ext) . (caGetOSFamily() == OS_POSIX ? " 2> /dev/null" : ""), $va_output, $vn_return); } if ($vn_return < 0 || $vn_return > 1 || !@filesize($filepath . "." . $ext)) { @unlink($filepath . "." . $ext); // don't throw error as ffmpeg cannot generate frame still from all file } } $this->properties["mimetype"] = $mimetype; $this->properties["typename"] = isset($this->typenames[$mimetype]) ? $this->typenames[$mimetype] : $mimetype; break; # ------------------------------------ # ------------------------------------ case 'image/png': $vn_preview_width = $this->properties["width"]; $vn_preview_height = $this->properties["height"]; if (caMediaPluginFFfmpegInstalled($this->ops_path_to_ffmpeg) && $this->handle["mime_type"] != "application/x-shockwave-flash") { if (($vn_start_secs = $this->properties["duration"] / 8) > 120) { $vn_start_secs = 120; // always take a frame from the first two minutes to ensure performance (ffmpeg gets slow if it has to seek far into a movie to extract a frame) } exec($this->ops_path_to_ffmpeg . " -i " . caEscapeShellArg($this->filepath) . " -vcodec png -ss " . $vn_start_secs . " -t 0.04 -s {$vn_preview_width}x{$vn_preview_height} -y " . caEscapeShellArg($filepath . "." . $ext) . (caGetOSFamily() == OS_POSIX ? " 2> /dev/null" : ""), $va_output, $vn_return); if ($vn_return < 0 || $vn_return > 1 || !@filesize($filepath . "." . $ext)) { @unlink($filepath . "." . $ext); // try again, with -ss 1 (seems to work consistently on some files where other -ss values won't work) exec($this->ops_path_to_ffmpeg . " -i " . caEscapeShellArg($this->filepath) . " -vcodec png -ss " . $vn_start_secs . " -t 1 -s {$vn_preview_width}x{$vn_preview_height} -y " . caEscapeShellArg($filepath . "." . $ext) . (caGetOSFamily() == OS_POSIX ? " 2> /dev/null" : ""), $va_output, $vn_return); } if ($vn_return < 0 || $vn_return > 1 || !@filesize($filepath . "." . $ext)) { @unlink($filepath . "." . $ext); // don't throw error as ffmpeg cannot generate frame still from all file } } $this->properties["mimetype"] = $mimetype; $this->properties["typename"] = isset($this->typenames[$mimetype]) ? $this->typenames[$mimetype] : $mimetype; break; # ------------------------------------ # ------------------------------------ case 'video/x-flv': if (caMediaPluginFFfmpegInstalled($this->ops_path_to_ffmpeg)) { $vn_video_bitrate = $this->get('video_bitrate'); if ($vn_video_bitrate < 20000) { $vn_video_bitrate = 256000; } $vn_audio_bitrate = $this->get('audio_bitrate'); if ($vn_audio_bitrate < 8000) { $vn_audio_bitrate = 32000; } $vn_audio_sample_freq = $this->get('audio_sample_freq'); if ($vn_audio_sample_freq != 44100 && $vn_audio_sample_freq != 22050 && $vn_audio_sample_freq != 11025) { $vn_audio_sample_freq = 44100; } exec($vs_cmd = $this->ops_path_to_ffmpeg . " -i " . caEscapeShellArg($this->filepath) . " -f flv -b " . intval($vn_video_bitrate) . " -ab " . intval($vn_audio_bitrate) . " -ar " . intval($vn_audio_sample_freq) . " -y " . caEscapeShellArg($filepath . "." . $ext) . (caGetOSFamily() == OS_POSIX ? " 2> /dev/null" : ""), $va_output, $vn_return); if ($vn_return < 0 || $vn_return > 1 || filesize($filepath . "." . $ext) == 0) { @unlink($filepath . "." . $ext); $this->postError(1610, _t("Couldn't convert file to FLV format"), "WLPlugVideo->write()"); return false; } $this->properties["mimetype"] = $mimetype; $this->properties["typename"] = $this->typenames[$mimetype]; } break; # ------------------------------------ # ------------------------------------ case 'video/mpeg': case 'video/ogg': // only support "command" option... if (caMediaPluginFFfmpegInstalled($this->ops_path_to_ffmpeg)) { $va_ffmpeg_params = array(); if (!($vs_ffmpeg_command = $this->get('command'))) { // Video bitrate $vn_video_bitrate = $this->get('video_bitrate'); if ($vn_video_bitrate != '') { if ($vn_video_bitrate < 20000) { $vn_video_bitrate = 256000; } $va_ffmpeg_params["video_bitrate"] = "-b " . intval($vn_video_bitrate); } // Audio bitrate $vn_audio_bitrate = $this->get('audio_bitrate'); if ($vn_audio_bitrate < 8000) { $vn_audio_bitrate = 32000; } $va_ffmpeg_params["audio_bitrate"] = "-ab " . intval($vn_audio_bitrate); // Audio sample frequency $vn_audio_sample_freq = $this->get('audio_sample_freq'); if ($vn_audio_sample_freq != 44100 && $vn_audio_sample_freq != 22050 && $vn_audio_sample_freq != 11025) { $vn_audio_sample_freq = 44100; } $va_ffmpeg_params["audio_sample_freq"] = "-ar " . intval($vn_audio_sample_freq); // Multithreading $vn_threads = $this->get('threads'); if ($vn_threads < 1 || $vn_threads == '') { $vn_threads = 1; } $va_ffmpeg_params["threads"] = "-threads " . $vn_threads; // Quantitizers $vn_qmin = $this->get('qmin'); if ($vn_qmin != '') { $va_ffmpeg_params["qmin"] = "-qmin " . $vn_qmin; } $vn_qmax = $this->get('qmax'); if ($vn_qmax != '') { $va_ffmpeg_params["qmax"] = "-qmax " . $vn_qmax; } // Flags if (($vs_flags = $this->get('flags')) != '') { $va_ffmpeg_params["flags"] = "-flags " . $vs_flags; } // Resolution if (($vs_res = $this->get('resolution')) != '') { $va_ffmpeg_params["resolution"] = "-s " . $vs_res; } // Coder if (($vn_coder = $this->get('coder')) != '') { $va_ffmpeg_params["coder"] = "-coder " . $vn_coder; } // 2-pass encoding if ($this->get('twopass')) { $vb_twopass = true; } else { $vb_twopass = false; } // qdiff if (($vs_qdiff = $this->get('qdiff')) != '') { $va_ffmpeg_params["qdiff"] = "-qdiff " . $vs_qdiff; } // partitions if (($vs_partitions = $this->get('partitions')) != '') { $va_ffmpeg_params["partitions"] = "-partitions " . $vs_partitions; } // cmp if (($vs_cmp = $this->get('cmp')) != '') { $va_ffmpeg_params["cmp"] = "-cmp " . $vs_cmp; } // qdiff if (($vs_sc_threshold = $this->get('sc_threshold')) != '') { $va_ffmpeg_params["sc_threshold"] = "-sc_threshold " . $vs_sc_threshold; } // vpre if (!($vs_vpreset = $this->get('vpre')) != '') { $vs_vpreset = null; } } // put it all together // we need to be in a directory where we can write (libx264 logfiles) $vs_cwd = getcwd(); chdir(__CA_APP_DIR__ . "/tmp/"); $vs_cmd = ''; if ($vs_ffmpeg_command) { exec($vs_cmd .= $this->ops_path_to_ffmpeg . " -i " . caEscapeShellArg($this->filepath) . " {$vs_ffmpeg_command} " . caEscapeShellArg($filepath . "." . $ext) . (caGetOSFamily() == OS_POSIX ? " 2> /dev/null" : ""), $va_output, $vn_return); } else { if ($vs_vpreset) { $vs_other_params = ""; if ($vn_audio_bitrate) { $vs_other_params .= "-ab {$vn_audio_bitrate} "; } if ($vn_audio_sample_freq) { $vs_other_params .= "-ar {$vn_audio_sample_freq} "; } if ($vs_res && $vs_res != '') { $vs_other_params .= "-s " . $vs_res; } exec($vs_cmd .= $this->ops_path_to_ffmpeg . " -i " . caEscapeShellArg($this->filepath) . " -f mp4 -vcodec libx264 -acodec libfaac {$vs_other_params} -vpre {$vs_vpreset} -y " . caEscapeShellArg($filepath . "." . $ext) . (caGetOSFamily() == OS_POSIX ? " 2> /dev/null" : ""), $va_output, $vn_return); } else { if (!$vb_twopass) { exec($vs_cmd .= $this->ops_path_to_ffmpeg . " -i " . caEscapeShellArg($this->filepath) . " -f mp4 -vcodec libx264 -acodec libfaac " . join(" ", $va_ffmpeg_params) . " -y " . caEscapeShellArg($filepath . "." . $ext) . (caGetOSFamily() == OS_POSIX ? " 2> /dev/null" : ""), $va_output, $vn_return); } else { exec($vs_cmd .= $this->ops_path_to_ffmpeg . " -i " . caEscapeShellArg($this->filepath) . " -f mp4 -vcodec libx264 -pass 1 -acodec libfaac " . join(" ", $va_ffmpeg_params) . " -y " . caEscapeShellArg($filepath . "." . $ext) . (caGetOSFamily() == OS_POSIX ? " 2> /dev/null" : ""), $va_output, $vn_return); exec($vs_cmd .= $this->ops_path_to_ffmpeg . " -i " . caEscapeShellArg($this->filepath) . " -f mp4 -vcodec libx264 -pass 2 -acodec libfaac " . join(" ", $va_ffmpeg_params) . " -y " . caEscapeShellArg($filepath . "." . $ext) . (caGetOSFamily() == OS_POSIX ? " 2> /dev/null" : ""), $va_output, $vn_return); // probably cleanup logfiles here } } } chdir($vs_cwd); // avoid fun side-effects if (@filesize($filepath . "." . $ext) == 0) { @unlink($filepath . "." . $ext); if ($vs_vpreset) { $this->postError(1610, _t("Couldn't convert file to MPEG4 format [%1]; does the ffmpeg preset '%2' exist? (command was %3)", $vn_return, $vs_vpreset, $vs_cmd), "WLPlugVideo->write()"); } else { $this->postError(1610, _t("Couldn't convert file to MPEG4 format [%1] (command was %2)", $vn_return, $vs_cmd), "WLPlugVideo->write()"); } return false; } // try to hint for streaming if (file_exists($this->ops_path_to_qt_faststart)) { exec($this->ops_path_to_qt_faststart . " " . caEscapeShellArg($filepath . "." . $ext) . " " . caEscapeShellArg($filepath . "_tmp." . $ext) . (caGetOSFamily() == OS_POSIX ? " 2> /dev/null" : ""), $va_output, $vn_return); rename("{$filepath}_tmp.{$ext}", "{$filepath}.{$ext}"); } # ------------------------------------ $this->properties["mimetype"] = $mimetype; $this->properties["typename"] = $this->typenames[$mimetype]; } break; # ------------------------------------ # ------------------------------------ default: if ($mimetype != $this->handle["mime_type"]) { # this plugin can't write this mimetype (no conversions allowed) $this->postError(1610, _t("Can't convert '%1' to %2", $this->handle["mime_type"], $mimetype), "WLPlugVideo->write()"); return false; } # write the file if (!copy($this->filepath, $filepath . "." . $ext)) { $this->postError(1610, _t("Couldn't write file to '%1'", $filepath), "WLPlugVideo->write()"); return false; } break; # ------------------------------------ } // if output file doesn't exist, ffmpeg failed or isn't installed // so use default icons if (!file_exists($filepath . "." . $ext)) { # use default media icons return __CA_MEDIA_VIDEO_DEFAULT_ICON__; } return $filepath . "." . $ext; }
public function write($filepath, $mimetype, $pa_options = null) { if (!$this->handle) { return false; } if (!($ext = $this->info["EXPORT"][$mimetype])) { # this plugin can't write this mimetype return false; } # is mimetype valid? switch ($mimetype) { # ------------------------------------ case 'image/jpeg': $vn_preview_width = $this->properties["width"]; $vn_preview_height = $this->properties["height"]; if (caMediaPluginFFfmpegInstalled($this->ops_path_to_ffmpeg)) { if (($vn_start_secs = $this->properties["duration"] / 8) > 120) { $vn_start_secs = 120; // always take a frame from the first two minutes to ensure performance (ffmpeg gets slow if it has to seek far into a movie to extract a frame) } exec($this->ops_path_to_ffmpeg . " -ss " . $vn_start_secs . " -i " . caEscapeShellArg($this->filepath) . " -f mjpeg -t 0.001 -y " . caEscapeShellArg($filepath . "." . $ext), $va_output, $vn_return); if ($vn_return < 0 || $vn_return > 1 || !@filesize($filepath . "." . $ext)) { @unlink($filepath . "." . $ext); // don't throw error as ffmpeg cannot generate frame still from all files } else { // resize image to desired dimensions $o_media = new Media(); $o_media->read($filepath . "." . $ext); $o_media->transform('SCALE', array('width' => $vn_preview_width, 'height' => $vn_preview_height, 'mode' => 'bounding_box', 'antialiasing' => 0.5)); $o_media->write($filepath . "_tmp", 'image/jpeg', array()); if (!$o_media->numErrors()) { rename($filepath . "_tmp." . $ext, $filepath . "." . $ext); } else { @unlink($filepath . "_tmp." . $ext); } } } // if output file doesn't exist, ffmpeg failed or isn't installed // so use default icons if (!file_exists($filepath . "." . $ext)) { return __CA_MEDIA_VIDEO_DEFAULT_ICON__; } $this->properties["mimetype"] = $mimetype; $this->properties["typename"] = isset($this->typenames[$mimetype]) ? $this->typenames[$mimetype] : $mimetype; break; # ------------------------------------ # ------------------------------------ default: if ($mimetype != $this->handle["mime_type"]) { # this plugin can't write this mimetype (no conversions allowed) $this->postError(1610, _t("Can't convert '%1' to %2", $this->handle["mime_type"], $mimetype), "WLPlugQuicktimeVR->write()"); return false; } # write the file if (!copy($this->filepath, $filepath . "." . $ext)) { $this->postError(1610, _t("Couldn't write file to '%1'", $filepath), "WLPlugQuicktimeVR->write()"); return false; } break; # ------------------------------------ } return $filepath . "." . $ext; }