目标:
制作一个简易的视频播放器,实现对视频文件的打开,播放,暂停,退出,以及实现进度条的显示,通过点击视频播放进度条可以更改视频的播放时间。还添加调节音量的功能。
工程的准备:
因为通过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文件夹需自建。
图:所需要的三个文件
二、下载slf4j库后,解压,将其中的slf4j-api-1.7.25.jar和slf4j-nop-1.7.25.jar,两个文件添加到java工程的lib文件夹中。把添加好的库添加到构建路径中,用来引用。工程结构如下图:
图:工程结构图
关于vlcj库使用说明:
关于vlcj库的使用,具体可点击:Vlcj查看。在这个Java工程中,首先使用是按照官方给出的例子使用。
第一步使用自动发现本地库:
//NativeDiscovery().discover();函数返回的是一个布尔类型的值,所有可以定义一个布尔类型的值,用来接收,利用控制台打印,是否发现本地库
boolean found = new NativeDiscovery().discover();
System.out.println(found);
官方提示原代码:
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路径。
//指定VLC路径,这里使用的路径是安装默认路径。
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), "C:\\Program Files\\VideoLAN\\VLC");
//打印版本,用来检验是否获得文件
System.out.println(LibVlc.INSTANCE.libvlc_get_version());
官方原代码:
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());
}
}
图:使用说明
只有当运行代码后,控制台什么都没有输出,一切正常,证明准备工作已做好,可以进行下面的进程。
行
图:运行后,控制台正常
播放器代码的实现:
主方法代码:
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() {
//调节视频音量
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 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);
}
}
窗体代码实现:
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选项。
图:导出第一步,选择导出类型
第二步:
点击Launch configuration,进行选择要导出的主方法。我的主方法为MainVideoPlayer。
图:导出第二步,选择导出类型主方法
第三步:
选择要导出的文件位置,一般选择放在本工程文件中的release文件夹中,此文件夹需新建。
图:导出第三步,选择导出文件位置
第四步:
选择导出文件库 包装类型,一般选择第二个,把所有需要库都打包。
图:导出第四步,选择导出包装类型
第五步:
导出完成,只要在有Java运行环境的电脑中,双击此文件即可运行程序。
图:导出第四步,完成