我使用vlcj编写了一个代码,该代码旨在定期获取视频的屏幕截图。当我尝试输出视频的长度时,它显示为0。这是什么问题?

import uk.co.caprica.vlcj.binding.LibVlc;
import uk.co.caprica.vlcj.player.MediaPlayerFactory;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
import uk.co.caprica.vlcj.runtime.RuntimeUtil;

import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;

public class ScreenShotCapture {

    public static void main(String[] args){
        NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), "C:\\Program Files\\VideoLAN\\VLC");
        Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
        MediaPlayerFactory mediaPlayerFactory = new MediaPlayerFactory();
        final EmbeddedMediaPlayer mediaPlayer =mediaPlayerFactory.newEmbeddedMediaPlayer();
        mediaPlayer.playMedia("E:\\videos\\Avenged Sevenfold - So Far Away [Music Video].mp4");
        mediaPlayer.setSnapshotDirectory("E:\\vidoes");
        long length = mediaPlayer.getTime();
        long interval = length / 21;
        for(long  i = 1;i <= length;i+= interval){
            mediaPlayer.setTime(i);
            mediaPlayer.saveSnapshot();
        }
    }
}

最佳答案

媒体长度不是立即可用的,它会在解码器确定长度后开始播放媒体后的一段时间内可用。这本质上就是VLC的工作方式。

几乎所有事物都是异步运行的,这意味着您必须将代码基于事件,而不是仅以过程方式编写代码。

当长度更改时,将生成本机事件,最终导致触发MediaPlayerEventListener#lengthChanged事件。触发该事件后,对mediaPlayer.getLength()的调用应返回非零值。

下一个问题是您在调用saveSnapshot之后立即调用setTime。同样,setTime是异步工作的,因此您不能假定该方法返回时媒体播放器已达到所需的时间。您必须等待timeChanged事件,然后检查是否已经到达(实际上已过去)您的时间。

最后一个问题可能并不重要,具体取决于您的用例,它是对saveSnapshot的调用本身是异步的,因此本质上您已请求快照,但尚未生成快照。这次您需要等待snapshotTaken事件。仅当收到该事件时,快照才实际保存到磁盘。

因此,基本上,您需要采取不同的思维方式,而是实施基于事件的方法。

此vlcj示例中的一个示例生成快照:https://github.com/caprica/vlcj/blob/vlcj-3.0.1/src/test/java/uk/co/caprica/vlcj/test/condition/ConditionTest.java

如果您不喜欢该示例,则可以通过响应您自己的MediaPlayerEventListener实现中的事件来实现它。

旁白:您还可以使用VLC“场景”过滤器以可靠的方式生成快照。

10-08 05:34