php做自己的网站,长春营销型网站制作,智能建造技术,高端网站建设万维科技总结
最近在写直播项目 目前比较重要的点就是推拉流 自己也去了解了一下
ffmpeg
FFmpeg 是一个开源项目#xff0c;它提供了一个跨平台的命令行工具#xff0c;以及一系列用于处理音频和视频数据的库。FFmpeg 能够执行多种任务#xff0c;包括解封装、转封装、视频和音频…总结
最近在写直播项目 目前比较重要的点就是推拉流 自己也去了解了一下
ffmpeg
FFmpeg 是一个开源项目它提供了一个跨平台的命令行工具以及一系列用于处理音频和视频数据的库。FFmpeg 能够执行多种任务包括解封装、转封装、视频和音频的编码和解码、流处理等。它广泛应用于多媒体处理领域被许多项目和网站推荐使用。
FFmpeg 的主要特点包括
多平台支持FFmpeg 可以在多种操作系统上运行包括 Windows、Mac OS X、Linux 等。
功能丰富它支持大量的音视频格式能够进行编码、解码、转码、复用、解复用、滤波、转换、抓取等操作。
命令行工具FFmpeg 提供了简洁的命令行接口使得用户能够方便地进行批处理操作。
下载ffmpeg
官网 http://ffmpeg.org/ 配置环境变量 添加到系统环境变量中 输入这个ffmpeg -version 出现这个 说明成功
node端 const http require(http);
const express require(express);
const socketio require(socket.io);const app express();
const server http.createServer(app);
const io socketio(server);
app.use(express.static(public))
var spawn require(child_process).spawn;
spawn(ffmpeg, [-h]).on(error, function (m) {console.error(FFMpeg not found in system cli; please install ffmpeg properly or make a softlink to ./!);process.exit(-1);
});io.on(connection, function (socket) {socket.emit(message, Hello from mediarecorder-to-rtmp server!);socket.emit(message, Please set rtmp destination before start streaming.);var ffmpeg_process, feedStream false;socket.on(config_rtmpDestination, function (m) {socket._rtmpDestination m;});socket.on(config_vcodec, function (m) {socket._vcodec m;});socket.on(start, function (m) {if (ffmpeg_process || feedStream) {socket.emit(fatal, stream already started.);return;}if (!socket._rtmpDestination) {socket.emit(fatal, no destination given.);return;}var framerate socket.handshake.query.framespersecond;var audioBitrate parseInt(socket.handshake.query.audioBitrate);var audioEncoding 64k;console.log(audioEncoding, audioBitrate);console.log(framerate on node side, framerate);var ops [-i, -,-c:v, libx264, -preset, veryfast, -tune, zerolatency,-c:a, aac, -ar, 44100, -b:a, 64k,-y,-use_wallclock_as_timestamps, 1,-async, 1,-filter_complex, aresample44100,-strict, experimental,-bufsize, 1000,-f, flv, socket._rtmpDestination];ffmpeg_process spawn(ffmpeg, ops);ffmpeg_process.stderr.on(data, function (data) {socket.emit(ffmpeg_stderr, data);});ffmpeg_process.on(error, function (err) {socket.emit(fatal, ffmpeg error! err);feedStream false;console.log(意外出错,err);socket.disconnect();});ffmpeg_process.on(exit, function (err) {socket.emit(fatal, ffmpeg exit! err);socket.disconnect();console.log(exit,err);});socket.on(binarystream, function (data) {console.log(data,48888);ffmpeg_process.stdin.write(data);});});socket.on(disconnect, function () {feedStream false;ffmpeg_process.stdin.end();ffmpeg_process.kill(SIGINT);});
});const PORT process.env.PORT || 8080;
server.listen(PORT, () {console.log(Socket.IO server is running on port ${PORT});
});
解释一下代码 开启一个子线程用于运行ffmpeg
var spawn require(child_process).spawn;
spawn(ffmpeg, [-h]).on(error, function (m) {console.error(FFMpeg not found in system cli; please install ffmpeg properly or make a softlink to ./!);process.exit(-1);
});用sockect进行连接 当监听到connection事件之后所做的事情
io.on(connection, function (socket) {
....
}socket监听start消息
io.on(start, function (socket) {
....
}设置对ffmpeg进行操作的命令 用于推流 var ops [-i, -,-c:v, libx264, -preset, veryfast, -tune, zerolatency,-c:a, aac, -ar, 44100, -b:a, 64k,-y,-use_wallclock_as_timestamps, 1,-async, 1,-filter_complex, aresample44100,-strict, experimental,-bufsize, 1000,-f, flv, socket._rtmpDestination];ffmpeg_process spawn(ffmpeg, ops);这个data就是接收到的数据流 ffmpeg_process.stderr.on(data, function (data) {socket.emit(ffmpeg_stderr, data);});
前端部分
!DOCTYPE html
html langenheadmeta charsetUTF-8meta http-equivX-UA-Compatible contentIEedgemeta nameviewport contentwidthdevice-width, initial-scale1.0titleDocument/titlelink relstylesheet href./index.css
/head
script srchttps://cdn.bootcdn.net/ajax/libs/socket.io/4.7.2/socket.io.js/scriptbodyheader classheaderh1Start a Live Stream!/h1/headerbrbrlabel foroption_width classformSize:/labelinput classform typetext idoption_width value1280 / times;input classform typetext idoption_height value720 /brbrlabel classform foroption_framerateFrame Rate:/labelinput classform typetext idoption_framerate value15 /brbrlabel classform foroption_framerateAudio bitrate:/labelselect classform idoption_bitrateoption value2205022050/optionoption value4410044100/optionoption value1102511025/option/selectbrbrinput classform typehidden idsocket.io_address value/ /label classform foroption_urlRTMP:/label!-- RMTP YOUTUBE URL/KEY--input classform typetext idoption_url stylewidth:33%valuertmp://a.rtmp.youtube.com/live2/cqg8-76xs-hztf-hfx7-9q5y /br!-- RMTP YOUTUBE URL/KEY--input classform typecheckbox styledisplay:none idcheckbox_Reconection checkedtruelabel classform styledisplay:noneReconnection /labelbrdiv classformConnect the server, then start streaming./divbr /button classform idbutton_serverConnect Server/buttonbutton classform idbutton_startStart Streaming/buttonbutton classform idbutton_stopStop Streaming/buttonbrp idoutput_message/ptextarea readonlytrue idoutput_console rows15Server Logs/textareabrdiv classvideovideo classoutput_video idoutput_video autoplaytrue/video/divbrscript src./index.js/script
/body/htmljs部分
var output_console document.getElementById(output_console),output_message document.getElementById(output_message),output_video document.getElementById(output_video),option_url document.getElementById(option_url),socketio_address document.getElementById(socket.io_address),option_width document.getElementById(option_width),option_height document.getElementById(option_height),option_framerate document.getElementById(option_framerate),option_bitrate document.getElementById(option_bitrate),button_start document.getElementById(button_start),height parseInt(option_height.value),width parseInt(option_width.value),framerate parseInt(option_framerate.value),audiobitrate parseInt(option_bitrate.value),url option_url.value;option_height.onchange option_height.onkeyup function () { height 1 * this.value; }
option_width.onchange option_width.onkeyup function () { width 1 * this.value; console.log(width width); }
option_framerate.onchange option_framerate.onkeyup function () { framerate 1 * this.value; console.log(framerate framerate); }
option_bitrate.onchange option_bitrate.onkeyup function () { audiobitrate 1 * this.value; console.log(bitrate audiobitrate); }
option_url.onchange option_url.onkeyup function () { url this.value; }
button_start.onclick requestMedia;
button_server.onclick connect_server;
var flagConnect truevar mediaRecorder;
var socket;
var state stop;
console.log(state initiated state);
var t;
button_start.disabled true;
button_stop.disabled true;
function connect_server() {navigator.getUserMedia (navigator.mediaDevices.getUserMedia ||navigator.mediaDevices.mozGetUserMedia ||navigator.mediaDevices.msGetUserMedia ||navigator.mediaDevices.webkitGetUserMedia);if (!navigator.getUserMedia) { fail(No getUserMedia() available.); }if (!MediaRecorder) { fail(No MediaRecorder available.); }var socketOptions { secure: true, reconnection: true, reconnectionDelay: 1000, timeout: 15000, pingTimeout: 15000, pingInterval: 45000, query: { framespersecond: framerate, audioBitrate: audiobitrate } };socket io(socketOptions);socket.on(connect_timeout, (timeout) {console.log(连接超时 timeout);output_message.innerHTML Connection timed out;});socket.on(error, (error) {console.log(state on connection error error);output_message.innerHTML Connection error;});socket.on(connect_error, function () {console.log(连接错误 state);});socket.on(message, function (m) {console.log(state on message state m);show_output(SERVER: m);});socket.on(fatal, function (m) {show_output(Fatal ERROR: unexpected: m);console.log(fatal socket error!!, m);console.log(state on fatal error state);console.log(media recorder restarted);if (flagConnect) {output_message.innerHTML server is reload!;console.log(重置连接);}//should reload?});socket.on(flagConnect, function (m) {//this is the ffmpeg output for each frameshow_output(FFMPEG: m);console.log(m, 我是每一帧);});socket.on(disconnect, function (reason) {console.log(state disconec state);show_output(ERROR: server disconnected!);console.log(失去连接 reason);connect_server();if (flagConnect) {output_message.innerHTML 重置;console.log(重置);}});state ready;console.log(state state);button_start.disabled false;button_stop.disabled false;button_server.disabled true;output_message.innerHTML Connecting local server...;
}
async function requestMedia() {var constraints {audio: {sampleRate: audiobitrate,echoCancellation: true},video: {width: { min: 100, ideal: width, max: 1920 },height: { min: 100, ideal: height, max: 1080 },frameRate: { ideal: framerate }}}const stream await navigator.mediaDevices.getUserMedia(constraints)video_show(stream)socket.emit(config_rtmpDestination, url);socket.emit(start, start);mediaRecorder new MediaRecorder(stream);mediaRecorder.start(250)button_stop.disabled false;button_start.disabled true;button_server.disabled true;var livestream document.getElementsByClassName(Livestream);livestream.innerHtml test;mediaRecorder.onstop function (e) {console.log(stopped!);console.log(e);}mediaRecorder.onpause function (e) {console.log(media recorder paused!!);console.log(e);}mediaRecorder.onerror function (event) {let error event.error;console.log(error, error.name);};mediaRecorder.ondataavailable function (e) {socket.emit(binarystream, e.data);state start;}
}
function video_show(stream) {console.log(stream, 111111);if (srcObject in output_video) {output_video.muted true;output_video.srcObject stream;} else {output_video.src window.URL.createObjectURL(stream);}
}
function show_output(str) {output_console.value \n str;output_console.scrollTop output_console.scrollHeight;
};
以上代码分为 这三个方法 其中 以connect-server 先使用浏览器自带的 navigator.getUserMedia获取设备 并且将配置的属性传入socket配置中 这个方法就是对socket连接进行处理 包括处理服务器端连接过程通信的过程
requestMedia 获取媒体数据流 并且通过 socket.emit(“binarystream”, e.data);传递给后台 const stream await navigator.mediaDevices.getUserMedia(constraints)实例
下周
目前弄了一个分片上传 下周弄完之后可以分享分享 文章转载自: http://www.morning.wnnts.cn.gov.cn.wnnts.cn http://www.morning.xkmrr.cn.gov.cn.xkmrr.cn http://www.morning.rfkyb.cn.gov.cn.rfkyb.cn http://www.morning.ybhjs.cn.gov.cn.ybhjs.cn http://www.morning.wxfjx.cn.gov.cn.wxfjx.cn http://www.morning.wjzzh.cn.gov.cn.wjzzh.cn http://www.morning.rpsjh.cn.gov.cn.rpsjh.cn http://www.morning.fpqsd.cn.gov.cn.fpqsd.cn http://www.morning.rjcqb.cn.gov.cn.rjcqb.cn http://www.morning.chehb.com.gov.cn.chehb.com http://www.morning.tnyanzou.com.gov.cn.tnyanzou.com http://www.morning.swimstaracademy.cn.gov.cn.swimstaracademy.cn http://www.morning.smhtg.cn.gov.cn.smhtg.cn http://www.morning.rlhjg.cn.gov.cn.rlhjg.cn http://www.morning.lzsxp.cn.gov.cn.lzsxp.cn http://www.morning.xbckm.cn.gov.cn.xbckm.cn http://www.morning.wzdjl.cn.gov.cn.wzdjl.cn http://www.morning.pdkht.cn.gov.cn.pdkht.cn http://www.morning.tsrg.cn.gov.cn.tsrg.cn http://www.morning.ztqj.cn.gov.cn.ztqj.cn http://www.morning.smjyk.cn.gov.cn.smjyk.cn http://www.morning.trhlb.cn.gov.cn.trhlb.cn http://www.morning.jfbpf.cn.gov.cn.jfbpf.cn http://www.morning.prplf.cn.gov.cn.prplf.cn http://www.morning.lylkh.cn.gov.cn.lylkh.cn http://www.morning.cmzcp.cn.gov.cn.cmzcp.cn http://www.morning.sqxr.cn.gov.cn.sqxr.cn http://www.morning.yfmxn.cn.gov.cn.yfmxn.cn http://www.morning.yqfdl.cn.gov.cn.yqfdl.cn http://www.morning.bxch.cn.gov.cn.bxch.cn http://www.morning.mwkwg.cn.gov.cn.mwkwg.cn http://www.morning.cctgww.cn.gov.cn.cctgww.cn http://www.morning.kpbq.cn.gov.cn.kpbq.cn http://www.morning.ntyanze.com.gov.cn.ntyanze.com http://www.morning.yknsr.cn.gov.cn.yknsr.cn http://www.morning.rnzgf.cn.gov.cn.rnzgf.cn http://www.morning.kjnfs.cn.gov.cn.kjnfs.cn http://www.morning.pxlsh.cn.gov.cn.pxlsh.cn http://www.morning.yysqz.cn.gov.cn.yysqz.cn http://www.morning.mgwpy.cn.gov.cn.mgwpy.cn http://www.morning.tsnq.cn.gov.cn.tsnq.cn http://www.morning.qfmcm.cn.gov.cn.qfmcm.cn http://www.morning.mxmdd.cn.gov.cn.mxmdd.cn http://www.morning.brwnd.cn.gov.cn.brwnd.cn http://www.morning.bwgrd.cn.gov.cn.bwgrd.cn http://www.morning.jbshh.cn.gov.cn.jbshh.cn http://www.morning.nmqdk.cn.gov.cn.nmqdk.cn http://www.morning.llxqj.cn.gov.cn.llxqj.cn http://www.morning.bhznl.cn.gov.cn.bhznl.cn http://www.morning.kfsfm.cn.gov.cn.kfsfm.cn http://www.morning.wiitw.com.gov.cn.wiitw.com http://www.morning.amonr.com.gov.cn.amonr.com http://www.morning.tqsmc.cn.gov.cn.tqsmc.cn http://www.morning.chtnr.cn.gov.cn.chtnr.cn http://www.morning.psdbf.cn.gov.cn.psdbf.cn http://www.morning.bdkhl.cn.gov.cn.bdkhl.cn http://www.morning.mdpcz.cn.gov.cn.mdpcz.cn http://www.morning.tfpqd.cn.gov.cn.tfpqd.cn http://www.morning.gpryk.cn.gov.cn.gpryk.cn http://www.morning.ncrk.cn.gov.cn.ncrk.cn http://www.morning.xsrnr.cn.gov.cn.xsrnr.cn http://www.morning.nhzxr.cn.gov.cn.nhzxr.cn http://www.morning.mzzqs.cn.gov.cn.mzzqs.cn http://www.morning.kysport1102.cn.gov.cn.kysport1102.cn http://www.morning.xnyfn.cn.gov.cn.xnyfn.cn http://www.morning.bwygy.cn.gov.cn.bwygy.cn http://www.morning.ykyfq.cn.gov.cn.ykyfq.cn http://www.morning.tcfhs.cn.gov.cn.tcfhs.cn http://www.morning.jqbmj.cn.gov.cn.jqbmj.cn http://www.morning.lpcct.cn.gov.cn.lpcct.cn http://www.morning.skwwj.cn.gov.cn.skwwj.cn http://www.morning.ylklr.cn.gov.cn.ylklr.cn http://www.morning.rknsp.cn.gov.cn.rknsp.cn http://www.morning.yrjkz.cn.gov.cn.yrjkz.cn http://www.morning.pswzc.cn.gov.cn.pswzc.cn http://www.morning.sgrdp.cn.gov.cn.sgrdp.cn http://www.morning.qwhbk.cn.gov.cn.qwhbk.cn http://www.morning.rnwmp.cn.gov.cn.rnwmp.cn http://www.morning.qgdsd.cn.gov.cn.qgdsd.cn http://www.morning.lgwjh.cn.gov.cn.lgwjh.cn