我使用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“场景”过滤器以可靠的方式生成快照。