3种ffmpeg-web端视频直播推流方案

记录了三种 ffmpeg 工具进行推流的方法,并在web端实现直播效果。

一. node-media-server + ffmpeg 推流rtmp

安装node-media-server依赖,新建app.js运行

npm install node-media-server -g

const  NodeMediaServer  = require('node-media-server');
const config = {rtmp: {port: 1935,chunk_size: 60000,gop_cache: true,ping: 60,ping_timeout: 30},http: {port: 8000,allow_origin: '*'}
};
var nms = new NodeMediaServer(config);
nms.run();

node app.js

执行ffmpeg推流

官网下载ffmpeg并配置把bin目录添加到环境变量
ffmpeg -version 查看版本
mpeg -list_devices true -f dshow -i dummy 查看可用以音视频设备

使用本地摄像头推流

ffmpeg -f dshow -i video="Integrated Camera":audio="麦克风阵列 (Synaptics SmartAudio HD)" -vcodec libx264 -acodec copy -preset:v ultrafast -tune:v zerolatency -f flv "rtmp://192.168.20.107:1935/live/home"

使用网络摄像头推流

ffmpeg -threads 5 -i rtsp://admin:px123456@192.168.20.100:554/Streaming/Channels/101 -tune zerolatency -preset ultrafast -vcodec libx264 -threads 5 -b:v 400k -s 720x576 -r 25 -acodec libfaac -b:a 64k -f flv rtmp://192.168.20.107:1935/live/home

rtsp://{账号}:{密码}@{ip}:{端口}/根据摄像头厂牌区分

rtmp://{本地ip}:1935/live/home

本地ip地址要设置为与网络摄像头同一网段

web端HTML页面

因为各浏览器不再支持flash,需要使用flv.js插件
 

<!DOCTYPE html>
<html>
<head><meta charset="UTF-8"><title></title>
</head>
<body>
<script src="https://cdn.bootcss.com/flv.js/1.4.0/flv.min.js"></script>
<video id="videoElement" style="width: 80%;" controls="controls"></video>
<script>if (flvjs.isSupported()) {//检查flvjs能否正常使用var videoElement = document.getElementById('videoElement');//使用id选择器找到第二步设置的dom元素var flvPlayer = flvjs.createPlayer({//创建一个新的flv播放器对象type: 'flv',//类型flvurl: 'http://192.168.20.107:8000/live/home.flv'//flv文件地址},{enableWorker: true,enableStashBuffer: false,stashInitialSize: 128});flvPlayer.attachMediaElement(videoElement);//将flv视频装载进video元素内flvPlayer.load();//载入视频flvPlayer.play();//自动播放}
</script>
</body>
</html>

【免费分享】音视频学习资料包、大厂面试题、技术视频和学习路线图,资料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以点击788280672加群免费领取~

二. nginx + ffmpeg 推流hls

hls流延迟比较大,按官方的说法60秒内算正常!

下载安装nginx

Windows下安装方法:www.cnblogs.com/qfb620/p/55…

Linux下安装:blog.csdn.net/wenqiangluy…

配置nginx

修改配置文件:/conf/nginx.conf ,在server内添加:
 

location /hls {root html;#add_header Cache-Control no-cache;add_header Access-Control-Allow-Origin *;
}

修改配置文件:/conf/mime.types ,在types内添加:

application/vnd.apple.mpegurl m3u8;
application/x-mpegURL m3u8;
video/mp2t ts;

ffmpeg推流:

要在html目录下创建hls目录
ffmpeg -i "rtsp://admin:px123456@192.168.20.100:554/Streaming/Channels/101" -vcodec libx265 -threads 5 -preset ultrafast -c copy -f hls -hls_time 5.0 -hls_list_size 1 15 D:/tool/Science/nginx-1.18.0/html/hls/test.m3u8

1. -hls_time n: 设置每片的长度,默认值为2。单位为秒
2. -hls_list_size n:设置播放列表保存的最多条目,设置为0会保存有所片信息,默认值为5
3. -hls_wrap n:设置多少片之后开始覆盖,如果设置为0则不会覆盖,默认值为0.这个选项能够避免在磁盘上存储过多的片,而且能够限制写入磁盘的最多的片的数量
4. -hls_start_number n:设置播放列表中sequence number的值为number,默认值为0

web端HTML页面

需要使用video.js插件
<!DOCTYPE html>
<html lang="en" dir="ltr"><head><meta charset="utf-8"><title>video.js</title><link href="https://unpkg.com/video.js@6.11.0/dist/video-js.min.css" rel="stylesheet"><script src="https://unpkg.com/video.js@6.11.0/dist/video.min.js"></script><script src="https://unpkg.com/videojs-flash/dist/videojs-flash.js"></script><script src="https://unpkg.com/videojs-contrib-hls/dist/videojs-contrib-hls.js"></script></head><body><video id="my-player" class="video-js" controls><source src="http://localhost/hls/test.m3u8" type="application/x-mpegURL"><p class="vjs-no-js">not support</p></video><script type="text/javascript">var player = videojs('my-player',{width:400,heigh:200});</script></body>

三. 通过webSocket发送MPEG,前端解析MPEG绘制canvas

这是我试过延迟最小的方法,0.5秒左右,但是非常耗cpu。

创建app.js,安装WebSocket等相应模块

var fs = require('fs'), http = require('http'), WebSocket = require('ws');// console.log(process.argv)
if (process.argv.length < 3) {// console.log('输入正确参数');process.argv[2]='supersecret';process.argv[3]='8081';process.argv[4]='8082';
// 	process.exit();
}var stream_secret = process.argv[2];//密码
var stream_port = process.argv[3] || 8081;//ffpeng推送端口
var websocket_port = process.argv[4] || 8082;//前端websocket端口 ,比如:8082
var record_stream = false;
var totalSize = 0;function initWebSocket(websocket_port) {var clientMap = new Map();//缓存,实现多个视频流同时播放的问题var socketServer = new WebSocket.Server({port : websocket_port,perMessageDeflate : false});socketServer.on('connection', function(socket, upgradeReq) {var url = upgradeReq.socket.remoteAddress + upgradeReq.url;var key = url.substr(1).split('/')[1];//key就是通过url传递过来的标识比如:(ws://127.0.0.1:8082/live3)其中live3就是这个标识,其他的流可随机生成其他的字符串var clients = clientMap.get(key);if(!clients){clients = new Set();clientMap.set(key,clients);}clients.add(socket);totalSize++;process.stdout.write("[INFO]:a new connection, the current number of connections: " + totalSize + ".\r");socket.on('close', function(code, message) {var clientSet = clientMap.get(key);if(clientSet){clientSet.delete(socket);totalSize--;if(clientSet.size == 0){clientMap.delete(key);}}process.stdout.write("[INFO]:close a connection, the current number of connections:" + totalSize + ".\r");});});socketServer.broadcast = function(data, theme) {var clients = clientMap.get(theme);if (clients) {clients.forEach(function (client, set) {if(client.readyState === WebSocket.OPEN){client.send(data);}});}};return socketServer;
}function initHttp(stream_port, stream_secret, record_stream, socketServer) {var streamServer = http.createServer(function(request, response) {var params = request.url.substr(1).split('/');if (params.length != 2) {process.stdout.write("\n[ERROR]:Incorrect parameters, enter password and push theme");response.end();}if (params[0] !== stream_secret) {process.stdout.write("\n[ERROR]:Password error: "+request.socket.remoteAddress+":"+request.socket.remotePort+"");response.end();}response.connection.setTimeout(0);request.on('data', function(data) {socketServer.broadcast(data, params[1]);if (request.socket.recording) {request.socket.recording.write(data);}});request.on('end', function() {process.stdout.write("\n[INFO]:close request");if (request.socket.recording) {request.socket.recording.close();}});if (record_stream) {var path = 'recordings/' + Date.now() + '.ts';request.socket.recording = fs.createWriteStream(path);}}).listen(stream_port);console.log('started rtsp WebSocket service in secret is [%s], service port is [%s], ws port is [%s].',stream_secret,stream_port,websocket_port);
}initHttp(stream_port, stream_secret, record_stream,initWebSocket(websocket_port));

执行ffmpeg(封装run.js)

我把ffmpeg命令封装成js文件,以方便执行多条命令。
require('shelljs/global');var version = exec('node --version', {silent:true}).output;exec(`ffmpeg -i "rtsp://admin:px123456@192.168.3.21:554/Streaming/Channels/101" -q 0 -f mpegts -codec:v mpeg1video -s 1680x945 http://127.0.0.1:8081/supersecret/live1`, function(status, output) {console.log('Exit status:', status);console.log('Program output:', output);
});
exec(`ffmpeg -i "rtsp://admin:px123456@192.168.3.21:554/Streaming/Channels/101" -q 0 -f mpegts -codec:v mpeg1video -s 1680x945 http://127.0.0.1:8081/supersecret/live2`, function(status, output) {console.log('Exit status:', status);console.log('Program output:', output);
});
exec(`ffmpeg -i "rtsp://admin:px123456@192.168.3.21:554/Streaming/Channels/101" -q 0 -f mpegts -codec:v mpeg1video -s 1680x945 http://127.0.0.1:8081/supersecret/live3`, function(status, output) {console.log('Exit status:', status);console.log('Program output:', output);
});
exec(`ffmpeg -i "rtsp://admin:px123456@192.168.3.21:554/Streaming/Channels/101" -q 0 -f mpegts -codec:v mpeg1video -s 1680x945 http://127.0.0.1:8081/supersecret/live4`, function(status, output) {console.log('Exit status:', status);console.log('Program output:', output);
});

创建index.html

需要使用 jsmpeg.js插件
页面要运行到服务器中!
<!DOCTYPE html>
<html>
<head><title></title><style type="text/css">html, body {text-align: center;}</style></head>
<body><canvas id="video-canvas"></canvas><canvas id="video-canvas1"></canvas><canvas id="video-canvas2"></canvas><canvas id="video-canvas3"></canvas><script type="text/javascript" src="jsmpeg.min.js"></script><script type="text/javascript">var canvas = document.getElementById('video-canvas');var url = 'ws://ip:8082/live1';var player = new JSMpeg.Player(url, {canvas: canvas,});console.log(player)var canvas1 = document.getElementById('video-canvas1');var url1 = 'ws://ip:8082/live2';var player1 = new JSMpeg.Player(url1, {canvas: canvas1});var canvas2 = document.getElementById('video-canvas2');var url2 = 'ws://ip:8082/live3';var player2 = new JSMpeg.Player(url2, {canvas: canvas2});var canvas3 = document.getElementById('video-canvas3');var url3 = 'ws://ip:8082/live4';var player3 = new JSMpeg.Player(url3, {canvas: canvas3});</script>
</body>
</html>

原文链接 3种ffmpeg-web端视频直播推流方案 - 掘金

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/416894.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

CentOS上安装Mellanox OFED

打开Mellanox官网下载驱动 Linux InfiniBand Drivers 点击下载链接跳转至 Tgz解压缩执行 ./mlnxofedinstall发现缺少模块 # ./mlnxofedinstall Logs dir: /tmp/MLNX_OFED_LINUX.11337.logs General log file: /tmp/MLNX_OFED_LINUX.11337.logs/general.log Verifying KMP rpm…

Codeforce s Round 920 (Div. 3) G题 旋转矩阵,斜缀和,平移

Problem - G - Codeforces 目录 题意&#xff1a; 思路&#xff1a; 总思路&#xff1a; 旋转矩阵&#xff1a; 前缀和预处理&#xff1a; 平移的处理&#xff0c;尤其是越界的处理&#xff1a; 核心代码&#xff1a; 题意&#xff1a; 给你个n*m的矩阵&#xff0c;里…

验证回文串[简单]

优质博文&#xff1a;IT-BLO-CN 一、题目 如果在将所有大写字符转换为小写字符、并移除所有非字母数字字符之后&#xff0c;短语正着读和反着读都一样。则可以认为该短语是一个回文串。 字母和数字都属于字母数字字符。 给你一个字符串s&#xff0c;如果它是回文串&#xff…

李沐《动手学深度学习》多层感知机 深度学习相关概念

系列文章 李沐《动手学深度学习》预备知识 张量操作及数据处理 李沐《动手学深度学习》预备知识 线性代数及微积分 李沐《动手学深度学习》线性神经网络 线性回归 李沐《动手学深度学习》线性神经网络 softmax回归 李沐《动手学深度学习》多层感知机 模型概念和代码实现 目录 …

Deepin_Ubuntu_查看树形目录结构(tree)

Linux系统&#xff08;Deepin、Ubuntu&#xff09;中&#xff0c;可以使用tree命令来查看树形目录结构&#xff0c;下面是一些示例&#xff1a; 查看当前目录的树形结构&#xff1a; tree查看指定目录的树形结构&#xff0c;例如/etc/X11/fonts目录&#xff1a; tree /etc/X…

递归、搜索与回溯算法(专题一:递归)

往期文章&#xff08;希望小伙伴们在看这篇文章之前&#xff0c;看一下往期文章&#xff09; &#xff08;1&#xff09;递归、搜索与回溯算法&#xff08;专题零&#xff1a;解释回溯算法中涉及到的名词&#xff09;【回溯算法入门必看】-CSDN博客 接下来我会用几道题&#…

【JSON2WEB】01 WEB管理信息系统架构设计

WEB管理信息系统分三层设计&#xff0c;分别为DataBase数据库、REST2SQL后端、JSON2WEB前端&#xff0c;三层都可以单独部署。 1 DataBase数据库 数据库根据需要选型即可&#xff0c;不需要自己设计开发&#xff0c;一般管理信息系统都选关系数据库&#xff0c;比如Oracle、…

Android studio 简单登录APP设计

一、登录界面: 二、xml布局设计: <LinearLayoutandroid:id="@+id/linearLayout"android:layout_width="match_parent"android:layout_height="match_parent"android:orientation="vertical"tools:layout_editor_absoluteX="…

AI大模型预先学习笔记一:transformer和fine tune技术介绍

一、商业观点&#xff1a;企业借助大模型获得业务增长可能 二、底层原理&#xff1a;transformer 1&#xff09;备注 ①下面每个步骤都是自回归的过程&#xff08;aotu-regressive&#xff09;&#xff1a;已输出内容的每个字作为输入&#xff0c;一起生成下一个字 ②合起来就…

Android期末项目:美食点餐APP的设计与实现

目录 1 项目基本信息 1.1 项目名称 1.2 开发运行环境 1.3 使用的核心类及组件 2 项目需求分析 2.1 APP管理员 2.2 APP用户 3 项目开发过程 3.1 APP功能模块 3.2 数据库设计 3.3具体实现 3.3.1 用户注册与登录 3.3.2 fragment首页界面 3.3.3 fragment不同界面切换…

11种开源即插即用模块汇总 !!(附论文和代码)

即插即用的模块就像是一盒乐高&#xff0c;让我们能快速组合各种设计好的模块&#xff0c;搭建出我们需要的模型&#xff0c;这样做不仅让建模速度提升&#xff0c;还保证了模型的创新性和有效性。 文章目录 1、SCConv&#xff1a;空间和通道重构卷积&#xff08;2023&#xff…

锐浪报表 Grid++Report 明细表格标题重复打印

一、问题提出 锐浪报表 GridReport&#xff0c;打印表格时&#xff0c;对于明细表格的标题&#xff0c;打开换页时&#xff0c;需要重复打印明细表格的标题&#xff0c;或取消打印明细表格的标题。见下表&#xff1a; 首页&#xff1a; 后续页&#xff1a;&#xff08;无明细表…