<?php
define('FFMPEG', 'ffmpeg');
define('WSLPATH', '/usr/bin/wslpath');
define('TMP_DIR', realpath('./tmp'));
function usage()
{
global $argv;
echo "Usage: $argv[0] fcp-7-xml-v5-timeline.xml output.mkv\n";
exit;
}
if ($argc != 3) {
usage();
}
$xml = $argv[1];
$output = $argv[2];
$pid = getmypid();
if (!is_file($xml)) {
usage();
}
if (!is_dir(TMP_DIR)) {
mkdir(TMP_DIR, 0777, true);
}
$obj = new SimpleXMLElement(file_get_contents($xml));
$timeBase = $obj->sequence->rate->timebase;
$i = 1;
$list = [];
$files = [];
foreach ($obj->sequence->media->video->track->clipitem as $clip) {
$id = (string) ($clip->file['id']);
$url = $clip->file->pathurl;
$path = escapeshellarg(pathUrlDecode($id, $url));
$start = escapeshellarg($clip->in / $timeBase);
$end = escapeshellarg($clip->out / $timeBase);
$tmpFile = TMP_DIR."/tmp-$pid-$i.mkv";
$list[] = "file '$tmpFile'";
$files[] = $tmpFile;
$cmd = FFMPEG." -hide_banner -i $path -ss $start -to $end -c copy $tmpFile -y";
echo "********************************\n$cmd\n";
passthru($cmd);
echo "\n";
$i++;
}
$mergeList = TMP_DIR."/merge-$pid.list";
file_put_contents($mergeList, implode("\n", $list));
$cmd = FFMPEG." -hide_banner -f concat -safe 0 -i $mergeList -c copy ".escapeshellarg($output)." -y";
echo "********************************\n$cmd\n";
passthru($cmd);
echo "\n";
unlink($mergeList);
foreach ($files as $file) {
unlink($file);
}
function pathUrlDecode($id, $url)
{
static $urlCache = [];
if (isset($urlCache[$id])) {
return $urlCache[$id];
}
$originUrl = $url;
if (!is_file($url) && substr($url, 0, 17) == 'file://localhost/') {
$url = substr($url, 17);
}
if (!is_file($url) && preg_match('#%[a-f0-9]{2}#is', $url)) {
$url = urldecode($url);
}
if (!is_file($url) && preg_match('#^([a-z]):(.+)$#is', $url, $opt) && is_file(WSLPATH)) {
$url = system(WSLPATH.' '.escapeshellarg($url));
}
if (!is_file($url)) {
die("无法解析媒体文件URL,请手动修改XML中的文件路径。\n有问题的URL:$originUrl\n解析后:$url\n");
}
$urlCache[$id] = $url;
return $url;
}