纯属自己理解和搜刮来的实现 哈哈
web视频聊天的基本思路
1.借助浏览器获取摄像头信息
2.获取摄像头视频信息
3.得到视频信息后进行编码
4.服务器进行信息转发
5.客户端解码进行播放
web直播的基本思路
1.有了视频聊天,简单的直播那就是服务器端对客户端进行转发推送
遇到的问题
1.对于单纯的视频聊天1对1可以实现无卡顿操作直接对流进行拼接就可以的了,这里有个问题就是获取的视频信息段单独播放是失败的后续查找后说是缺少关键帧,我对这里的理解也是有限的,那么有了这个问题在直播的时候无法满足中途进来的用户。
2.解决了第一个问题通过一些其他的方式获取的帧都是独立可以播放的,但是在客户端接收数据后通过src切换加载有个问题那就是卡顿很明显的切换数据加载。
3.第二个问题解决办法在进行切src的时候进行获取当前播放的最后一个画面设置为下一个播放的预览图这个是目前我这里找到的办法,有其它方式可以给我留言。
实现
服务端:NETTY(websocket)
客户端浏览器、视频播放video.js
传输协议JSON
部分代码
1.视频1对1发送
try { var options = {mimeType: mimeType}; mediaRecorder = new MediaRecorder(stream, options); } catch (e) { console.error('Exception while creating MediaRecorder: ' + e); log('Exception while creating MediaRecorder: ' + e); alert('Exception while creating MediaRecorder: ' + e + '. mimeType: ' + options.mimeType); return; } //这里有个触发器每一秒钟会得到一个 mediaRecorder.start(1000); //把获取到的数据可以转码为base64通过websocket推送到服务器进行转发 mediaRecorder.ondataavailable = handleDataAvailable; function handleDataAvailable(event) { if (event.data && event.data.size > 0) { console.log('正在发送数据...'); var reader = new FileReader(); reader.readAsDataURL(event.data); reader.onload = function (e) { //console.info("videoStr:"+reader.result); //发送给服务端进行转发 sendVideo(reader.result); //window.URL.revokeObjectURL(localVideoPlayer.src); } //socket.send(event.data); } } 复制代码
2.视频1对1接收
//接收数据 var index=0; var successStream; var oSourceBuffer, oMediaSource; var mimeCodec='video/webm; codecs="vp8,opus"'; if ('MediaSource' in window && MediaSource.isTypeSupported(mimeCodec)) { console.log("oMediaSource"); oMediaSource = new MediaSource(); var url = URL.createObjectURL(oMediaSource); remoteVideoVid.src = url; oMediaSource.addEventListener('sourceopen', sourceOpen); } else { console.log("The Media Source Extensions API is not supported.") } function sourceOpen () { console.log("oMediaSource2:"+this.readyState); // open oSourceBuffer = oMediaSource.addSourceBuffer(mimeCodec); oSourceBuffer.addEventListener('updateend', streamPlay); }; function streamPlay(e) { remoteVideoVid.play(); } //接收服务端推送过来的数据 这里只需要拼接就可以了 function remotStream(stream){ if (oSourceBuffer) { oSourceBuffer.appendBuffer(dataURItoArray(stream)); } else { console.log('no init sourceBuffer'); } } 复制代码
3.直播推送的处理发放
//这里通过定时任务进行推送,每次的数据都是一个可以播放的小模块 setInterval("stopSend()",1000); function stopSend(){ console.log("stop:"+sendIndex); if(mediaRecorder){ mediaRecorder.stop(); mediaRecorder.start(); console.log("testRequestData"); }else{ console.log("noStop:"+sendIndex); } } 复制代码
4.直播接收的处理
remoteVideoPlayer2.on('ended',function(e) { console.log("ended2:"+videoStart+"_"+index); //在记载下一个视频块的时候背景采用上一个的画面,这样是卡顿不是太明显 ctx.drawImage(remoteVideoVid2, 0, 0, 400, 300); let src=canvas.get()[0].toDataURL("image/jpeg"); remoteVideoPlayer2.poster(src); //这里后续需要优化因为目前的地方是把接收到的数据缓存在了浏览器 remoteVideoPlayer2.src(new_source.slice(index-1)); } 复制代码
5.服务器进行信息转发
//netty进行信息转发 ChannelManager.getChannel(message.getAccept().getUserCode()) .writeAndFlush(newTextWebSocketFrame(this.getMapper(). writeValueAsString(message))); 复制代码
效果
网络异常,图片无法展示
|