文章目录
前言
项目需求:老板要大屏显示视频,还可以用手机上的微信小程序控制暂停播放
播放视频谁不会?
MP4用爱奇艺播放器啊,迅雷影音啊,腾讯视频啊
树莓派播放?
树莓派专用系统Raspbian底层是Linux,也就是一片漆黑的命令窗口,也不支持那些exe安装的软件
一、使用技术
1.控制设备
使用mqtt,根据订阅的主题不一样进行分发指令
2.怎么窗口播放
这里使用的Swing,比较古老的窗口化,Java的Gui
3.视频卡死
减少线程个数,thread
4.远程显示
VPN可视化界面
5.远程命令链接
PUTTY,有人说用XShell,一样随个人喜好
6.文件传输
FileZilla,这个使用sftp就可以传输,有人说远程桌面,那需要安装xrdp,看个人喜好
二、视频播放
一、omxplayer播放
1.安装树莓派播放器
sudo apt-get install omxplayer
2.播放视频
sodo omxplayer -o hdmi /path/to/filename.mp4 --loop
缺陷:不能控制开始暂停,所以PASS
二.vlc播放
1.环境配置
(1)下载VLC VlC官网http://www.videolan.org/ 各个版本的下载地址http://download.videolan.org/pub/videolan/vlc/last/ 里面有32位和64位的区分,按照自己的系统下载对应的vlc版本,下载解压后提取;
(2)下载VLCJ (http://capricasoftware.co.uk/#/projects/vlcj)把下载文件解压后将其目录下的jna-3.5.2.jar、platform-3.5.2.jar、vlcj-3.8.0.jar(不同版本后缀数字可能会不同)三个文件复制到对应的java工程目录(新建 lib 文件夹)下;
如果是maven工程直接引入maven即可
(3)将vlc安装目录下的libvlc.dll、libvlccore.dll 两个文件以及plugins问佳佳复制到对应的java工程目录下;根目录
2.代码编写
播放器主类代码
package deng.test;
import java.awt.EventQueue;
import java.io.File;
import javax.swing.JFileChooser;
import javax.swing.SwingWorker;
import com.sun.jna.Native;
import com.sun.jna.NativeLibrary;
import uk.co.caprica.vlcj.binding.LibVlc;
import uk.co.caprica.vlcj.runtime.RuntimeUtil;
public class PlayerMain {
static Window frame;
private static int times=1;
private static boolean flag=true;
// private static final String NATIVE_LIBRARY_SEARCH_PATH = "D:\\Program
// Files\\VideoLAN\\VLC\\sdk\\lib";
public static void main(String[] args) {
// 环境配置,将vlc sdk导入到eclipse
// if(RuntimeUtil.isWindows()){ }
// NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(),
// "D:\\vlc\\vlc-2.2.6\\sdk\\lib"); //导入的路径是vlc的安装路径
NativeLibrary.addSearchPath(RuntimeUtil.getLibVlcLibraryName(), "vlcj//lib"); // 导入的路径是vlc的安装路径
Native.loadLibrary(RuntimeUtil.getLibVlcLibraryName(), LibVlc.class);
// System.out.println(LibVlc.INSTANCE.libvlc_get_version());
// 创建主程序界面运行窗体
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
frame = new Window();
frame.setVisible(true);
frame.getMediaPlayer().playMedia("video//style.avi"); // 直接播放视屏,参数是视屏文件的绝对路径
// frame.getMediaPlayer().prepareMedia("video//test.mp4");
// //控制即将播放的视频
new SwingWorker<String, Integer>() {
@Override
protected String doInBackground() throws Exception {
// TODO Auto-generated method stub
while (flag) { // 获取视频播放进度并且按百分比显示
long total = frame.getMediaPlayer().getLength();
if(total==-1){//如果视频播放完,循环播放视频
play();
times++;
System.out.println(times+"******************");
}
long curr = frame.getMediaPlayer().getTime();
float percent = (float) curr / total;
publish((int) (percent * 100));
Thread.sleep(100);
}
return null;
}
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 dispose(){
flag=false;
frame.getMediaPlayer().stop();
frame.dispose();
}
// 打开文件
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 exit() {
frame.getMediaPlayer().release();
System.exit(0);
}
// 实现播放按钮的方法
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 setVol(int v) {
frame.getMediaPlayer().setVolume(v);
}
}
播放器窗体类:
package deng.test;
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.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;
@SuppressWarnings("serial")
public class Window extends JFrame{
private JPanel contentPane; //顶层容器,整个播放页面的容器
private JMenuBar menuBar; //菜单栏
private JMenu mnFile,mnSetting,mnHelp; //文件菜单
private JMenuItem mnOpenVideo,mnExit; //文件菜单子目录,打开视屏、退出
private JPanel panel; //控制区域容器
private JProgressBar progress; //进度条
private JPanel progressPanel; //进度条容器
private JPanel controlPanel; //控制按钮容器
private JButton btnStop,btnPlay,btnPause; //控制按钮,停止、播放、暂停
private JSlider slider; //声音控制块
EmbeddedMediaPlayerComponent playerComponent; //媒体播放器组件
public static void main(String[] args) {
}
//MainWindow构造方法,创建视屏播放的主界面
public Window(){
setTitle(" 小婷婷专属播放器 Copyright@dengchaoqun");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
setBounds(200,80,900,600);
contentPane=new JPanel();
contentPane.setBorder(new EmptyBorder(5, 5, 5, 5));
contentPane.setLayout(new BorderLayout(0,0));
setContentPane(contentPane);
/*视频播放窗口中的菜单栏*/
menuBar=new JMenuBar();
setJMenuBar(menuBar);
mnFile=new JMenu("文件"); //设置菜单名
menuBar.add(mnFile);
mnSetting=new JMenu("设置");
menuBar.add(mnSetting);
mnHelp=new JMenu("帮助");
menuBar.add(mnHelp);
mnOpenVideo =new JMenuItem("打开文件"); //设置文件菜单子目录打开文件
mnFile.add(mnOpenVideo);
mnExit =new JMenuItem("退出"); //设置文件菜单子目录退出
mnFile.add(mnExit);
//打开文件
mnOpenVideo.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
PlayerMain.openVideo();
}
});
//退出
mnExit.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
// TODO Auto-generated method stub
PlayerMain.exit();
}
});
/*视屏窗口中播放界面部分*/
JPanel videoPane=new JPanel();
contentPane.add(videoPane, BorderLayout.CENTER);
videoPane.setLayout(new BorderLayout(0,0));
playerComponent=new EmbeddedMediaPlayerComponent();
videoPane.add(playerComponent);
/*视屏窗口中控制部分*/
panel=new JPanel(); //实例化控制区域容器
videoPane.add(panel,BorderLayout.SOUTH);
progressPanel=new JPanel(); //实例化进度条容器
panel.add(progressPanel, BorderLayout.NORTH);
//添加进度条
progress=new JProgressBar();
progressPanel.add(progress);
//panel.add(progress,BorderLayout.NORTH);
progress.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e){ //点击进度条调整视屏播放进度
int x=e.getX();
PlayerMain.jumpTo((float)x/progress.getWidth());
}
});
progress.setStringPainted(true);
controlPanel=new JPanel(); //实例化控制按钮容器
panel.add(controlPanel,BorderLayout.SOUTH);
//添加停止按钮
btnStop=new JButton("停止");
btnStop.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
PlayerMain.stop();
}
});
controlPanel.add(btnStop);
//添加播放按钮
btnPlay=new JButton("播放");
btnPlay.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
PlayerMain.play();
}
});
controlPanel.add(btnPlay);
//添加暂停按钮
btnPause=new JButton("暂停");
btnPause.addMouseListener(new MouseAdapter() {
@Override
public void mouseClicked(MouseEvent e) {
// TODO Auto-generated method stub
//PlayerMain.dispose();
PlayerMain.pause();
}
});
controlPanel.add(btnPause);
//添加声音控制块
slider=new JSlider();
slider.setValue(80);
slider.setMaximum(100);
slider.addChangeListener(new ChangeListener() {
@Override
public void stateChanged(ChangeEvent e) {
// TODO Auto-generated method stub
PlayerMain.setVol(slider.getValue());
}
});
controlPanel.add(slider);
}
//获取播放媒体实例(某个视频)
public EmbeddedMediaPlayer getMediaPlayer() {
return playerComponent.getMediaPlayer();
}
//获取进度条实例
public JProgressBar getProgressBar() {
return progress;
}
}
缺陷:windows开发的不支持Linux,所以Pass
三.JavaFX播放
1.不要看官网,直接开撸
看了FX半天的官网,什么JDK环境必须11+,什么插件安装,什么dll安装,总结四个字:一派胡言
2.直接上代码:
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ToggleButton;
import javafx.scene.control.ToggleGroup;
import javafx.scene.layout.HBox;
import javafx.scene.layout.VBox;
import javafx.scene.media.Media;
import javafx.scene.media.MediaPlayer;
import javafx.scene.media.MediaView;
import javafx.scene.text.Font;
import javafx.stage.Stage;
import javafx.util.Duration;
import java.io.File;
/**
* @Author: 一蓑烟雨
* @Description: 音频、视频播放Demo
* @Date: 2021/6/3 21:46
* @Version: 1.0
*/
public class MediaDemo extends Application{
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage){
// 音频或视频的路径
// 举例中的路径为工程根目录下的test.mp4
// 如果不能正常播放,则音频或视频文件可能损坏;或者有版权,需对应的播放器正常播放;或者录屏后重新尝试,避过版权问题
//String url = new File(System.getProperty("user.dir") + "/test.mp4").getAbsoluteFile().toURI().toString();
File url = new File("D://131.mp4");
//String s = url.getAbsoluteFile().toURI().toString();
String s = "http://222.133.14.246:19091//hnyfkj-file-server/plugins/im/mp4/20210603/131.mp4";
//String url = "D://131.mp4";
Media media = new Media(s);
MediaPlayer mediaPlayer = new MediaPlayer(media);
// 设置音量:0.0 - 1.0
mediaPlayer.setVolume(0.5);
// 设置开始时间
mediaPlayer.setStartTime(Duration.seconds(1));
MediaView mView = new MediaView(mediaPlayer);
System.out.println(media.getSource());
VBox vBox = new VBox(3);
vBox.getChildren().add(mView);
vBox.setPrefWidth(580);
vBox.setPrefHeight(360);
mView.setFitWidth(vBox.getPrefWidth());
mView.setFitHeight(vBox.getPrefHeight() - 40);
int fontSize = 16;
ToggleGroup toggleGroup = new ToggleGroup();
ToggleButton playButton = new ToggleButton("播放");
playButton.setFont(new Font(fontSize));
playButton.setOnMouseClicked(event -> mediaPlayer.play());
playButton.setToggleGroup(toggleGroup);
ToggleButton suspendButton = new ToggleButton("暂停");
suspendButton.setFont(new Font(fontSize));
suspendButton.setOnMouseClicked(event -> mediaPlayer.pause());
suspendButton.setToggleGroup(toggleGroup);
ToggleButton continueButton = new ToggleButton("继续");
continueButton.setFont(new Font(fontSize));
continueButton.setOnMouseClicked(event -> mediaPlayer.play());
continueButton.setToggleGroup(toggleGroup);
ToggleButton closeButton = new ToggleButton("结束");
closeButton.setFont(new Font(fontSize));
closeButton.setOnMouseClicked(event -> mediaPlayer.stop());
closeButton.setToggleGroup(toggleGroup);
HBox hBox = new HBox(3);
hBox.getChildren().addAll(playButton, suspendButton, continueButton, closeButton);
vBox.getChildren().add(hBox);
Scene scene = new Scene(vBox,580,360);
primaryStage.setTitle("MediaDemo");
primaryStage.setScene(scene);
primaryStage.show();
}
}
缺陷:在树莓派系统播放总是Mtqq报错,所以Pass(具体原因还在排查)
三.vlcj播放
vlcj比vlc多了一个字母J,有啥区别?具体区别我也不清楚,不过这个比那个适应力更强,不需要记载本地dll,所以跨平台性比较高,然后可以在任何平台依附平台播放器的安装位置来播放
1.环境搭建
跟clv环境是一样的只不过不需要复制plugs和dll到项目中,因为vlcj是跨平台的,所以Linux不能加载dll,不需要加在dll了
2.代码
播放器代码的实现:
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().setRepeat(true);
//让窗体获得视频资源
frame.getMediaPlayer().prepareMedia(
"D:\\xxxx.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);
}
}
缺陷:在树莓派系统播放播放一小时会卡关机,但是有思路,我准备先把视频加载缓存到本地,然后进行播放是不是会好点(树莓派本身运行内存就小,所以播放视频还是有难度的,一半用来做嵌入式开发会好一些,播放视频用windows会好点)
总结
方法不同,效果也不同,优缺点也不同,看个人喜好