Html画布视频流

Posted

技术标签:

【中文标题】Html画布视频流【英文标题】:Html canvas video streaming 【发布时间】:2021-11-18 10:33:28 【问题描述】:

我有这段代码,它在视频标签中播放我的相机视图,然后在同一页面的画布元素中播放,页面有 2 个正方形,一个用于视频标签(播放相机视图),另一个用于画布(播放视频标签的相同视频)。我如何编辑我的代码以使视频在另一个页面的画布中播放以让我的用户实时观看它,如果有一种方法可以让用户在同一页面而不是另一个页面上观看它并且只看到画布,那就是也接受了。

这是我的 html 文件:

<html>
    <head>
        <meta charset="UTF-8">
        <title>With canvas</title>
    </head>
    <body>
        <div class="booth">
            <video id="video"   autoplay></video>
            <canvas id="canvas"   style="border: 1px solid black;"></canvas>
        </div>
        <script src="video.js"></script>
    </body>
</html>

这是我的 js 文件:

(function() 
    var canvas= document.getElementById('canvas'),
    context = canvas.getContext('2d'),
    video = document.getElementById('video'),
    vendorUrl = window.URL || window.webkitURL;

    navigator.getMedia = navigator.getUserMedia ||
                         navigator.webkitGetUserMedia ||
                         navigator.mozGetUserMedia ||
                         navigator.msGetUserMedia;

    navigator.getMedia (
        video: true,
        audio: false
    , function(stream) 
        //video.src = vendorUrl.createObjectURL(stream);
        if ('srcObject' in video) 
            video.srcObject = stream;
           else 
            video.src = vendorUrl.createObjectURL(stream);
          
        video.play();
    , function(error) 
        // An error occured
        //error.code
    );


    video.addEventListener('play', function() 
        setInterval(() => 
        draw(this, context, 400, 300);
        , 100);

    , false );
    function draw(video, context, width, height) 
        context.drawImage(video, 0, 0, width, height);
    
    
) ();

【问题讨论】:

如果您想在另一个页面上播放,您可以将相机数据作为数组缓冲区获取,但是为什么您想在可以在视频标签中播放时在画布中播放? 用户可以现场观看吗? @阿米尔·拉赫曼 您将获得块中的缓冲区,无论如何您都必须将其发送给其他用户,然后它可以像现场直播一样播放等待我有此类实验的代码我将在答案中发布它等待分钟 好的,@Amir Rahman 【参考方案1】:

使用MediaRecorder 以块的形式获取实时数据,作为来自摄像机的媒体记录器记录,并提供可以通过另一端用户发送的块

然后使用mediasource 在用户的另一侧附加块以附加它并在收到新块时实时播放

我知道这是一件复杂的事情,但相信我,当我在做这个实验时,我花了很多时间来理解我相信你会从我下面的实验代码中得到一些好处

这是一个有效的demo

var mediasource = new MediaSource(),video = document.querySelector("video"),
    mime = 'video/webm;codecs=vp9,opus'
video.src = URL.createObjectURL(mediasource)

mediasource.addEventListener("sourceopen",function(_)
    var source = mediasource.addSourceBuffer(mime)
    navigator.mediaDevices.getUserMedia(video: true,audio: true).then(stream=>
        var recorder = new MediaRecorder(stream,mimeType:mime)
        recorder.ondataavailable = d =>
// creating chunks of 5 seconds of video continiously
            var r = new Response(d.data).arrayBuffer() // convert blob to arraybuffer
            r.then(arraybuffer=>
                source.appendBuffer(arraybuffer)
            )
        
        recorder.start(5000)
    )
)

&lt;video class="video" controls autoplay&gt;&lt;/video&gt;

收集实时数据并播放的分离版本 demo

// gathering camera data to liveData array
var vid = document.querySelector(".video"),
    mime = 'video/webm;codecs=vp9,opus',
    liveData = []

    navigator.mediaDevices.getUserMedia(video:true,audio:true).then(stream=>
        var recorder = new MediaRecorder(stream,mimeType:mime)
        recorder.ondataavailable = d =>
            console.log("capturing")
            new Response(d.data).arrayBuffer().then(eachChunk=>
            // recording in chunks here and saving it to liveData array                
                liveData.push(eachChunk)
            )
        
        recorder.start(5000)    
    )
//--------------------------------------------------------------------------------
 
// playing from liveData in video 
var ms = new MediaSource()
vid.src =URL.createObjectURL(ms)

ms.onsourceopen = function()
    var source = ms.addSourceBuffer(mime),chunkIndex = 0
    setInterval(function()
        if(liveData.length > 0)
            var currentChunk = liveData[chunkIndex]
            source.appendBuffer(currentChunk)
            console.log("playing")
            chunkIndex++     
        
    ,5000)

【讨论】:

谢谢大佬,但我要如何让用户观看呢?我想让用户像在 Facebook 现场直播一样观看它,但更简单。 这段代码每次为您提供 5 秒的录制时间,可以使用 MediaSource 在视频播放器中播放,因为您无法手动附加块,这就是为什么一旦您将 MediaSource 连接到视频播放器,MediaSource 就在这里然后在MediaSource 中追加块,它将追加并实时播放 对不起兄弟,你能用代码解释一下吗?我以前没有使用过,所以对我来说不清楚,请帮助我。 @阿米尔·拉赫曼 好的,首先我将只向您展示记录器,我知道 mediasource API 不是那么用户友好,但就是这样 你救了我的命!

以上是关于Html画布视频流的主要内容,如果未能解决你的问题,请参考以下文章

html5:在画布内显示视频

html5:在画布内显示视频

直播 HTML5 视频绘制到画布不工作

HTML5 drawimage 从视频到画布

html HTML5:视频,音频,画布

HTML5:在 IOS Safari 中手动“播放”画布内的视频