您的位置 首页 > 德语词汇

cselement是什么意思?用法、例句,浏览器最新支持的WebCodecs 到底是什么?

各位老铁们,大家好,今天由我来为大家分享cselement是什么意思?用法、例句,以及浏览器最新支持的WebCodecs 到底是什么?的相关问题知识,希望对大家有所帮助。如果可以帮助到大家,还望关注收藏下本站,您的支持是我们最大的动力,谢谢大家了哈,下面我们开始吧!

大家好,很高兴又见面了,我是"高前端?进阶?",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!

现代技术提供了丰富的视频处理方式,比如MediaStreamAPI、MediaRecordingAPI、MediaSourceAPI和WebRTCAPI共同组成了一个用于录制、传输和播放视频流的丰富工具集。

cselement是什么意思?用法、例句,浏览器最新支持的WebCodecs 到底是什么?

在Chrome94+版本上已经支持了WebCodecs!

在解决某些高级任务时,这些API不允许Web开发者处理视频流的各个组成部分,例如帧、未混合的编码视频或音频块。为了获得对这些基本组件的底层访问,开发人员一直在使用WebAssembly将视频和音频编解码器引入浏览器。但鉴于现代浏览器已经附带了各种编解码器,将它们重新打包为WebAssembly似乎是对人力和计算机资源的浪费。

WebCodecsAPI为开发者提供了一种使用浏览器中已经存在的媒体组件的方法,从而提高了效率。具体包括以下部分:

WebCodecsAPI对于需要完全控制媒体内容处理方式的Web应用程序非常有用,例如视频编辑器、视频会议、视频流等。

帧是视频处理的核心。因此,在WebCodecs中,大多数类要么消费帧,要么生产帧。视频编码器将帧转换为编码块,而视频解码器则相反。可以通过如下方法判断浏览器是否支持WebCodecs:

if(window.isSecureContext){\n//页面上下文完全,同时serviceWorker加载完成\nnavigator.serviceWorker.register("/offline-worker.js").then(()=>{\n});\n}\nif('VideoEncoder'inwindow){\n//支持WebCodecsAPI\n}

请记住,WebCodecs仅在安全上下文中可用,因此如果self.isSecureContext为false,检测将失败!

VideoFrame通过成为CanvasImageSource并具有接受CanvasImageSource的构造函数,可以很好地与其他WebAPI配合使用。所以它可以用在drawImage()和texImage2D()等函数中。它也可以由画布、位图、视频元素和其他视频帧构建。VideoFrame的构造函数如下:

newVideoFrame(image)\nnewVideoFrame(image,options)\nnewVideoFrame(data,options)\n//第二个参数为配置对象

下面是VideoFrame的一个典型示例:

constpixelSize=4;\nconstinit={timestamp:0,codedWidth:320,codedHeight:200,format:'RGBA'};\nletdata=newUint8Array(init.codedWidth*init.codedHeight*pixelSize);\nfor(letx=0;x<init.codedWidth;x++){\nfor(lety=0;y<init.codedHeight;y++){\nletoffset=(y*init.codedWidth+x)*pixelSize;\ndata[offset]=0x7F;\n//Red\ndata[offset+1]=0xFF;\n//Green\ndata[offset+2]=0xD4;\n//Blue\ndata[offset+3]=0x0FF;\n//Alpha\n}\n}\nletframe=newVideoFrame(data,init);

WebCodecsAPI与InsertableStreamsAPI中的类协同工作,后者将WebCodecs连接到媒体流轨道(MediaStreamTracks)。

MediaStreamTrack接口表示流中的单个媒体轨道;通常,这些是音频或视频轨道,但也可能存在其他轨道类型。

根据设计,WebCodecsAPI异步完成所有繁重的工作并脱离主线程。但是由于框架和块回调通常可以每秒调用多次,它们可能会使主线程混乱,从而降低网站的响应速度。因此,最好将单个帧和编码块的处理转移到WebWorker中。

为此,ReadableStream提供了一种方便的方法来自动将来自媒体轨道的所有帧传输到工作程序。例如,MediaStreamTrackProcessor可用于获取来自网络摄像头的媒体流轨道的ReadableStream。之后,流被传输到WebWorker,其中帧被一个一个地读取并排队进入VideoEncoder。

StreamsAPI的ReadableStream接口表示字节数据的可读流。FetchAPI通过Response对象的body属性提供了ReadableStream的具体实例。

使用HTMLCanvasElement.transferControlToOffscreen甚至可以在主线程之外完成渲染。如果所有高级工具都不符合要求,VideoFrame本身是可转移的,可以在WebWorker之间移动。

这一切都始于VideoFrame,可以通过三种方式构建视频帧。

constcanvas=document.createElement("canvas");\n//在Canvas中绘制\nconstframeFromCanvas=newVideoFrame(canvas,{timestamp:0});使用MediaStreamTrackProcessor从MediaStreamTrack拉取帧

conststream=awaitnavigator.mediaDevices.getUserMedia({\naudio:true,\nvideo:{\nwidth:{min:1024,ideal:1280,max:1920},\nheight:{min:576,ideal:720,max:1080}\n}\n});\n//获取媒体帧的配置:https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia\nconsttrack=stream.getTracks()[0];\nconsttrackProcessor=newMediaStreamTrackProcessor(track);\nconstreader=trackProcessor.readable.getReader();\nwhile(true){\nconstresult=awaitreader.read();\n//读取数据\nif(result.done)break;\nconstframeFromCamera=result.value;\n}从BufferSource中的二进制像素创建帧

constpixelSize=4;\nconstinit={\ntimestamp:0,\ncodedWidth:320,\ncodedHeight:200,\nformat:"RGBA",\n};\nconstdata=newUint8Array(init.codedWidth*init.codedHeight*pixelSize);\n//创建Uint8Array对象\nfor(letx=0;x<init.codedWidth;x++){\nfor(lety=0;y<init.codedHeight;y++){\nconstoffset=(y*init.codedWidth+x)*pixelSize;\ndata[offset]=0x7f;//Red\ndata[offset+1]=0xff;//Green\ndata[offset+2]=0xd4;//Blue\ndata[offset+3]=0x0ff;//Alpha\n}\n}\nconstframe=newVideoFrame(data,init);\n//实例化VideoFrame对象

无论那种方式,都可以使用VideoEncoder将帧编码到EncodedVideoChunk对象中。在编码之前,需要给VideoEncoder两个JavaScript对象:

如果浏览器不支持配置,则configure()方法将抛出NotSupportedError。鼓励您使用配置调用静态方法VideoEncoder.isConfigSupported()以预先检查配置是否受支持并等待其promise的结果。

constinit={\noutput:handleChunk,\n//处理快\nerror:(e)=>{\nconsole.log(e.message);\n},\n//处理错误\n};\nconstconfig={\ncodec:"vp8",\nwidth:640,\nheight:480,\nbitrate:2_000_000,//2Mbps\nframerate:30,\n};\nconst{supported}=awaitVideoEncoder.isConfigSupported(config);\n//判断是否支持\nif(supported){\nconstencoder=newVideoEncoder(init);\nencoder.configure(config);\n}else{\n//Tryanotherconfig.\n}

设置编码器后就可以通过encode()方法接受帧了。configure()和encode()都立即返回,无需等待实际工作完成。它允许多个帧同时排队等待编码,而encodeQueueSize显示有多少请求在队列中等待先前的编码完成。

如果参数或方法调用顺序违反API约定,或者通过调用error()回调来解决编解码器实现中遇到的问题,可以通过立即抛出异常来报告错误。如果编码成功完成,将使用新的编码块作为参数调用output()回调。

这里的另一个重要细节是,当不再需要框架时,需要通过调用close()来告知它们。

letframeCounter=0;\nconsttrack=stream.getVideoTracks()[0];\nconsttrackProcessor=newMediaStreamTrackProcessor(track);\nconstreader=trackProcessor.readable.getReader();\nwhile(true){\nconstresult=awaitreader.read();\nif(result.done)break;\nconstframe=result.value;\nif(encoder.encodeQueueSize>2){\n//太多帧要处理,编码器过载,丢弃当前帧\nframe.close();\n}else{\nframeCounter++;\nconstkeyframe=frameCounter%150==0;\nencoder.encode(frame,{keyFrame});\nframe.close();\n}\n}

最后是通过编写一个函数来完成编码代码的时候了,该函数处理来自编码器的编码视频块。通常此功能将通过网络发送数据块或将它们混合到媒体容器中进行存储。

functionhandleChunk(chunk,metadata){\nif(metadata.decoderConfig){\n//Decoderneedstobeconfigured(orreconfigured)withnewparameters\n//whenmetadatahasanewdecoderConfig.\n//Usuallyithappensinthebeginningorwhentheencoderhasanew\n//codecspecificbinaryconfiguration.(VideoDecoderConfig.description).\nfetch("/upload_extra_data",{\nmethod:"POST",\nheaders:{"Content-Type":"application/octet-stream"},\nbody:metadata.decoderConfig.description,\n});\n}\n//真实编码数据块大小\nconstchunkData=newUint8Array(chunk.byteLength);\nchunk.copyTo(chunkData);\nfetch(`/upload_chunk?timestamp=${chunk.timestamp}&type=${chunk.type}`,{\nmethod:"POST",\nheaders:{"Content-Type":"application/octet-stream"},\nbody:chunkData,\n});\n}

如果在某个时候您需要确保所有待处理的编码请求都已完成,可以调用flush()并等待它的promise结果。

awaitencoder.flush();3.解码

设置VideoDecoder与VideoEncoder类似:创建解码器时需要传递两个函数,并将编解码器参数提供给configure()。

编解码器参数因编解码器而异。例如,H.264编解码器可能需要AVCC的二进制blob,除非它以所谓的AnnexB格式编码(encoderConfig.avc={format:"annexb"})。

constinit={\noutput:handleFrame,\nerror:(e)=>{\nconsole.log(e.message);\n},\n};\n\nconstconfig={\ncodec:"vp8",\ncodedWidth:640,\ncodedHeight:480,\n};\nconst{supported}=awaitVideoDecoder.isConfigSupported(config);\nif(supported){\nconstdecoder=newVideoDecoder(init);\n//实例化编码器\ndecoder.configure(config);\n//配置编码器\n}else{\n//Tryanotherconfig.\n}

解码器初始化后,您可以开始为其提供EncodedVideoChunk对象。要创建块,您需要:

此外,编码器发出的任何块都可以按原样为解码器准备好。上面所说的关于错误报告和编码器方法的异步性质的所有内容对于解码器也同样适用。

constresponses=awaitdownloadVideoChunksFromServer(timestamp);\nfor(leti=0;i<responses.length;i++){\nconstchunk=newEncodedVideoChunk({\ntimestamp:responses[i].timestamp,\ntype:responses[i].key?"key":"delta",\ndata:newUint8Array(responses[i].body),\n});\ndecoder.decode(chunk);\n}\nawaitdecoder.flush();

现在是时候展示如何在页面上显示新解码的帧了。最好确保解码器输出回调(handleFrame())快速返回。在下面的示例中,它仅将一个帧添加到准备渲染的帧队列中。渲染是单独发生的,由两个步骤组成:

一旦不再需要某个帧,调用close()以在垃圾收集器到达它之前释放底层内存,这将减少Web应用程序使用的平均内存量。

constcanvas=document.getElementById("canvas");\nconstctx=canvas.getContext("2d");\nletpendingFrames=[];\nletunderflow=true;\nletbaseTime=0;\n\nfunctionhandleFrame(frame){\npendingFrames.push(frame);\nif(underflow)setTimeout(renderFrame,0);\n}\n\nfunctioncalculateTimeUntilNextFrame(timestamp){\nif(baseTime==0)baseTime=performance.now();\nletmediaTime=performance.now()-baseTime;\nreturnMath.max(0,timestamp/1000-mediaTime);\n}\n\nasyncfunctionrenderFrame(){\nunderflow=pendingFrames.length==0;\nif(underflow)return;\nconstframe=pendingFrames.shift();\n//Basedontheframe'stimestampcalculatehowmuchofrealtimewaiting\n//isneededbeforeshowingthenextframe.\nconsttimeUntilNextFrame=calculateTimeUntilNextFrame(frame.timestamp);\nawaitnewPromise((r)=>{\nsetTimeout(r,timeUntilNextFrame);\n});\nctx.drawImage(frame,0,0);\nframe.close();\n//立即启动下一帧的调用逻辑\nsetTimeout(renderFrame,0);\n}参考资料

https://developer.chrome.com/articles/webcodecs/(Chrome官方文档)

https://developer.mozilla.org/en-US/docs/Web/API/isSecureContext

https://developer.mozilla.org/en-US/docs/Web/Security/Secure_Contexts

https://developer.mozilla.org/en-US/docs/Web/API/ReadableStream

https://www.w3.org/2020/06/machine-learning-workshop/talks/media_processing_hooks_for_the_web.html

好了,关于cselement是什么意思?用法、例句和浏览器最新支持的WebCodecs 到底是什么?的问题到这里结束啦,希望可以解决您的问题哈!

本站涵盖的内容、图片、视频等数据,部分未能与原作者取得联系。若涉及版权问题,请及时通知我们并提供相关证明材料,我们将及时予以删除!谢谢大家的理解与支持!

Copyright © 2023