ffmpeg以RTP协议推送视频
docker编译环境
docker pull abdulachik/ffmpeg.js:latest
docker run -it -p 8080:8080 -v /Users/workspace/Downloads/ffmpeg_wasm:/tmp --privileged=true abdulachik/ffmpeg.js:latest /bin/bash
cd /tmp
流程概述
摄像头->ffmpeg->编码为h264视频->传递给h264解码器->播放
(也可以让视频编码后直接RTMP协议推流,本地解码播放仅作测试)
ffmpeg编码视频流(来自摄像头)为flv(h264)
读取PC摄像头视频数据并以RTMP协议发送为直播流。
ffmpeg综合应用示例(一)——摄像头直播
浏览器可通过调用MediaDevices.getUserMedia()来访问本地媒体,调用该方法后浏览器会提示用户给予使用媒体输入的许可,媒体输入会产生一个MediaStream,里面包含了请求的媒体类型的轨道。此流可以包含一个视频轨道(来自硬件或者虚拟视频源,比如相机、视频采集设备和屏幕共享服务等等)、一个音频轨道(同样来自硬件或虚拟音频源,比如麦克风、A/D转换器等等),也可能是其它轨道类型。
谈谈MediaStream
FFmpeg获取DirectShow设备数据(摄像头,录屏)
流媒体协议
- RTP:基于UDP协议,不保证传输质量
- RTCP
- RTSP
- RTMP
- MMS
- HLS
编码为H.264,发布RTP
下面这条命令,实现了:获取摄像头数据->编码为H.264->封装为RTP并发送至组播地址。
ffmpeg -f dshow -i video="Integrated Camera" -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -f rtp rtp://233.233.233.223:6666>test.sdp
注1:考虑到提高libx264的编码速度,添加了-preset:v ultrafast和-tune:v zerolatency两个选项。
注2:结尾添加“>test.sdp”可以在发布的同时生成sdp文件。该文件可以用于该视频流的播放。
下面这条命令,实现了从摄像头读取数据并编码为H.264,最后保存成mycamera.mkv。
ffmpeg -f dshow -i video="Integrated Camera" -vcodec libx264 mycamera.mkv
编码为MPEG2,发布UDP
与编码为H.264类似,指明-vcodec即可。
ffmpeg -f dshow -i video="Integrated Camera" -vcodec mpeg2video -f mpeg2video udp://233.233.233.223:6666
浏览器上实现编码为H.264并发布RTP
假设获取到的浏览器视频流为MediaStream
写成命令形式为:
ffmpeg -f dshow -i video="MediaStream" -vcodec libx264 -preset:v ultrafast -tune:v zerolatency -s 320x240 -f rtp rtp://192.168.4.1 > cam_h264.sdp
require.js
用于引入包
html文件中(js文件都在同级目录下)
main.js
require(['ffmpeg'],function(main){
});
本地调试网页
npm install -g http-server
cd 目录
http-server
cd 目录
python3 -m http.server
es6标准可用import导入模块
import * as ffmpeg from "ffmpeg-mp4";
npm(node.js)使用帮助
查看安装的模块 npm ls -g --depth 0
npm ls
查看模块帮助 npm help hexo
但是如果查看ffmpeg.js模块,需要其他方法
全局包安装路径/usr/local/lib/node_modules
其他包安装路径ls ./node_modules(就是当前工作目录)
ffmpeg.js文件(下载即用)
ffmpeg-mp4.js -- 支持mp4格式文件的编解码等
ffmpeg-webm.js
ffmpeg-worker-mp4.js -- 优化的文件
ffmpeg-worker-webm.js -- 优化的文件
shim
通过require.js加载的模块一般都需要符合AMD规范即使用define来申明模块,但是部分时候需要加载非AMD规范的js,这时候就需要用到另一个功能:shim,shim解释起来也比较难理解,shim直接翻译为"垫",其实也是有这层意思的。
非AMD模块输出,将非标准的AMD模块"垫"成可用的模块,例如:在老版本的jquery中,是没有继承AMD规范的,所以不能直接require["jquery"],这时候就需要shim,比如我要是用老版本jquery类库,但是他并没有实现AMD规范,那我们可以这样配置
require.config({
baseUrl: "javascript",
//packages: ['carousel'],
paths: {
jquery: 'lib/jquery.1.6',
bootstrap: 'lib/bootstrap'
},
shim: {
"jquery" : {
exports : "$"
}
}
});
require.js和node.js调用函数区别
- require.js是AMD(异步模块定义,Asynchronous Module Definition)规范
- node.js的require是commonJS规范
浏览器调用命令行程序
[https://zhuanlan.zhihu.com/p/27910351]
在执行最后一步之前,有个疑问,ffmpeg正常编译出来的二进制应该是个命令行文件,接受命令行参数执行操作。但当我们把它编译到js里时,该怎么向它传递参数呢?传递了参数之后又要怎么样才能拿到它的执行结果呢?
理想的状况下,我们希望最终编译出来的wasm/asm.js文件能向外export一个函数来作为入口,我们通过这个函数入口传入参数,通过返回值或者回调函数等方法获取结果。
其实这就是wasm/asm.js文件和浏览器js的信息通信问题,Emscripten为我们提供了这样一些解决方案,Emscripten官网文档 API Reference - Emscripten 1.37.10 documentation
WebRTC
WebRTC实现了基于网页的视频会议,标准是WHATWG 协议,目的是通过浏览器提供简单的javascript就可以达到实时通讯(Real-Time Communications (RTC))能力。
如果一个服务端实现了WebRTC客户端的能力,那么它也可以被认为是一个Peer,与用户浏览器的WebRTC客户端创建连接,获得客户端推送过来的媒体数据,就完成了Peer to Server的转换。
go语言WebRTC实现,对于esp32的Xtensa架构(32位处理器)支持不佳.
WebRTC 研究系列 二、打通webrtc与rtmp