直播敲代码?你可能需要它

1,996 阅读3分钟
原文链接: www.jianshu.com

二话不说,先放图:


自拍233

二话不说,再放github地址:
github
这个是demo:
demo
如果觉得好玩请点个星啊,谢谢。

StringAnmt


不靠颜值吃饭的程序猿,直播敲代码也是可以露脸的!
而且这脸露得也要有点B格!
(其实这个给程序猿直播的功能是后来想出来的,最开始只是想要用这个小玩意做一些比较“有意义”的事情(滑稽))

先简单地说一下原理

利用HTML5新API:mediaDevices.getUserMedia开启你的摄像头,然后将你的视频图像转成字符串动画,输出到canvas上,没错,就是这么简单。

  1. 开启摄像头,读取摄像头流信息,输出到<video>上:

    /*获取video元素*/
    var vdo=document.getElementsByTagName('video')[0];
    
    /*设备开启参数*/
    var opt={
          /*开启麦克风*/
          audio:true,
    
          /*开启摄像头*/
          video:{
                height:600,
                width:800
          }
    }
    
    //调用系统设备(麦克风、摄像头)
    navigator.mediaDevices
        .getUserMedia(opt)
        .then(function(mediaStream){
             //获取输出流
             vdo.srcObject = mediaStream;
    
             //视频就绪回调
             vdo.onloadedmetadata = function(e) {
                   vdo.play();
             }
        })
        .catch(function(err){
             /*error handle*/
        })
  2. 获取视频每一帧的像素信息:
    这里就需要我们的canvas同学了,利用canvas的drawImage接口,将视频每一帧输入到canvas上,然后用getImageData获取像素信息,将图像处理成灰色,然后根据灰度填充文字

    var cvs=document.getElementByTagName('canvas')[0];
    var ctx=cvs.getContext('2d');
    var fontSize='10';
    
    ctx.font="0px Arial".replace(0,fontSize)
    
    ctx.drawImage(vdo,0,0,800,600);
    var fm=getImageData(0,0,800,600);
    var data=fm.data;
    var str='';
    
    for(var j=0;j<60;j++){
       str='';
       for(var i=0;i<80;i++){
    
           /*获取位置的像素的信息、采样*/
           var index=(j*800+i)*fontSize;
           index*=4;
    
           /*灰度公式:gray=r*0.299+g*0.587+b*0.114   */
           var gray = data[index] * 0.299 + data[index + 1] * 0.587 + data[index + 2] * 0.114;
           str+=addText(gray);
       }
       ctx.fillText(str,0,j*fontSize,800);
    }
    function addText(gray){
       /* 文本方向:从左到右代表从黑到白 */
       var text="苟利国家生死以";
       var d = parseInt(256 / text.length);
       var i = parseInt(gray / d);
    
       /*防止溢出*/
       if (i > text.length - 1) {
           i = text.length - 1;
       }
       return  text[i];
    }  
    `

    以上就是处理每一帧时的操作;
    然后再使用requestAnimationFrame定时获取视频信息,然后绘制输出。
    貌似。。。好像核心就这部分,其他的没什么可说的了。。。都是数学问题而不是代码问题啦。


再简单地说一下我这个库的使用方式

  • 快速使用:

    <canvas id="cvs"></canvas>
    <video id="vdo" style="display:none"></video>
    <script src="StringAnmt.js"></script>
    <script>
    var StrAnmt = new StringAnmt({
      videoId: 'vdo',
      canvasId: 'cvs',
      text: ['    ', '氵', '水', '淼'],
      fontSize: '18'
    });
    StrAnmt.openCamera(
      window.screen.width,
      window.screen.height,
      false
    )
    </script>
  • StringAnmt参数说明

    • videoIdvideo标签的id;
    • canvasIdcanvas标签的id;
    • text:想要渲染成动画的字符串或数组,从左到右是黑到白,不推荐字母、数字、汉字混编,尽量选用字符宽度差不多的字符,以免输出失真;使用的字符越多,画面细节(色块)越丰富。
    • fontSize:字符大小,字符串类型;
    • color: 输出的字符颜色
  • StringAnmt方法:

    • openCamera(width,height,isAudio):开启摄像头
      • width: 摄像头宽度
      • height: 摄像头高度
      • isAudio: 是否开启麦克风
    • play():播放
    • pause():暂停
    • playAndPause():若是播放状态则暂停,若是暂停状态则播放(可用于截图)

写在最后

没错,这玩意就是情人节那天,一个人非常无聊的时候撸出来的,撸出来之后也不知道能干嘛,就是看着好玩而已,反正现在看起来感觉非常简单,整篇文章感觉也没什么可以说的。
但后来发现,稍微改一改也可以弄成直播的那些主播的小头像啊,可以装逼用的。。。。
而且有点气人的一点就是,mediaDevices.getUserMedia在谷歌浏览器,如果你的服务器不是基于https协议的话,它会阻止你打开摄像头,嗨呀好气啊,局域网服务器都搭好了,websocket协议也弄好了。。。就是无法打开摄像头。。。
话说webRTC看起来有点复杂啊。。。
稍微有点常识的人都会知道,我想要干什么(滑稽)