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

posted @ 2022-08-15 06:06  qsBye  阅读(1401)  评论(0编辑  收藏  举报