You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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
    }
}

问题原因

  1. 媒体未就绪时调用位置设置:在media().play()之前调用setPosition,此时媒体尚未加载,元数据(如时长)还未解析,设置操作无法生效。
  2. 不可靠的线程休眠:使用Thread.sleep()等待媒体加载,无法保证媒体实际完成解析,休眠时间过短或过长都会导致设置时机不对。
  3. 操作顺序混乱:先播放再停止,之后设置位置再启动,此时媒体状态可能未处于可设置位置的状态。

解决方法及最简示例

正确的做法是监听媒体解析完成的事件,在媒体元数据就绪后再设置播放位置,确保调用时机正确。

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.21 17:06:30