摘要:前言经过前面两篇文章的讲解,大家已经了解了的基本使用方法,下面我们就根据我们了解的做一个直播。因为没有做回音消除,和破音处理,这样听上去会很爽。
前言
经过前面两篇文章的讲解,大家已经了解了audio的基本使用方法,下面我们就根据我们了解的api做一个直播。
web音频流转发之AudioNode
web音频流转发之音频源
视频直播:采集一帧一帧的视频,转换为base64转发,接收到base64后,设置为img的src,然后不停的修改img的src形成视频
音频直播:采集一帧一帧的音频二进制数据,转发2进制数据,在接收端对2进制原始音频数据进行播放
采集和推流获取摄像头,和麦克风需要https
navigator.getUserMedia已经废弃,使用navigator.mediaDevices.getUserMedia,当然需要做兼容
//获取音频视频流数据
mediaDevices = navigator.mediaDevices.getUserMedia({audio: true,video: { width: 320, height: 240 }});
mediaDevices.then(stream => {
//视频流转换到video标签播放
video.srcObject = stream;
video.play();
//音频流转换到AudioNode做数据采集
let source = audioCtx.createMediaStreamSource(stream);
recorder = audioCtx.createScriptProcessor(2048, 1, 1);
source.connect(recorder);
recorder.connect(audioCtx.destination);
recorder.onaudioprocess = function(ev){
//采集单声道数据
let inputBuffer = ev.inputBuffer.getChannelData(0);
//将视频画面转换成base64发送
ws.send(canvas.toDataURL("image/jpeg"));
//发送音频pcm数据
ws.send(inputBuffer.buffer);
};
});
video.onplay = function(){
//将video绘制到canvas上
interval = setInterval(function(){
ctx.drawImage(video, 0, 0);
},30);
};
接收流文件
对接收的文件进行一个缓存,以达到一个好的用户体验
let ws = new WebSocket("wss://192.168.3.102"),
imgChuncks = [],
audioChuncks = [],
img = null;
//如何处理二进制数据,默认是Blob
ws.binaryType = "arraybuffer",
ws.onmessage = function(evt) {
if(evt.data.byteLength === undefined) {
//收到的base64图片
imgChuncks.push(evt.data);
}else{
//收到的音频二进制pcm数据
audioChuncks.push(new Float32Array(evt.data));
}
//缓存2帧的数据后开始播放
if(!img && audioChuncks.length > 2){
myplay();
}
};
处理流
//创建播放音频视频函数
function myplay(){
//创建img标签来播放base64图片
img = new Image();
document.body.appendChild(img);
//创建播放音频对象
let myBuffer = audioCtx.createBuffer(1, 2048, audioCtx.sampleRate),
source = audioCtx.createBufferSource(),
recorder = audioCtx.createScriptProcessor(2048, 1, 1);
source.connect(recorder);
recorder.connect(audioCtx.destination);
recorder.onaudioprocess = function(ev){
//修改img的src达到视频的效果
img.src = imgChuncks.shift();
//播放audioChuncks里面真正的二进制数据
ev.outputBuffer.copyToChannel(audioChuncks.shift() || new Float32Array(2048), 0, 0);
};
}
注意
这只是一个实例程序,为进行任何优化
在测试时请给扬声器插上耳机收听,或者让扬声器和麦克风放置到不同的房间。因为没有做回音消除,和破音处理,这样听上去会很爽。
自己生成一个https文件做测试
完整代码index.html
- let ws = new WebSocket("wss://192.168.3.102"),
- imgChuncks = [],
- audioChuncks = [],
- img = null;
- //如何处理二进制数据,默认是Blob
- ws.binaryType = "arraybuffer",
- ws.onmessage = function(evt) {
- if(evt.data.byteLength === undefined) {
- //收到的base64图片
- imgChuncks.push(evt.data);
- }else{
- //收到的音频二进制pcm数据
- audioChuncks.push(new Float32Array(evt.data));
- }
- //缓存2帧的数据后开始播放
- if(!img && audioChuncks.length > 2){
- myplay();
- }
- };
- //创建播放音频视频函数
- function myplay(){
- //创建img标签来播放base64图片
- img = new Image();
- document.body.appendChild(img);
- //创建播放音频对象
- let myBuffer = audioCtx.createBuffer(1, 2048, audioCtx.sampleRate),
- source = audioCtx.createBufferSource(),
- recorder = audioCtx.createScriptProcessor(2048, 1, 1);
- source.connect(recorder);
- recorder.connect(audioCtx.destination);
- recorder.onaudioprocess = function(ev){
- //修改img的src达到视频的效果
- img.src = imgChuncks.shift();
- //播放audioChuncks里面真正的二进制数据
- ev.outputBuffer.copyToChannel(audioChuncks.shift() || new Float32Array(2048), 0, 0);
- };
- }
- let video = document.querySelector("video"),
- start = document.querySelector(".start"),
- stop = document.querySelector(".stop"),
- canvas = document.querySelector("canvas"),
- ctx = canvas.getContext("2d"),
- audioCtx = new (window.AudioContext || window.webkitAudioContext)(),
- interval = null,
- mediaDevices = null;
- //点击开始
- start.onclick = function(){
- //获取音频视频流数据
- mediaDevices = navigator.mediaDevices.getUserMedia({audio: true,video: { width: 320, height: 240 }});
- mediaDevices.then(stream => {
- //视频流转换到video标签播放
- video.srcObject = stream;
- video.play();
- //音频流转换到AudioNode做数据采集
- let source = audioCtx.createMediaStreamSource(stream);
- recorder = audioCtx.createScriptProcessor(2048, 1, 1);
- source.connect(recorder);
- recorder.connect(audioCtx.destination);
- recorder.onaudioprocess = function(ev){
- //采集单声道数据
- let inputBuffer = ev.inputBuffer.getChannelData(0);
- //将视频画面转换成base64发送
- ws.send(canvas.toDataURL("image/jpeg"));
- //发送音频pcm数据
- ws.send(inputBuffer.buffer);
- };
- });
- };
- video.onplay = function(){
- //将video绘制到canvas上
- interval = setInterval(function(){
- ctx.drawImage(video, 0, 0);
- },30);
- };
servers.js
</>code
let https = require("https"),
fs = require("fs"),
WebSocket = require("ws"),
options = {
key: fs.readFileSync("./key.pem"),
cert:fs.readFileSync("./key-cert.pem")
},
server = https.createServer(options, function(req, res){
fs.readFile("./index.html", function(err, data){
res.writeHead(200,{"Content-Type": "text/html"});
res.end(data);
});
}).listen(443, function(){
console.log("服务启动成功")
});
const wss = new WebSocket.Server({server});
wss.binaryType = "arraybuffer";
wss.on("connection", (ws) => {
ws.on("message", function(data) {
wss.clients.forEach(function each(client) {
if (client.readyState === WebSocket.OPEN && client !== ws) {
client.send(data);
}
});
});
});
文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。
转载请注明本文地址:https://www.ucloud.cn/yun/51362.html
摘要:前言音频流转发之音视频直播音频流转发之能直播为什么不可以看完本系列文章,你就能做一个直播,真正的直播,包括音频流的转发,这也是我最近查看发现有相关能实现音频流的转发,所有打算分享系列文章供大家交流,如有不对之处请指正。 前言 web音频流转发之音视频直播web音频流转发之AudioNodeapp能直播,web为什么不可以?看完本系列文章,你就能做一个直播,真正的直播,包括音频流的转发,...
摘要:概述是一个处理音频的通用模块比如一个音频源一个元素一个音频地址或者一个中间处理模块一个过滤器如或一个音量控制器如一个既有输入也有输出。下面一章就开始介绍音频流的转发了。 前言 上一章地址: web音频流转发之音频源下一张地址:web音频流转发之音视频直播在这一章我说几个我们需要用到的音频处理模块也就3个吧,包括我们转发流是需要用到的核心模块。更多模块请看MDN,或者看HTML5音频AP...
阅读 1223·2021-11-19 09:40
阅读 2371·2021-11-15 18:00
阅读 1411·2021-10-18 13:34
阅读 2378·2021-09-02 15:40
阅读 1667·2019-08-30 14:01
阅读 1232·2019-08-30 11:11
阅读 2601·2019-08-29 15:26
阅读 852·2019-08-29 14:15