发布日期 » 2019年1月5日 星期六

版权声明 » 自媒体人·陈帅华原创内容,转载请注明出处

基于Nodejs+Canvas+WebSocket实现视频流直播H5应用

TL;DR

  • PC端浏览器将视频流直播到服务器;移动端H5接收实时数据观看视频直播;
  • 学习基于websocket技术的socket.io模块的使用
  • 通过浏览器获取用户音、视频流;
  • 将捕获的视频流绘制到Canvas画布;
  • 基于Canvas与base64编码实现数据传输与渲染
  • ffmpeg输出视频帧到图像

基本实现

  • 主播和观众直播与观看直播的入口均为/live
  • 已登录的主播进入 /live 后立即开始直播,未登录的观众进入 /live 后观看直播;
  • 若当前无直播画面,则为进入 /live 的观众循环播放录播画面;
  • 主播进入 /live后,自动将所有正在观看录播画面的观众切换到直播画面;
  • 主播退出直播界面后,自动将所有观众切换到录播画面
  • 目前仅实现无声画面直播。

Chrome录制 - 主播端(左)、观众端(右)

笔记

  • Node服务器端与客户端均使用socket.io提供的全双工通信协议模块

    # Node服务端安装Socket.io
    npm i socket.io
    # 客户端使用Socket.io-client
    npm i socket.io-client
    
  • LIVE角色分为主播端、观众端,通过共享session识别登录状态分配直播或观看权限。

      # 支持session安装下方模块
      npm i express-session
      # 与socket.io分享session还需同时安装下方模块
      npm i express-socket.io-session
    
  • Chrome浏览器处于安全考虑,除本机IP外禁止非HTTPs协议传输的页面调用获取用户媒介权限,Firefox则无限制。

    // 处理各浏览器兼容问题
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
    // 请求获取用户媒介
    navigator.getUserMedia({
      audio: false,
      video: {
        width: videoWidth, 
        height: vidoeHeight
      }},
      onsuccess,
      onerror
    )
    
  • 将视频帧编码为base64图像通过websocket协议传输至服务器。

    // 第一个参数可以是 'image/png' 'image/jpeg' 'image/webm',后两者可设置图像质量
    const quality = .5
    canvas.toDataURL('image/webp', quality)
    
  • 关于base64编码与解码

    // 编码base64数据
    btoa('shuaihua')  // c2h1YWlodWE=
    // 解码base64数据。
    atob('c2h1YWlodWE=') // shuaihua
    
    
  • ffmpeg每隔一段时间提取视频帧并输出为图像文件

    # 每0.2秒输出一帧300*250大小的图像,以序号命名图像,图像格式为jpg
    ffmpeg -i ./movie/videoplayback.mp4 -f image2 -vf fps=fps=1/.2 -s 300x250 %d.jpg
    

待办

  • 实时弹幕发言功能
  • 有声直播与基于WebAudio API 的音频流播放方案
  • 最大程度发挥FFmpeg模块作用
  • 在现有性能限制之下,寻找画质与延迟间的平衡