如何使用 FFMPEG 获取播放视频的持续时间?

How can I get the duration of played video with FFMPEG?

我正在使用 FFMPEG 播放视频(因为我需要允许 .avi 和 .mov 格式),目前找不到获取视频时长的方法。如果我不使用 FFMPEG,那么使用 onMetaData 就足够简单了,但是这个 returns 0 因为 FFMPEG 需要 netStream.play(null); 而不是 netStream.play(videoPath);

我希望添加的功能来检查视频的持续时间:

nativeProcess.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, onOutputData);

public function onOutputData(e:ProgressEvent):void {
    var videoStream:ByteArray = new ByteArray();
    nativeProcess.standardOutput.readBytes(videoStream, 0, nativeProcess.standardOutput.bytesAvailable);
    netStream.appendBytes(videoStream);
}

您可以使用 ffmpegNativeProcess 获取视频的时长:

var video:File = File.applicationDirectory.resolvePath('video.avi'),
    exe:File = File.applicationDirectory.resolvePath('ffmpeg.exe');

if (NativeProcess.isSupported) {

    var args:Vector.<String> = new Vector.<String>();
        args.push("-i", video.nativePath);

    var npsi:NativeProcessStartupInfo = new NativeProcessStartupInfo();
        npsi.executable = exe;
        npsi.arguments = args;

    var process:NativeProcess = new NativeProcess();        
        process.addEventListener(ProgressEvent.STANDARD_ERROR_DATA, on_output_data);
        process.start(npsi);

    function on_output_data(e:ProgressEvent):void {
        var s:String = process.standardError.readUTFBytes(process.standardError.bytesAvailable);
        var a:Array = s.match(/Duration: (\d{2}:\d{2}:\d{2})/) || [];
        if(a.length > 0){
            trace('video duration :', a[1]);    
            // gives for example : video duration : 00:01:45
        }   
    }

} else {

    trace('NativeProcess is not supported');

}

您也可以像这样使用 ffprobe

var exe:File = File.applicationDirectory.resolvePath('ffprobe.exe');

var args:Vector.<String> = new Vector.<String>();
    args.push('-v', 'error', '-show_entries', 'format=duration', '-of', 'default=noprint_wrappers=1:nokey=1', video.nativePath);

var npsi:NativeProcessStartupInfo = new NativeProcessStartupInfo();
    npsi.executable = exe;
    npsi.arguments = args;

var process:NativeProcess = new NativeProcess();        
    process.addEventListener(ProgressEvent.STANDARD_OUTPUT_DATA, on_output_data);
    process.start(npsi);

function on_output_data(e:ProgressEvent):void
{       
    trace('video duration :', process.standardOutput.readUTFBytes(process.standardOutput.bytesAvailable));
    // gives for example : video duration : 67.250584
}

希望能帮到你。

编辑(您可以尝试的另一种方式..):

当 NetStream 播放视频时,它首先检查元数据,并且由于 FLV 元数据包含 duration 条目,您可以尝试读取该条目(元数据始终先发送以进行附加任何实际的视频帧数据)...

1) 声明一个 public 变量来监听元数据

public var metaListener : Object;

2) 在设置 NetStream 的同时设置 Meta 监听器

nc = new NetConnection();   nc.connect(null);
metaListener = new Object();
metaListener = { onMetaData: received_Meta };
ns = new NetStream(nc); ns.client = metaListener;

3) 上面触发的"received Meta"函数"onMetaData"

public function received_Meta ( v_data : Object ) : void
{
    trace("video duration   : "  + v_data.duration );
}


或者自动列出元数据中的每个可用条目

public function received_Meta ( v_data : Object ) : void
{
    trace("### Begin Metadata listing : FLV Entries ### "  );
        for (var entry:* in v_data) 
        {
            var value:Object = v_data[ entry ];
            trace(" > " + entry + " : " + value);
        }
    trace("### End of Metadata listing for this FLV ### "  );
}