----------------siwuxie095
使用 Java Swing 框架制作一個簡單的視頻播放器:
首先到 VideoLAN 的官網下載 VLC media player,制作的視頻播放器內核
需要調用 VLC media player
VideoLAN:http://www.videolan.org/
VLC command-line help:https://wiki.videolan.org/VLC_command-line_help/
接着下載相關的在線開源庫:vlcj
GitHub 鏈接:https://github.com/caprica/vlcj
下載鏈接:
(1)http://capricasoftware.co.uk/#/projects/vlcj
(2)http://capricasoftware.co.uk/#/projects/vlcj/tutorial/installation
(3)http://download.csdn.net/detail/siwuxie095/9807180
vlcj 教程:http://capricasoftware.co.uk/#/projects/vlcj/tutorial
vlcj-3.8.0-dist.tar.gz 解壓后一覽:
必備的 4 個 jar 包:
(1)jna-3.5.2.jar
(2)platform-3.5.2.jar
(3)vlcj-3.8.0.jar
(4)slf4j-api-1.7.10.jar
雖然這 4 個 jar 包已經夠了,但根據控制台的提示:
Failed to load class "org.slf4j.impl.StaticLoggerBinder"
最好還是查看具體的細節:https://www.slf4j.org/codes.html#StaticLoggerBinder
可以導入頁面中所提到的 5 個包中的任何一個且只能一個來解決問題
(1)slf4j-nop.jar
(2)slf4j-simple.jar
(3)slf4j-log4j12.jar
(4)slf4j-jdk14.jar
(5)logback-classic.jar
SLF4J 下載鏈接:
(1)https://www.slf4j.org/download.html
(2)http://download.csdn.net/detail/siwuxie095/9807191
我選擇導入 slf4j-nop-1.7.25.jar,即 5 個可選包中的第一個
工程名:MyVideoPlayer
包名:com.siwuxie095.main、com.siwuxie095.view
類名:VideoPlayer.java(主類)、MainWindow.java
打開資源管理器,在工程 MyVideoPlayer 文件夾下,創建一個
文件夾:lib,在其中放入:
(1)jna-3.5.2.jar
(2)platform-3.5.2.jar
(3)vlcj-3.8.0.jar
(4)slf4j-api-1.7.10.jar
(5) slf4j-nop-1.7.25.jar
工程結構目錄如下:
全選這 5 個 jar 文件,右鍵->Build Path->Add to Build Path
此時,工程結構目錄一覽:
VideoPlayer.java(主類):
package com.siwuxie095.main;
import java.awt.EventQueue; import java.io.File;
import javax.swing.JFileChooser; import javax.swing.SwingWorker;
import com.siwuxie095.view.MainWindow; import com.sun.jna.Native; import com.sun.jna.NativeLibrary;
import uk.co.caprica.vlcj.binding.LibVlc; import uk.co.caprica.vlcj.discovery.NativeDiscovery; import uk.co.caprica.vlcj.runtime.RuntimeUtil;
public class VideoPlayer {
/** * VLC播放器系統庫的路徑:D:\VLC media player\VLC * 注意需要將路徑中的反斜杠改為斜杠,或 使用雙反斜杠(即通過轉義符進行轉義) * 系統庫一般是在含有 libvlc.dll、libvlccore.dll 的路徑 */ private static final String NATIVE_LIBRARY_SEARCH_PATH = "D:/VLC media player/VLC";
//將聲明轉移到類中,並設為 static static MainWindow frame;
public static void main(String[] args) {
//(1)法一:首先要找到本機庫(VLC播放器的系統庫),這是自動搜索本機庫的位置 boolean found = new NativeDiscovery().discover(); System.out.println(found); System.out.println(LibVlc.INSTANCE.libvlc_get_version());
//判斷當前的系統是否是Windows //還可以判斷Mac和Linux,以傳入不同的路徑 if (RuntimeUtil.isWindows()) {
//(2)法二:手動設置本機庫(VLC播放器的系統庫)的路徑 NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), NATIVE_LIBRARY_SEARCH_PATH);
System.out.println(LibVlc.INSTANCE.libvlc_get_version()); }
//加載VLC播放器的系統庫 Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
//在主方法中創建窗體 EventQueue.invokeLater(new Runnable() { public void run() { try { frame = new MainWindow(); frame.setVisible(true); //字幕的編碼 String options="--subsdec-encoding=GB18030"; /** * prepareMedia() 先准備而不是馬上播放 * 可傳入視頻文件的路徑(和播放參數,如:字幕編碼) * 這里使用雙反斜杠(通過轉義符進行轉義) * 關於播放參數,可以參考 VLC command-line * 鏈接:https://wiki.videolan.org/VLC_command-line_help/ * 進入后搜索 subsdec 設定字幕編碼 * 還可以傳入更多播放參數 */ frame.getMediaPlayer().prepareMedia("C:\\Users\\siwux\\Desktop\\" + "testvideo\\test.mp4",options);
frame.getMediaPlayer().toggleFullScreen();
//創建一個 SwingWorker 線程,用於實時調節進度 //注意:創建完畢,最后要 execute() 將它運行起來 new SwingWorker<String, Integer>() {
@Override protected String doInBackground() throws Exception {
while (true) { //視頻總時長,以毫秒計 long total=frame.getMediaPlayer().getLength(); //當前所看時長,以毫秒計 long curr=frame.getMediaPlayer().getTime(); //百分比,並強轉為 float float percent=(float)curr/total; //因為進度條不是按百分比進行計算,而是 0-100 的數值范圍 //所以要乘 100,並強轉為 int,publish() 到 process() //(進度條范圍可設置,如果改為 0-120,就要乘 120) publish((int)(percent*100));
//每隔 0.1 秒(100毫秒)更新一次進度條,如果不加則刷新過快 Thread.sleep(100); }
}
protected void process(java.util.List<Integer> chunks) { //創建int型變量 value 接收 chunks 中的值 for (int value : chunks) { frame.getProgressBar().setValue(value); }
}; }.execute(); } catch (Exception e) { e.printStackTrace(); } } });
}
//播放 public static void play() { frame.getMediaPlayer().play(); }
//暫停 public static void pause() { frame.getMediaPlayer().pause(); }
//停止 public static void stop() { frame.getMediaPlayer().stop(); }
public static void jumpTo(float to) { //為跳轉設定時間:百分比乘以視頻時間的總長 frame.getMediaPlayer().setTime((long)(to*frame.getMediaPlayer().getLength())); }
public static void openVideo() { //創建文件選擇器:JFileChooser JFileChooser chooser=new JFileChooser(); //將父級窗體設置成 null int v=chooser.showOpenDialog(null); if (v==JFileChooser.APPROVE_OPTION) { File file=chooser.getSelectedFile(); //獲取到文件的絕對路徑,開始播放 frame.getMediaPlayer().playMedia(file.getAbsolutePath()); } }
public static void openSubtitle() { JFileChooser chooser=new JFileChooser(); int v=chooser.showOpenDialog(null); if (v==JFileChooser.APPROVE_OPTION) { File file=chooser.getSelectedFile(); //設定字幕,直接傳入 file 對象 frame.getMediaPlayer().setSubTitleFile(file); } }
public static void exit() { //在退出之前,先釋放播放器的資源 frame.getMediaPlayer().release(); System.exit(0); }
public static void setVol(int vol) { //設定音量 frame.getMediaPlayer().setVolume(vol); }
} |
MainWindow.java:
package com.siwuxie095.view;
import java.awt.BorderLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.MouseAdapter; import java.awt.event.MouseEvent;
import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.JPanel; import javax.swing.JProgressBar; import javax.swing.JSlider; import javax.swing.UIManager; import javax.swing.UnsupportedLookAndFeelException; import javax.swing.border.EmptyBorder; import javax.swing.event.ChangeEvent; import javax.swing.event.ChangeListener;
import com.siwuxie095.main.VideoPlayer; import com.sun.java.swing.plaf.windows.WindowsLookAndFeel;
import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent; import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
public class MainWindow extends JFrame {
private JPanel contentPane;
//創建播放器的界面需要使用 EmbeddedMediaPlayerComponent EmbeddedMediaPlayerComponent playerComponent;
private JPanel bottomPane; private JButton btnPlay; private JButton btnPause; private JButton btnStop; private JPanel controlPane; private JProgressBar progress; private JMenuBar menuBar; private JMenu mnFile; private JMenuItem mntmOpenvideo; private JMenuItem mntmOpensubtitle; private JMenuItem mntmExit; private JSlider slider;
/** * Create the frame. */ public MainWindow() {
try { UIManager.setLookAndFeel(new WindowsLookAndFeel()); } catch (UnsupportedLookAndFeelException e) { e.printStackTrace(); }
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); setBounds(100, 100, 450, 300);
menuBar = new JMenuBar(); setJMenuBar(menuBar);
mnFile = new JMenu("File"); menuBar.add(mnFile);
mntmOpenvideo = new JMenuItem("OpenVideo"); mntmOpenvideo.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { VideoPlayer.openVideo(); } }); mnFile.add(mntmOpenvideo);
mntmOpensubtitle = new JMenuItem("OpenSubtitle"); mntmOpensubtitle.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { VideoPlayer.openSubtitle(); } }); mnFile.add(mntmOpensubtitle);
mntmExit = new JMenuItem("Exit"); mntmExit.addActionListener(new ActionListener() { public void actionPerformed(ActionEvent e) { VideoPlayer.exit(); } }); mnFile.add(mntmExit); contentPane = new JPanel(); contentPane.setBorder(new EmptyBorder(5, 5, 5, 5)); contentPane.setLayout(new BorderLayout(0, 0)); setContentPane(contentPane);
JPanel videoPane = new JPanel(); contentPane.add(videoPane, BorderLayout.CENTER); videoPane.setLayout(new BorderLayout(0, 0));
//在 videoPane 創建之后實例化 playerComponent playerComponent=new EmbeddedMediaPlayerComponent(); //將 playerComponent 添加到 videoPane 中,並指定布局 videoPane.add(playerComponent, BorderLayout.CENTER);
bottomPane = new JPanel(); videoPane.add(bottomPane, BorderLayout.SOUTH); bottomPane.setLayout(new BorderLayout(0, 0));
controlPane = new JPanel(); bottomPane.add(controlPane);
btnStop = new JButton("Stop"); controlPane.add(btnStop); btnStop.setFocusable(false);
btnPlay = new JButton("Play"); controlPane.add(btnPlay); btnPlay.setFocusable(false);
btnPause = new JButton("Pause"); controlPane.add(btnPause); btnPause.setFocusable(false);
slider = new JSlider(); slider.setFocusable(false); //關於默認音量的設定要在 stateChanged 事件之前 //如果要設定最大音量和最小音量也是如此 slider.setValue(20); //為音量調節 slider 添加 stateChanged 事件 slider.addChangeListener(new ChangeListener() { public void stateChanged(ChangeEvent e) { VideoPlayer.setVol(slider.getValue()); } });
controlPane.add(slider);
progress = new JProgressBar(); progress.setFocusable(false);
//為進度條 progress 添加 mouseClicked 事件 progress.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { //獲取鼠標點擊在進度條上的位置 int x=e.getX(); //計算點擊位置占進度條總長的百分比 float per=(float)x/progress.getWidth(); VideoPlayer.jumpTo(per); } }); //讓進度條 progress 顯示數字百分比 progress.setStringPainted(true); bottomPane.add(progress, BorderLayout.NORTH);
//為 Stop 按鈕添加 mouseClicked 事件 btnStop.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { VideoPlayer.stop(); } });
//為 Play 按鈕添加 mouseClicked 事件 btnPlay.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { VideoPlayer.play(); } });
//為 Pause 按鈕添加 mouseClicked 事件 btnPause.addMouseListener(new MouseAdapter() { @Override public void mouseClicked(MouseEvent e) { VideoPlayer.pause(); } });
}
//返回媒體播放器的實例 public EmbeddedMediaPlayer getMediaPlayer() { return playerComponent.getMediaPlayer(); }
//返回JProgressBar的實例 public JProgressBar getProgressBar() { return progress; }
} |
將窗體 JFrame 的 LookAndFeel 設定為 Windows
根面板 contentPane 使用默認布局 Border Layout
在 contentPane 的中間添加一個 JPanel,將其布局改為:
Border Layout,Rename 為 videoPane
在 videoPane 的下方添加一個 JPanel,將其布局改為:
Border Layout,Rename 為 bottomPane
在 bottomPane 的中間添加一個 JPanel,將其布局改為:
Flow Layout,Rename 為 controlPane
在 controlPane 中添加三個 JButton 和一個 JSlider
將三個 JButton 的 focusable 屬性設為 false,並將其文本(text)分別改為:
Stop、Play 和 Pause,再分別 Rename 為:btnStop、btnPlay 和 btnPause
為三個 JButton 添加 mouseClicked 事件,實現對應 停止、播放 和 暫停 的功能
將 Slider 的 focusable 屬性設為 false
為 JSlider 添加 stateChanged 事件,實現 調節音量 的功能
在 bottomPane 的上方添加一個 JProgressBar
將 JProgressBar 的 focusable 屬性設為 false,stringPainted 屬性設為 true,
並 Rename 為:progress
為 JProgressBar 添加 mouseClicked 事件,實現 調節進度 的功能
在 JFrame 的上方添加一個 JMenuBar,注意:JMenuBar 和 contentPane 同級
制作 菜單欄,為 菜單項 添加 actionPerformed 事件,實現
打開視頻、打開字幕 和 退出 的功能
整體的 Components 視圖:
運行程序:
最后導出為可執行的 Java 程序:
選擇工程 MyVideoPlayer,右鍵->Export->Java->Runnable JAR file
然后選擇當前主類:VideoPlayer - MyVideoPlayer,導出
路徑指定為:E:\workspace\MyVideoPlayer\release,並
命名為:MyVideoPlayer.jar
【made by siwuxie095】