admin管理员组文章数量:1533920
概述
本章主要讲解实际工作中遇到的问题,以及如何解决并实现,下面是音视频开发的常用工具,下载地址就不贴了。
VLC media player 视频流播放工具
MediaInfo 视频信息查看工具
开发人员:app(负责开发板),java(负责服务器,进行编解码)
一.通过海康sdk获取视频流
海康提供的sdk录像功能,然后保存到sd卡中,当客户端有人想看这个视频时,去sd卡中拿视频
实现步骤:
1.当开发板生成视频,将视频路径以及设备id信息通知后端服务器,服务器将数据展示在web界面中.
2.当web界面,有人想看某个视频,将视频路径传到服务器,服务器通过websocket和开发板通信(这里之所以用websocket,是因为板子没有公网ip,所以它可以访问服务器,因为nat或其他技术,但是服务器无法直接访问这块板子,所以需要,板子一上电,就和服务器建立一个双通道的websocket,这样双方就可以交换数据了),根据协议,封装数据报,并发送。
3,开发板根据和服务器协商好的协议(类似于网络协议,便于双方知道对方想干什么),知道服务器要看视频,然后解析视频路径,然后去sd卡中获取,然后将文件流(stream)传到服务器,服务器接收到流,在返回给web客户端。
遇到的问题:
1.浏览器如何播放视频?
2.sd卡中保存的视频的封装格式是MPEG-PS,普通播放器无法播放,需要转码
问题1:浏览器如何播放视频?
1.前端可以拿到文件流,具体就是byte数组,然后转成base64,赋值给vedio标签,但是这样有个问题如果视频较小,这么做可以,但是如果视频是几十兆的这种,时间会比较久,低配的电脑,可能浏览器会出现卡死的情况,所以这种方案即便可以,但是用户体验也不是太好,因为base64转码会比原文件,多出三分之一的大小,这种实现的最大弊端就是,由于是通过文件流传输,从开发板到服务器,再从服务器到web,耗时太久,网络不是很好的话,耗时还会增加,所以这种方式肯定是有问题的。
**2.开发板将文件流传给服务器,服务器将流上传至文件服务器,然后返回一个公网可以访问的url,然后将这个视频和url做一个映射(map),别人在看这个视频,就可以通过映射关系,拿到url,将url返回到web,vedio可以直接播放,这种方式有个好处,多个人看一个视频的时候,视频只需要传递一次,就可以,至于为什么开发板生成视频后就上传到文件服务器,因为一些原因(板子有sd卡,视频生成是因为发生了故障xxx等,所以不需要放到服务器),但是需要定时器,在文件服务器去删除视频,目前我们使用是这种方式。
问题2: sd卡中保存的视频的封装格式是MPEG-PS,普通播放器无法播放,需要转码
解决问题1的时候发现一个问题,将开发板上的文件流,上传到服务器,发现服务器的视频无法播放,经MediaInfo 查看,发现,视频的封装格式为MPEG-PS,这种视频,普通的播放器无法播放的,更别说浏览器自带的了,可以通过万能播放器软件等播放,但是,我们最终是要把视频展示在h5当中,所以,需要进行转码,转成浏览器可以播放的视频格式,查看一些博客和资料,最后发现,可以通过ffmpeg 这个软件,进行编解码,具体资料以及使用方式,可以去雷神的博客学习https://blog.csdn/leixiaohua1020/article/details/15811977,注意不同的版本所支持的编解码器不同,根据业务需要使用的编解码器,去下载指定的版本,linux部署的时候踩了不少坑,这里给的下载地址都是可以放心使用的,作者都亲测过.
这里具体说明使用方式:
windows安装:
进入官网,选择需要下载的文件:
官方网址
下载以后,解压到所放置的文件夹:
配置环境变量的步骤如下:
1.打开我的电脑
2.右键鼠标,点击属性
3.选择高级系统设置,然后点击下方的环境变量
4.在系统变量中,找到变量Path,点击值进行编辑,新增一条记录
5.C:\ffmpeg\bin 你自己的安装目录,注意要到bin
6.使用cmd命令,查看ffmpeg版本,如果正常显示
centos7安装教程:
(1).https://blog.csdn/u013314786/article/details/89682800
(2).https://linuxize/post/how-to-install-ffmpeg-on-centos-7/
linux中这两种方式不需要配置环境变量,如果想要在任意路径使用命令,就需要配置环境变量了,我这里使用的是方式(1)然后每次使用命令都需要到ffmpeg的安装目录下
mac安装
1.官网 https://evermeet.cx/ffmpeg/
mac可以通过brew直接安装的,但是作者这里一直失败,所以用了官网安装
2.选择进行下载
3.下载完成后进行解压,然后放到你自己的目录下,我这里直接放到桌面上的ffmpeg文件夹下了, 我本地安装目录就是:/Users/moch/Desktop/ffmpeg
4.配置环境变量,其实不配也可以,但是你只能在/Users/moch/Desktop/ffmpeg目录下使用ffmpeg命令,我这里配置了全局环境变量,具体如下
5.终端
1. cd ~
2. 使用ls -a可以看到.bash_profile文件
3. vi .bash_profile
//后面的值是你自己的安装路径,切记切记,如果你的path有多个,需要使用:分割
5. 添加 export PATH="/Users/moch/Desktop/ffmpeg"
// 让配置生效
6. source .bash_profile
通过在命令行输入ffmpeg,如出现下图中显示的信息,表示安装成功,图中有版本号,以及当前版本中的编解码器,这里安装结束后,我们测试下,看看是否可以转码为我们想要的格式。
在windows命令行输入
ffmpeg -i c:/video1.MP4 -vcodec libx264 -c:a aac c:/video.flv
其中 -i 后面是源数据 最后面的c:/video.flv是输出路径
至于libx264,aac一个是视频编码,一个是音频编码,因为我需要转成的视频格式为flv,flv的视频编码和音频编码,是avc和aac,至于参数的意思,这里就不详细讲解了,有兴趣的朋友可以去上面发的雷神的博客,或者网上自己学习
最终,生成的flv视频,通过MediaInfo查看
然后通过播放器,可以播放,说明视频转码成功,但是这里只是通过ffmpeg的软件进行操作的,实际操作中,不可能让用户这样操作,所以需要通过代码,调用ffmpeg的接口,进行转码,代码如下(前提是当前电脑的操作系统中,以及安装好了ffmpeg,并且可以正常使用)
配置类
package com.mochitec.hikbox.util;
import lombok.Data;
@Data
public class ConvertProperties {
//linux下,路径肯定不是这样,是/root/xx这样子
private String inputPath = "C:\\Users\\mochu\\Desktop\\video.MP4";
private String outputPath = "C:\\Users\\mochu\\Desktop\\video4.flv";
private String ffmpegPath = "C:\\wym\\ffmpeg\\bin\\"; //linux中,路径为 /root/moch/ffmpeg-4.4-amd64-static/ 你自己在linux服务器上安装的路径
private String convertFlag = "_wait";
}
package com.mochitec.hikbox.util;
import java.io.InputStream;
public class PrintStream extends Thread {
InputStream __is = null;
public PrintStream(InputStream is)
{
__is = is;
}
public void run()
{
try
{
while(this != null)
{
int _ch = __is.read();
if(_ch != -1)
System.out.print((char)_ch);
else break;
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
}
转码类
package com.mochitec.hikbox.util;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
public class ConvertService {
public boolean processMp4(String inputPath,String outputPath,String ffmpegPath) {
List<String> command = new ArrayList<>();
command.add(ffmpegPath + "ffmpeg");
command.add("-r");
command.add("25");
command.add("-i");
command.add(inputPath);
// command.add("-c:v");
command.add("-vcodec");
command.add("libx264");
command.add("-mbd");
command.add("0");
command.add("-c:a");
command.add("aac");
command.add("-s");
command.add("720*720");
command.add("-threads"); //指定同时启动线程执行数, 经测试到10再大速度几无变化
command.add("25");
command.add("-preset");
command.add("ultrafast");
command.add("-strict");
command.add("-2");
command.add("-pix_fmt");
command.add("yuv420p");
command.add("-movflags");
command.add("faststart");
command.add(outputPath);
try {
// 方案1
// Process videoProcess = Runtime.getRuntime().exec(ffmpegPath + "ffmpeg -i " + oldfilepath
// + " -ab 56 -ar 22050 -qscale 8 -r 15 -s 600x500 "
// + outputPath + "a.fl\\\\\\\\\\\\\v");
// 方案2
Process videoProcess = new ProcessBuilder(command).redirectErrorStream(true).start();
new PrintStream(videoProcess.getErrorStream()).start();
new PrintStream(videoProcess.getInputStream()).start();
videoProcess.waitFor();
System.out.println("转换完成");
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 删除文件方法
*
* @param filepath
*/
public void deleteFile(String filepath) {
File file = new File(filepath);
if (file.delete()) {
System.out.println("文件" + filepath + "已删除");
}
}
}
package com.mochitec.hikbox;
import com.mochitec.hikbox.util.ConvertProperties;
import com.mochitec.hikbox.util.ConvertService;
class HikboxApplicationTests {
public static void main(String[] args) {
ConvertService convertService = new ConvertService();
ConvertProperties convertProperties = new ConvertProperties();
//参数为,源文件路径,目标文件路径,以及ffmpeg的安装路径
convertService.processMp4(convertProperties.getInputPath(),
convertProperties.getOutputPath(), convertProperties.getFfmpegPath());
}
通过main进行调用,就可以转码了。至于实际业务中,调用,这些参数肯定是动态传递的,这里需要注意的是,在linux下,注意ffmpeg的安装路径,如果错误,程序运行后,会报找不到命令的错误,至此视频的转码工作完成,这里需要注意的是,需要源文件在服务器上存在,才可以这么做,所以我是先上传到服务器,然后将源文件删除掉的。最后将转换后的文件路径,传递给h5,linux下如果想让文件可以在公网访问,需要进行代理,一种是nginx,一种是tomcat,我这里使用的是tomcat,需要注意的是,如果想在url查看目录,需要配置tomcat的web.xml,默认是关闭查看的,因为这样有数据泄露。具体如何在tomcat配置如下
https://blog.csdn/wdays83892469/article/details/87944688
https://blog.csdn/wangduanqing5945/article/details/30266935
前端直接访问视频资源,会有跨域的问题,所以需要在tomcat里web.xml配置
<filter>
<filter-name>CORS</filter-name>
<filter-class>com.thetransactioncompany.cors.CORSFilter</filter-class>
<init-param>
<param-name>cors.allowOrigin</param-name>
<param-value>*</param-value>
</init-param>
<init-param>
<param-name>cors.supportedMethods</param-name>
<param-value>GET, POST, HEAD, PUT, DELETE</param-value>
</init-param>
<init-param>
<param-name>cors.supportedHeaders</param-name>
<param-value>Accept, Origin, X-Requested-With, Content-Type, Last-Modified</param-value>
</init-param>
<init-param>
<param-name>cors.exposedHeaders</param-name>
<param-value>Set-Cookie</param-value>
</init-param>
<init-param>
<param-name>cors.supportsCredentials</param-name>
<param-value>true</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>CORS</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
看到文章末尾的,可以看下的我的程序人生这篇文章,主要是讲我在编程这条路上的经历,祝愿对你有用,感谢!
版权声明:本文标题:音视频实战(海康视频预览,通过ffmpeg转码) 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://m.elefans.com/dongtai/1726867712a1087631.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论