vlcj--java-制作视频播放器

目标:

制作一个简易的视频播放器,实现对视频文件的打开,播放,暂停,退出,以及实现进度条的显示,通过点击视频播放进度条可以更改视频的播放时间。还添加调节音量的功能。

工程的准备:

因为通过java制作的视频播放器是基于vlcj库建立的,所有必须首先下载vlcj,然后解压导入Java工程中调用。还要下载slf4j库,点击可下载slf4j库,最后由于视频播放器的内核是基于VLC播放器的,所有需要在电脑上下载VLC播放器,下载后安装,我这里选择安装的路径是默认路径。

一、首先下载vlcj后解压,将其中的jna-3.5.3.jar、platform-3.5.2.jar、vlcj-3.8.0.jar三个文件复制到java工程的lib文件夹中,lib文件夹需自建。

vlcj

图:所需要的三个文件

二、下载slf4j库后,解压,将其中的slf4j-api-1.7.25.jar和slf4j-nop-1.7.25.jar,两个文件添加到java工程的lib文件夹中。把添加好的库添加到构建路径中,用来引用。工程结构如下图:

工程结构图

图:工程结构图

关于vlcj库使用说明:

关于vlcj库的使用,具体可点击:Vlcj查看。在这个Java工程中,首先使用是按照官方给出的例子使用。

第一步使用自动发现本地库:

1
2
3
//NativeDiscovery().discover();函数返回的是一个布尔类型的值,所有可以定义一个布尔类型的值,用来接收,利用控制台打印,是否发现本地库
boolean found = new NativeDiscovery().discover();
System.out.println(found);

官方提示原代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
package tutorial;

import uk.co.caprica.vlcj.binding.LibVlc;
import uk.co.caprica.vlcj.discovery.NativeDiscovery;

public class Tutorial {

public static void main(String[] args) {
boolean found = new NativeDiscovery().discover();
System.out.println(found);
System.out.println(LibVlc.INSTANCE.libvlc_get_version());
}
}

第一步

图:使用说明

第二步,需要指定VLC路径。

1
2
3
4
//指定VLC路径,这里使用的路径是安装默认路径。
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), "C:\\Program Files\\VideoLAN\\VLC");
//打印版本,用来检验是否获得文件
System.out.println(LibVlc.INSTANCE.libvlc_get_version());

官方原代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package tutorial;

import uk.co.caprica.vlcj.binding.LibVlc;
import uk.co.caprica.vlcj.runtime.RuntimeUtil;

import com.sun.jna.NativeLibrary;

public class Tutorial {

private static final String NATIVE_LIBRARY_SEARCH_PATH = "/home/vlc";

public static void main(String[] args) {
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), NATIVE_LIBRARY_SEARCH_PATH);
System.out.println(LibVlc.INSTANCE.libvlc_get_version());
}
}

第二步

图:使用说明

只有当运行代码后,控制台什么都没有输出,一切正常,证明准备工作已做好,可以进行下面的进程。

运行

图:运行后,控制台正常


播放器代码的实现:


主方法代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
package videoPlayer.Main;

import java.awt.EventQueue;
import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.SwingWorker;
import com.sun.jna.NativeLibrary;
import uk.co.caprica.vlcj.discovery.NativeDiscovery;
import uk.co.caprica.vlcj.runtime.RuntimeUtil;
import videoPlayer.views.MainWindow;

public class MainVideoPlayler {
//声明全局变量MainWindow
static MainWindow frame;
public static void main(String[] args) {
//实例化NativeDiscovery类
new NativeDiscovery().discover();
//通过判断选择系统,Windows,Mac OS,Liunx。以下都是各个系统的VLC默认安装路径
if (RuntimeUtil.isWindows()) {
NativeLibrary.addSearchPath(
RuntimeUtil.getLibVlcLibraryName(), "C:\\Program Files\\VideoLAN\\VLC");
}else if (RuntimeUtil.isMac()) {
NativeLibrary.addSearchPath(
RuntimeUtil.getLibVlcLibraryName(), "/Applications/VLC.app/Contents/MacOS/lib");
}else if (RuntimeUtil.isNix()) {
NativeLibrary.addSearchPath(
RuntimeUtil.getLibVlcLibraryName(), "/home/linux/vlc/install/lib");
}
EventQueue.invokeLater(new Runnable() {
public void run() {
try {
frame = new MainWindow();
frame.setVisible(true);
//通过--subsdec-encoding= 可以指定字幕文件编码格式
String options[] = {"--subsdec-encoding=GB18030"};
//让窗体获得视频资源
frame.getMediaPlayer().prepareMedia(
"D:\\我的文件\\06、Java语言\\7、界面设计\\10、Java视频播放器的制作\\1、工程的准备.mp4",options);
//prepareMedia();是准备播放视频。而PlayMedia();是直接播放视频
//frame.getMediaPlayer().playMedia(
// "D:\\我的文件\\06、Java语言\\7、界面设计\\10、Java视频播放器的制作\\1、工程的准备.mp4",options);
new SwingWorker<String, Integer>() {
//调节视频音量
protected String doInBackground() throws Exception {
while (true) {
//获得当前视频总时间长度
long total = frame.getMediaPlayer().getLength();
//获得当期播放时间
long curr = frame.getMediaPlayer().getTime();
//获取播放视频的百分比
float percent = ((float)curr/total);
publish((int)(percent*100));
Thread.sleep(100);
}
}
protected void process(java.util.List<Integer> chunks) {
for (int v:chunks) {
frame.getProgressBar().setValue(v);
}
};
}.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 chooser = new JFileChooser();
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();
frame.getMediaPlayer().playMedia(file.getAbsolutePath());
}
File file = chooser.getSelectedFile();
frame.getMediaPlayer().setSubTitleFile(file);
}
//实现软件退出
public static void exit() {
frame.getMediaPlayer().release();
System.exit(0);
}
//调节音量
public static void volume(int v) {
frame.getMediaPlayer().setVolume(v);
}
}

窗体代码实现:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
package videoPlayer.views;

import java.awt.BorderLayout;
import java.awt.FlowLayout;
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.JLabel;
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.border.EmptyBorder;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ChangeListener;

import uk.co.caprica.vlcj.component.EmbeddedMediaPlayerComponent;
import uk.co.caprica.vlcj.player.embedded.EmbeddedMediaPlayer;
import videoPlayer.Main.MainVideoPlayler;
import javax.swing.ImageIcon;

public class MainWindow extends JFrame {

private JPanel contentPane;
//创建播放器界面组件
EmbeddedMediaPlayerComponent playerComponent =
new EmbeddedMediaPlayerComponent();
private final JPanel panel = new JPanel();
private JProgressBar progress;

public MainWindow() {

setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(100, 100, 712, 512);
//菜单条
JMenuBar menuBar = new JMenuBar();
setJMenuBar(menuBar);
//菜单中的文件
JMenu menu = new JMenu("文件");
menuBar.add(menu);
//一级菜单中的打开文件选项
JMenuItem menuItem = new JMenuItem("打开文件");
menu.add(menuItem);
menuItem.addActionListener(new ActionListener() {
//点击后会文件选择器
@Override
public void actionPerformed(ActionEvent e) {
MainVideoPlayler.openVideo();
}
});
//一级菜单中的打开字符选项
JMenuItem menuItem_1 = new JMenuItem("打开字幕");
menu.add(menuItem_1);
menuItem_1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
MainVideoPlayler.openSubtitle();
}
});
//退出
JMenuItem menuItem_2 = new JMenuItem("退出");
menu.add(menuItem_2);
menuItem_2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
MainVideoPlayler.exit();
}
});
contentPane = new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0, 0));
setContentPane(contentPane);

JPanel videopanel = new JPanel();
//因为playerComponent布局为边界布局,所以Jpanl布局也必须边界布局,不然只能听到声音,看不到画面
contentPane.add(videopanel, BorderLayout.CENTER);
videopanel.setLayout(new BorderLayout(0, 0));
//将播放器界面添加到videopanel中,用来播放视频,并设置布局为居中
playerComponent = new EmbeddedMediaPlayerComponent();
videopanel.add(playerComponent, BorderLayout.CENTER);
videopanel.add(panel, BorderLayout.SOUTH);
panel.setLayout(new BorderLayout(0, 0));

JPanel controlPanel = new JPanel();
panel.add(controlPanel);
controlPanel.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));

JButton button_1 = new JButton("\u9000\u51FA");
controlPanel.add(button_1);

JButton btnNewButton = new JButton("");
btnNewButton.setIcon(new ImageIcon(MainWindow.class.getResource(
"/com/sun/javafx/webkit/prism/resources/mediaPlayDisabled.png")));
controlPanel.add(btnNewButton);

JButton button = new JButton("");
button.setIcon(new ImageIcon(MainWindow.class.getResource(
"/com/sun/javafx/webkit/prism/resources/mediaPause.png")));
controlPanel.add(button);

JLabel label = new JLabel("");
label.setIcon(new ImageIcon(MainWindow.class.getResource(
"/com/sun/javafx/webkit/prism/resources/mediaMuteDisabled.png")));
controlPanel.add(label);

JSlider slider = new JSlider();
slider.setValue(100);//设置默认音量100
slider.setMaximum(120);//设置最大音量120
controlPanel.add(slider);
slider.addChangeListener(new ChangeListener() {
public void stateChanged(ChangeEvent arg0) {
//将音量条的值传递给播放器的音量控件
MainVideoPlayler.volume(slider.getValue());
}
});
//视频播放进度条
progress = new JProgressBar();
progress.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
//获得鼠标点击进度条时的横坐标x值
int x = e.getX();
//x除以进度条总长度为当前百分比
MainVideoPlayler.jumpTo(((float)x/progress.getWidth()));
}
});
progress.setStringPainted(true);
panel.add(progress, BorderLayout.NORTH);
button.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
MainVideoPlayler.pause();
}
});
btnNewButton.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent arg0) {
MainVideoPlayler.play();
}
});
btnNewButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent arg0) {
}
});
button_1.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
MainVideoPlayler.stop();
}
});
}
//定义一个方法,返回视频播放器
public EmbeddedMediaPlayer getMediaPlayer() {
return playerComponent.getMediaPlayer();
}
//定义一个方法,获得经度条的进度
public JProgressBar getProgressBar() {
return progress;
}
}

程序运行效果图:


界面

图:程序运行主界面

文件

图:菜单栏

选择文件

图:选择文件


导处程序:

第一步:

选中项目工程,单击鼠标右键,选择导出选项。点击后如下图,选择Java文件夹中的Runnable JAR file选项。

导出1

图:导出第一步,选择导出类型


第二步:

点击Launch configuration,进行选择要导出的主方法。我的主方法为MainVideoPlayer

导出2.1

图:导出第二步,选择导出类型主方法


第三步:

选择要导出的文件位置,一般选择放在本工程文件中的release文件夹中,此文件夹需新建。

导出2

图:导出第三步,选择导出文件位置


第四步:

选择导出文件库 包装类型,一般选择第二个,把所有需要库都打包。

导出4

图:导出第四步,选择导出包装类型


第五步:

导出完成,只要在有Java运行环境的电脑中,双击此文件即可运行程序。

导出5

图:第五步,导出完成


坚持原创技术分享,您的支持将鼓励我继续创作!