用WebRTC的Insertable Streams API把元数据添加到媒体帧

以前,许多WebRTC功能只有在本机应用程序中才能使用,包括带有修改后的Chromium代码的电子应用程序。

如今,借助WebRTC NV API,其中一些程序已经可以在Web应用中使用了。上周我们发布了与Google合作开发的SFrame E2EE,多亏Insertable stream,其部分功能在Web可用了,现在我们就可以给大家展示另一个以前在Web应用程序中几乎不可能实现的功能。

受合作伙伴Around在其应用中出色工作的启发,我们会向大家展示如何在媒体和数据之间实现实时且有完美帧的同步,以及如何将简单的AI算法应用于视频内容,以改善用户体验。

通过访问原始编码的媒体帧并修改其内容,Instableable Streams API允许在编码后将自定义元数据附加到每个帧,并在解码过程之前,在另一端接收到媒体帧时提取自定义元数据。

尽管您可以通过WebRTC数据通道发送此元数据,但是对于AR / VR等应用程序来说,最好还是能够以每帧的精度将元数据附加到媒体流。

在如何演示此功能这方面,我们受到了Around应用的启发。该应用程序提供了最先进的UI / UX技术,涵盖面部识别和自动对焦功能,可将每个参与者的面部显示在一个小圆圈上,无需浪费屏幕空间来显示参与者背景。

https://www.around.co/

当前如果要实现此功能,你必须捕获媒体流的每个视频帧,将其显示在屏幕上,裁剪并调整到适当大小,然后使用canvas.captureStream(),就能够通过端对端连接发送指令了。

如你所见,此过程仍然不够高效(除非能支持WebRTC NV的“funny hats”用例)。所以我们尝试使用Insertable Streams API来实现此功能,并将图像处理推送到CSS的接收方以提高性能。

为了把处理逻辑移出主要的JavaScript线程,我们会用到两个Web工作程序。一个处理可插入流Insertable Streams,另一个处理面部检测。

主页会同时创建Web Worker和MessageChannel,以便他们可以直接在这两项之间发送消息,不必通过主线程。

主线程把可写和可读流从RTCRtpSender和RTCRtpReceiver传输到Insertable Streams工作器,并定期(每秒)从本地视频对象获取一帧,再将其传输到面部检测器工作器。

面部检测器工作器使用face-api.js来检测视频帧中存在的各人脸,并将检测到的面部的位置和大小信息发送到Insertable Streams工作器那里。

Insertable Streams工作器会将检测到的面部元数据附加到接收到的下一个视频帧中。该视频帧将被发送到服务并循环返回到浏览器,在此浏览器将再次对其进行处理,Insertable Streams工作器从帧中提取元数据(因此可以再次解码),然后将带有面部信息的消息发布到主线程。

let detector;
onmessage = async (event) => {
    //Depending on the mode
    switch(event.data.cmd)
    {
        case "detector" :
        {
            //get detector
            detector = event.data.port;
            //Listen
            detector.onmessage = (event) => {
                //get face data
                face = event.data;
            };
            //Done
            break;
        }
        case "insert":
        {
            //Get streams
            const {readableStream, writableStream} = event.data;
            //New transform stream for inserting metadata
            const transformStream = new TransformStream ({transform: insert});
            //Pipe
            readableStream
                .pipeThrough (transformStream)
                .pipeTo (writableStream);
            //Done
            break;
        }
        case "extract":
        {
            //Get streams
            const {readableStream, writableStream} = event.data;
            //New transform stream for inserting metadata
            const transformStream = new TransformStream ({transform: extract});
            //Pipe
            readableStream
                .pipeThrough (transformStream)
                .pipeTo (writableStream);
            //Done
            break;
        }
    }
};
view rawworker.js hosted with ❤ by GitHub

Web 工作器在视频帧上插入和提取面部元数据

然后,主线程会对视频元素应用进行css转换,在参与者的观看区域的中心显示其人脸。

https://sgmedooze.cosmosoftware.io/insertable-face

你可以看到一个著名的BBC主播直播时被孩子打断的原本情况。用我们的技术替代后,效果如下:

Insertable Streams API和TransformStream的精美设计还使该元数据的插入/提取过程与端到端加密过程得以轻松连接。这样,通过服务器发送的元数据被端到端加密,并且对SFU保密:

//Get streams
const {readableStream, writableStream} = event.data;
//New transform stream for inserting metadata
const transformStreamMetadata = new TransformStream ({transform: insert});
//New transform stream for encryption
const transformStreamEncrypt = new TransformStream ({transform: encrypt});
//Pipe
readableStream
    .pipeThrough (transformStreamMetadata)
    .pipeThrough (transformStreamEncrypt)
    .pipeTo (writableStream);
view rawsample.js hosted with ❤ by GitHub

端到端元数据加密

总结

  1. WebRTC已经成熟,并且该公司正准备发布第二代服务了,重点是改善用户体验,更好地适应其主要用例;
  2. WebRTC(或libWebRTC)的默认行为已从能够实现最高质量转变为能够实现所需的基本水平。有关如何超越基本体验的示例,参见增强音频处理基于Google DUO AI的丢包隐藏算法。需要很多非常具体的专业知识和技能;
  3. 基于WebRTC NV要求的新WebRTC API(例如Insertable Streams),将成为开发人员探索和使用它们来创新的非常强大的工具;
  4. 客户端开发将比以往任何时候都更加重要,但也难以实现;
  5. 在不久的将来,WebCodec、WebTransport和WASM将进一步扩大Web应用程序的容量。

原文地址:https://levelup.gitconnected.com/adding-metadata-to-media-frames-via-insertable-streams-api-for-webrtc-47f7a740e457

文章作者:Medooze

 

填写常用邮箱,接收社区更新

WebRTC 中文社区由

运营