vlcj中setPosition()/setTime()无响应,问题出在哪里?
VLCJ设置播放位置无效问题解决
问题描述
MP4视频/音频播放完全正常,start()和stop()可正常启停,但setTime(xx)和setPosition(xx)完全没有作用。
问题代码
import java.awt.BorderLayout; import java.awt.Canvas; import java.awt.Color; import javax.swing.JPanel; import com.sun.jna.NativeLibrary; import java.util.logging.Level; import java.util.logging.Logger; import uk.co.caprica.vlcj.binding.RuntimeUtil; import uk.co.caprica.vlcj.player.base.ControlsApi; import uk.co.caprica.vlcj.player.base.MediaApi; import uk.co.caprica.vlcj.player.base.MediaPlayer; import uk.co.caprica.vlcj.player.component.CallbackMediaPlayerComponent; import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent; import uk.co.caprica.vlcj.player.component.callback.FilledCallbackImagePainter; import uk.co.caprica.vlcj.player.component.callback.FixedCallbackImagePainter; import uk.co.caprica.vlcj.player.component.callback.ScaledCallbackImagePainter; import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer; import uk.co.caprica.vlcj.player.renderer.RendererItem; import uk.co.caprica.vlcjplayer.event.TickEvent; import uk.co.caprica.vlcjplayer.view.action.mediaplayer.MediaPlayerActions; public class TestClass extends JPanel { private EmbeddedMediaPlayerComponent ourMediaPlayer; TestClass(){ //NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), "C:\\Program Files\\VideoLAN\\VLC"); ourMediaPlayer = new EmbeddedMediaPlayerComponent(); /* Set the canvas */ Canvas c = new Canvas(); c.setBackground(Color.black); c.setVisible(true); /* Set the layout */ this.setLayout(new BorderLayout()); /* Add the canvas */ this.add(c, BorderLayout.CENTER); this.setVisible(true); this.add(ourMediaPlayer); } public void play() { /* Play the video */ System.out.println("Starting..."); ourMediaPlayer.mediaPlayer().controls().setPosition((float) 0.5); // NOPE ourMediaPlayer.mediaPlayer().media().play("/home/manfred/ExtraDisk/Work/BTL/Movement2022/walking.mp4"); // works ourMediaPlayer.mediaPlayer().controls().stop(); // works ourMediaPlayer.mediaPlayer().controls().setPosition((float) 0.5); //NOPE try { Thread.sleep(2000); } catch (InterruptedException ex) { Logger.getLogger(TestClass.class.getName()).log(Level.SEVERE, null, ex); } ourMediaPlayer.mediaPlayer().controls().setPosition((float) 0.5); //NOPE ourMediaPlayer.mediaPlayer().controls().setTime(2000); // NOPE ourMediaPlayer.mediaPlayer().controls().start(); //works System.out.println("Started!"); try { Thread.sleep(2000); } catch (InterruptedException ex) { Logger.getLogger(TestClass.class.getName()).log(Level.SEVERE, null, ex); } ourMediaPlayer.mediaPlayer().controls().stop(); // works } }
问题原因
- 媒体未就绪时调用位置设置:在
media().play()之前调用setPosition,此时媒体尚未加载,元数据(如时长)还未解析,设置操作无法生效。 - 不可靠的线程休眠:使用
Thread.sleep()等待媒体加载,无法保证媒体实际完成解析,休眠时间过短或过长都会导致设置时机不对。 - 操作顺序混乱:先播放再停止,之后设置位置再启动,此时媒体状态可能未处于可设置位置的状态。
解决方法及最简示例
正确的做法是监听媒体解析完成的事件,在媒体元数据就绪后再设置播放位置,确保调用时机正确。
import java.awt.BorderLayout; import javax.swing.JFrame; import uk.co.caprica.vlcj.player.component.EmbeddedMediaPlayerComponent; import uk.co.caprica.vlcj.player.base.MediaPlayer; import uk.co.caprica.vlcj.player.base.MediaPlayerEventListener; public class VlcPlayerPositionExample { private final EmbeddedMediaPlayerComponent mediaPlayerComponent; public VlcPlayerPositionExample() { mediaPlayerComponent = new EmbeddedMediaPlayerComponent(); // 添加媒体事件监听器,监听解析完成事件 mediaPlayerComponent.mediaPlayer().events().addMediaPlayerEventListener(new MediaPlayerEventListener() { @Override public void mediaParsedChanged(MediaPlayer mediaPlayer, boolean newStatus) { // 媒体解析完成后,设置播放位置到50%处 if (newStatus) { mediaPlayer.controls().setPosition(0.5f); // 启动播放 mediaPlayer.controls().start(); } } }); } public void playVideo(String videoPath) { // 加载媒体(自动触发解析) mediaPlayerComponent.mediaPlayer().media().prepare(videoPath); } public static void main(String[] args) { JFrame frame = new JFrame("VLCJ Position Test"); frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(800, 600); VlcPlayerPositionExample player = new VlcPlayerPositionExample(); frame.add(player.mediaPlayerComponent, BorderLayout.CENTER); frame.setVisible(true); // 替换为你的视频路径 player.playVideo("/home/manfred/ExtraDisk/Work/BTL/Movement2022/walking.mp4"); } }
关键修正点
- 使用
media().prepare()替代直接play(),确保媒体先完成解析。 - 通过
MediaPlayerEventListener的mediaParsedChanged事件,在媒体解析完成后再设置位置并启动播放。 - 避免使用不可靠的
Thread.sleep(),依赖事件回调保证时机正确。
内容的提问来源于stack exchange,提问作者NPC239
相关产品推荐
相关产品推荐

