网站建设公司简介京东网站怎么做

张小明 2026/1/9 12:03:40
网站建设公司简介,京东网站怎么做,工程造价信息价在什么网站查,电脑怎么创建网站吗WebRTC 的 API 全景图#xff08;API 体系篇#xff09; 本文是 WebRTC 系列专栏的第五篇#xff0c;也是基础入门部分的收官之作。我们将全面梳理 WebRTC 的 API 体系#xff0c;帮助你掌握所有核心 API 的职责与用法。 目录 API 体系概览getUserMedia 详解RTCPeerConnec…WebRTC 的 API 全景图API 体系篇本文是 WebRTC 系列专栏的第五篇也是基础入门部分的收官之作。我们将全面梳理 WebRTC 的 API 体系帮助你掌握所有核心 API 的职责与用法。目录API 体系概览getUserMedia 详解RTCPeerConnection 完整 APIRTCRtpSender / ReceiverRTCDataChannel其他重要 API总结1. API 体系概览1.1 WebRTC API 分类┌─────────────────────────────────────────────────────────────────────────┐ │ WebRTC API 体系 │ ├─────────────────────────────────────────────────────────────────────────┤ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 媒体捕获 API │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ │ │ getUserMedia() │ │getDisplayMedia()│ │enumerateDevices │ │ │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 媒体流 API │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ │ │ MediaStream │ │MediaStreamTrack │ │ MediaDevices │ │ │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 连接 API │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ │ │RTCPeerConnection│ │RTCSessionDescr. │ │ RTCIceCandidate │ │ │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ RTP API │ │ │ │ ┌─────────────────┐ ┌─────────────────┐ ┌─────────────────┐ │ │ │ │ │ RTCRtpSender │ │ RTCRtpReceiver │ │RTCRtpTransceiver│ │ │ │ │ └─────────────────┘ └─────────────────┘ └─────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 数据通道 API │ │ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ │ │ RTCDataChannel │ │ │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ │ ┌─────────────────────────────────────────────────────────────────┐ │ │ │ 统计 API │ │ │ │ ┌─────────────────────────────────────────────────────────┐ │ │ │ │ │ RTCStatsReport │ │ │ │ │ └─────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────┘ │ │ │ └─────────────────────────────────────────────────────────────────────────┘1.2 API 职责速查表API职责关键方法/属性getUserMedia()获取摄像头/麦克风constraints, streamgetDisplayMedia()屏幕共享constraints, streamMediaStream媒体流容器getTracks(), addTrack()MediaStreamTrack单个音视频轨道enabled, stop()RTCPeerConnectionP2P 连接核心createOffer(), addTrack()RTCRtpSender发送 RTP 流setParameters(), replaceTrack()RTCRtpReceiver接收 RTP 流getStats(), trackRTCRtpTransceiver收发器direction, sender, receiverRTCDataChannel数据通道send(), onmessage2. getUserMedia 详解2.1 基本语法conststreamawaitnavigator.mediaDevices.getUserMedia(constraints);2.2 约束Constraints详解基础约束// 最简单的约束constconstraints{video:true,audio:true};// 只获取音频constaudioOnly{video:false,audio:true};// 只获取视频constvideoOnly{video:true,audio:false};视频约束constvideoConstraints{video:{// 分辨率约束width:{min:640,ideal:1280,max:1920},height:{min:480,ideal:720,max:1080},// 宽高比aspectRatio:{ideal:16/9},// 帧率frameRate:{min:15,ideal:30,max:60},// 摄像头选择facingMode:user,// user 前置, environment 后置// facingMode: { exact: environment }, // 强制后置// 指定设备deviceId:{exact:camera-device-id},// 分组 ID同一物理设备的多个功能groupId:group-id},audio:true};音频约束constaudioConstraints{video:false,audio:{// 设备选择deviceId:{exact:microphone-device-id},// 音频处理echoCancellation:true,// 回声消除noiseSuppression:true,// 噪声抑制autoGainControl:true,// 自动增益控制// 采样参数sampleRate:48000,// 采样率sampleSize:16,// 采样位深channelCount:2,// 声道数// 延迟latency:{ideal:0.01}// 目标延迟秒}};约束语法详解// 约束值可以是以下形式// 1. 布尔值video:true// 2. 精确值width:{exact:1280}// 3. 理想值尽量满足不满足也可以width:{ideal:1280}// 4. 范围width:{min:640,max:1920}// 5. 组合width:{min:640,ideal:1280,max:1920}2.3 设备枚举// 获取所有媒体设备asyncfunctiongetDevices(){constdevicesawaitnavigator.mediaDevices.enumerateDevices();constvideoInputsdevices.filter(dd.kindvideoinput);constaudioInputsdevices.filter(dd.kindaudioinput);constaudioOutputsdevices.filter(dd.kindaudiooutput);console.log(摄像头:,videoInputs);console.log(麦克风:,audioInputs);console.log(扬声器:,audioOutputs);return{videoInputs,audioInputs,audioOutputs};}// 设备信息结构interfaceMediaDeviceInfo{deviceId:string;// 设备唯一标识groupId:string;// 设备组标识kind:videoinput|audioinput|audiooutput;label:string;// 设备名称需要权限才能获取}2.4 设备变化监听// 监听设备插拔navigator.mediaDevices.ondevicechangeasync(){console.log(设备列表已变化);constdevicesawaitnavigator.mediaDevices.enumerateDevices();updateDeviceList(devices);};2.5 屏幕共享// 获取屏幕共享constscreenStreamawaitnavigator.mediaDevices.getDisplayMedia({video:{cursor:always,// always | motion | neverdisplaySurface:monitor,// monitor | window | browserlogicalSurface:true,width:{max:1920},height:{max:1080},frameRate:{max:30}},audio:true// 系统音频部分浏览器支持});// 监听用户停止共享screenStream.getVideoTracks()[0].onended(){console.log(用户停止了屏幕共享);};2.6 错误处理asyncfunctiongetMediaWithErrorHandling(){try{conststreamawaitnavigator.mediaDevices.getUserMedia({video:true,audio:true});returnstream;}catch(error){switch(error.name){caseNotAllowedError:// 用户拒绝权限alert(请允许访问摄像头和麦克风);break;caseNotFoundError:// 找不到设备alert(未找到摄像头或麦克风);break;caseNotReadableError:// 设备被占用alert(设备被其他应用占用);break;caseOverconstrainedError:// 约束无法满足console.log(无法满足的约束:,error.constraint);// 尝试降低约束returnawaitnavigator.mediaDevices.getUserMedia({video:true,audio:true});caseSecurityError:// 安全错误非 HTTPSalert(请使用 HTTPS 访问);break;caseTypeError:// 约束格式错误console.error(约束格式错误);break;default:console.error(未知错误:,error);}throwerror;}}2.7 获取设备能力// 获取轨道的能力范围conststreamawaitnavigator.mediaDevices.getUserMedia({video:true});constvideoTrackstream.getVideoTracks()[0];// 获取能力constcapabilitiesvideoTrack.getCapabilities();console.log(设备能力:,capabilities);// {// width: { min: 1, max: 1920 },// height: { min: 1, max: 1080 },// frameRate: { min: 1, max: 60 },// facingMode: [user, environment],// ...// }// 获取当前设置constsettingsvideoTrack.getSettings();console.log(当前设置:,settings);// {// width: 1280,// height: 720,// frameRate: 30,// deviceId: ...,// ...// }// 获取约束constconstraintsvideoTrack.getConstraints();console.log(当前约束:,constraints);2.8 动态调整约束// 应用新约束asyncfunctionapplyConstraints(track,newConstraints){try{awaittrack.applyConstraints(newConstraints);console.log(约束应用成功);}catch(error){console.error(约束应用失败:,error);}}// 示例切换分辨率constvideoTrackstream.getVideoTracks()[0];awaitvideoTrack.applyConstraints({width:{ideal:1920},height:{ideal:1080}});3. RTCPeerConnection 完整 API3.1 构造函数与配置constconfiguration{// ICE 服务器配置iceServers:[{urls:stun:stun.l.google.com:19302},{urls:[turn:turn.example.com:3478,turns:turn.example.com:443],username:user,credential:password,credentialType:password// password | oauth}],// ICE 传输策略iceTransportPolicy:all,// all | relay// Bundle 策略多路复用bundlePolicy:max-bundle,// balanced | max-compat | max-bundle// RTCP 复用策略rtcpMuxPolicy:require,// require | negotiate// ICE 候选池大小iceCandidatePoolSize:0,// 证书可选用于 DTLScertificates:[awaitRTCPeerConnection.generateCertificate({name:ECDSA,namedCurve:P-256})]};constpcnewRTCPeerConnection(configuration);3.2 信令相关方法创建 Offer/Answer// 创建 OfferconstofferOptions{offerToReceiveAudio:true,offerToReceiveVideo:true,iceRestart:false,// 是否重启 ICEvoiceActivityDetection:true// 语音活动检测};constofferawaitpc.createOffer(offerOptions);// 创建 AnswerconstanswerOptions{voiceActivityDetection:true};constanswerawaitpc.createAnswer(answerOptions);设置描述// 设置本地描述awaitpc.setLocalDescription(offer);// 或使用隐式创建awaitpc.setLocalDescription();// 自动创建 offer 或 answer// 设置远端描述awaitpc.setRemoteDescription(newRTCSessionDescription({type:answer,sdp:remoteSdp}));ICE 候选// 添加远端 ICE 候选awaitpc.addIceCandidate(newRTCIceCandidate({candidate:candidate:...,sdpMid:0,sdpMLineIndex:0}));// 也可以传入 null 表示候选收集完成awaitpc.addIceCandidate(null);3.3 媒体相关方法添加/移除轨道// 添加轨道constsenderpc.addTrack(track,stream);// 移除轨道pc.removeTrack(sender);// 获取所有发送器constsenderspc.getSenders();// 获取所有接收器constreceiverspc.getReceivers();// 获取所有收发器consttransceiverspc.getTransceivers();添加收发器// 添加收发器更精细的控制consttransceiverpc.addTransceiver(video,{direction:sendrecv,// sendrecv | sendonly | recvonly | inactivestreams:[stream],sendEncodings:[{rid:high,maxBitrate:2500000},{rid:medium,maxBitrate:1000000,scaleResolutionDownBy:2},{rid:low,maxBitrate:500000,scaleResolutionDownBy:4}]});// 也可以传入轨道consttransceiver2pc.addTransceiver(videoTrack,{direction:sendonly});3.4 数据通道// 创建数据通道constdataChannelpc.createDataChannel(myChannel,{ordered:true,// 是否保证顺序maxPacketLifeTime:3000,// 最大生存时间ms// maxRetransmits: 3, // 或最大重传次数二选一protocol:json,// 子协议negotiated:false,// 是否手动协商id:0// 通道 ID});// 监听远端创建的数据通道pc.ondatachannel(event){constremoteChannelevent.channel;};3.5 状态属性// 连接状态pc.connectionState;// new | connecting | connected | disconnected | failed | closed// 信令状态pc.signalingState;// stable | have-local-offer | have-remote-offer |// have-local-pranswer | have-remote-pranswer | closed// ICE 连接状态pc.iceConnectionState;// new | checking | connected | completed |// failed | disconnected | closed// ICE 收集状态pc.iceGatheringState;// new | gathering | complete// 本地/远端描述pc.localDescription;// RTCSessionDescription | nullpc.remoteDescription;// RTCSessionDescription | nullpc.currentLocalDescription;pc.currentRemoteDescription;pc.pendingLocalDescription;pc.pendingRemoteDescription;// SCTP 传输用于 DataChannelpc.sctp;// RTCSctpTransport | null3.6 事件处理// 信令事件 // 需要重新协商如添加/移除轨道后pc.onnegotiationneededasync(){constofferawaitpc.createOffer();awaitpc.setLocalDescription(offer);// 发送 offer 到远端};// 信令状态变化pc.onsignalingstatechange(){console.log(信令状态:,pc.signalingState);};// ICE 事件 // 收集到 ICE 候选pc.onicecandidate(event){if(event.candidate){// 发送候选到远端}else{// 候选收集完成}};// ICE 候选错误pc.onicecandidateerror(event){console.error(ICE 错误:,event.errorCode,event.errorText);};// ICE 连接状态变化pc.oniceconnectionstatechange(){console.log(ICE 连接状态:,pc.iceConnectionState);};// ICE 收集状态变化pc.onicegatheringstatechange(){console.log(ICE 收集状态:,pc.iceGatheringState);};// 连接事件 // 连接状态变化pc.onconnectionstatechange(){console.log(连接状态:,pc.connectionState);switch(pc.connectionState){caseconnected:console.log(连接成功);break;casedisconnected:console.log(连接断开尝试重连...);break;casefailed:console.log(连接失败);pc.close();break;}};// 媒体事件 // 收到远端轨道pc.ontrack(event){const{track,streams,receiver,transceiver}event;console.log(收到轨道:,track.kind);// 绑定到视频元素if(streams[0]){remoteVideo.srcObjectstreams[0];}};// 数据通道事件 // 收到远端创建的数据通道pc.ondatachannel(event){constchannelevent.channel;channel.onmessage(e)console.log(收到消息:,e.data);};3.7 统计信息// 获取所有统计信息conststatsawaitpc.getStats();// 遍历统计报告stats.forEach(report{console.log(${report.type}:${report.id});console.log(report);});// 获取特定发送器的统计constsenderStatsawaitpc.getStats(sender);// 常用统计类型stats.forEach(report{switch(report.type){caseoutbound-rtp:// 发送 RTP 统计console.log(发送统计:,{bytesSent:report.bytesSent,packetsSent:report.packetsSent,framesEncoded:report.framesEncoded,framesSent:report.framesSent});break;caseinbound-rtp:// 接收 RTP 统计console.log(接收统计:,{bytesReceived:report.bytesReceived,packetsReceived:report.packetsReceived,packetsLost:report.packetsLost,jitter:report.jitter});break;casecandidate-pair:// 候选对统计if(report.statesucceeded){console.log(连接统计:,{availableOutgoingBitrate:report.availableOutgoingBitrate,currentRoundTripTime:report.currentRoundTripTime});}break;}});3.8 关闭连接// 关闭连接pc.close();// 关闭后状态console.log(pc.connectionState);// closedconsole.log(pc.signalingState);// closed4. RTCRtpSender / Receiver4.1 RTCRtpSenderRTCRtpSender 负责发送 RTP 流。属性constsenderpc.getSenders()[0];// 关联的轨道sender.track;// MediaStreamTrack | null// 关联的 DTLS 传输sender.transport;// RTCDtlsTransport | null// 关联的 DTMF 发送器音频轨道sender.dtmf;// RTCDTMFSender | null方法// 替换轨道无需重新协商awaitsender.replaceTrack(newTrack);// 获取参数constparamssender.getParameters();console.log(params);// {// encodings: [...],// transactionId: ...,// codecs: [...],// headerExtensions: [...],// rtcp: { cname: ..., reducedSize: true }// }// 设置参数params.encodings[0].maxBitrate1000000;awaitsender.setParameters(params);// 获取统计conststatsawaitsender.getStats();// 获取能力静态方法constcapabilitiesRTCRtpSender.getCapabilities(video);console.log(capabilities);// {// codecs: [// { mimeType: video/VP8, clockRate: 90000 },// { mimeType: video/VP9, clockRate: 90000 },// { mimeType: video/H264, clockRate: 90000, sdpFmtpLine: ... },// ...// ],// headerExtensions: [...]// }编码参数constparamssender.getParameters();// 修改编码参数params.encodings[0]{active:true,// 是否激活maxBitrate:2500000,// 最大码率bpsmaxFramerate:30,// 最大帧率scaleResolutionDownBy:1,// 分辨率缩放因子priority:high,// very-low | low | medium | highnetworkPriority:high};awaitsender.setParameters(params);Simulcast同时发送多路// 添加带 Simulcast 的收发器consttransceiverpc.addTransceiver(videoTrack,{direction:sendonly,sendEncodings:[{rid:high,maxBitrate:2500000},{rid:medium,maxBitrate:1000000,scaleResolutionDownBy:2},{rid:low,maxBitrate:500000,scaleResolutionDownBy:4}]});// 动态调整某一路constparamstransceiver.sender.getParameters();params.encodings[2].activefalse;// 禁用低质量层awaittransceiver.sender.setParameters(params);4.2 RTCRtpReceiverRTCRtpReceiver 负责接收 RTP 流。属性constreceiverpc.getReceivers()[0];// 关联的轨道receiver.track;// MediaStreamTrack// 关联的 DTLS 传输receiver.transport;// RTCDtlsTransport | null方法// 获取统计conststatsawaitreceiver.getStats();// 获取贡献源混音场景constcontributingSourcesreceiver.getContributingSources();// [{ source: 12345, timestamp: 1234567890, audioLevel: 0.5 }, ...]// 获取同步源constsynchronizationSourcesreceiver.getSynchronizationSources();// 获取能力静态方法constcapabilitiesRTCRtpReceiver.getCapabilities(audio);4.3 RTCRtpTransceiverRTCRtpTransceiver 组合了 Sender 和 Receiver。consttransceiverpc.getTransceivers()[0];// 属性transceiver.mid;// 媒体 IDSDP 中的 midtransceiver.sender;// RTCRtpSendertransceiver.receiver;// RTCRtpReceivertransceiver.direction;// sendrecv | sendonly | recvonly | inactive | stoppedtransceiver.currentDirection;// 当前实际方向// 设置方向transceiver.directionsendonly;// 停止收发器transceiver.stop();// 设置编解码器偏好constcodecsRTCRtpReceiver.getCapabilities(video).codecs;constvp9Codecscodecs.filter(cc.mimeTypevideo/VP9);transceiver.setCodecPreferences(vp9Codecs);5. RTCDataChannel5.1 创建数据通道// 发起方创建constdataChannelpc.createDataChannel(myChannel,{ordered:true,// 保证顺序默认 truemaxPacketLifeTime:3000,// 最大生存时间ms// maxRetransmits: 3, // 最大重传次数与上面二选一protocol:,// 子协议negotiated:false,// 是否手动协商id:undefined// 通道 IDnegotiated 为 true 时必须指定});// 接收方监听pc.ondatachannel(event){constreceiveChannelevent.channel;};5.2 配置选项详解选项类型默认值说明orderedbooleantrue是否保证消息顺序maxPacketLifeTimenumber-消息最大生存时间msmaxRetransmitsnumber-最大重传次数protocolstring‘’子协议名称negotiatedbooleanfalse是否手动协商idnumber自动通道 ID可靠性配置// 可靠有序默认类似 TCPconstreliablepc.createDataChannel(reliable,{ordered:true});// 不可靠无序类似 UDPconstunreliablepc.createDataChannel(unreliable,{ordered:false,maxRetransmits:0});// 部分可靠最多重传 3 次constpartiallyReliablepc.createDataChannel(partial,{ordered:true,maxRetransmits:3});// 部分可靠最多等待 3 秒consttimedReliablepc.createDataChannel(timed,{ordered:true,maxPacketLifeTime:3000});手动协商// 双方使用相同配置创建通道// 发起方constchannel1pc.createDataChannel(sync,{negotiated:true,id:0});// 接收方constchannel2pc.createDataChannel(sync,{negotiated:true,id:0});// 无需等待 ondatachannel 事件5.3 属性// 只读属性dataChannel.label;// 通道名称dataChannel.ordered;// 是否有序dataChannel.maxPacketLifeTime;// 最大生存时间dataChannel.maxRetransmits;// 最大重传次数dataChannel.protocol;// 子协议dataChannel.negotiated;// 是否手动协商dataChannel.id;// 通道 IDdataChannel.readyState;// connecting | open | closing | closeddataChannel.bufferedAmount;// 缓冲区待发送字节数// 可读写属性dataChannel.binaryType;// blob | arraybuffer默认 blobdataChannel.bufferedAmountLowThreshold;// 缓冲区低阈值5.4 方法// 发送数据dataChannel.send(text message);dataChannel.send(newArrayBuffer(1024));dataChannel.send(newBlob([binary data]));dataChannel.send(newUint8Array([1,2,3,4]));// 关闭通道dataChannel.close();5.5 事件// 通道打开dataChannel.onopen(){console.log(通道已打开);};// 通道关闭dataChannel.onclose(){console.log(通道已关闭);};// 收到消息dataChannel.onmessage(event){console.log(收到消息:,event.data);// 根据 binaryType 处理if(typeofevent.datastring){// 文本消息}elseif(event.datainstanceofArrayBuffer){// 二进制消息}elseif(event.datainstanceofBlob){// Blob 消息}};// 错误dataChannel.onerror(error){console.error(通道错误:,error);};// 缓冲区低于阈值dataChannel.onbufferedamountlow(){console.log(缓冲区已清空可以继续发送);};5.6 流量控制// 设置缓冲区低阈值dataChannel.bufferedAmountLowThreshold65536;// 64KB// 发送大文件时的流量控制asyncfunctionsendFile(file){constchunkSize16384;// 16KBconstreaderfile.stream().getReader();while(true){const{done,value}awaitreader.read();if(done)break;// 等待缓冲区清空while(dataChannel.bufferedAmountchunkSize*10){awaitnewPromise(resolve{dataChannel.onbufferedamountlowresolve;});}dataChannel.send(value);}}5.7 实际应用示例文件传输// 发送端asyncfunctionsendFile(file,dataChannel){// 发送文件元信息dataChannel.send(JSON.stringify({type:file-meta,name:file.name,size:file.size,mimeType:file.type}));// 分块发送文件内容constchunkSize16384;constreadernewFileReader();letoffset0;constreadNextChunk(){constslicefile.slice(offset,offsetchunkSize);reader.readAsArrayBuffer(slice);};reader.onload(e){dataChannel.send(e.target.result);offsete.target.result.byteLength;if(offsetfile.size){// 流量控制if(dataChannel.bufferedAmountchunkSize*10){readNextChunk();}else{dataChannel.onbufferedamountlowreadNextChunk;}}else{dataChannel.send(JSON.stringify({type:file-end}));}};readNextChunk();}// 接收端letfileBuffer[];letfileMetanull;dataChannel.onmessage(event){if(typeofevent.datastring){constmessageJSON.parse(event.data);if(message.typefile-meta){fileMetamessage;fileBuffer[];}elseif(message.typefile-end){constblobnewBlob(fileBuffer,{type:fileMeta.mimeType});downloadFile(blob,fileMeta.name);}}else{fileBuffer.push(event.data);}};6. 其他重要 API6.1 MediaStream// 创建空的 MediaStreamconststreamnewMediaStream();// 从轨道创建conststream2newMediaStream([videoTrack,audioTrack]);// 克隆流constclonedStreamstream.clone();// 属性stream.id;// 流 IDstream.active;// 是否有活动轨道// 方法stream.getTracks();// 获取所有轨道stream.getVideoTracks();// 获取视频轨道stream.getAudioTracks();// 获取音频轨道stream.getTrackById(id);// 根据 ID 获取轨道stream.addTrack(track);// 添加轨道stream.removeTrack(track);// 移除轨道// 事件stream.onaddtrack(event){console.log(添加轨道:,event.track);};stream.onremovetrack(event){console.log(移除轨道:,event.track);};6.2 MediaStreamTrackconsttrackstream.getVideoTracks()[0];// 属性track.id;// 轨道 IDtrack.kind;// audio | videotrack.label;// 设备名称track.enabled;// 是否启用可读写track.muted;// 是否静音只读track.readyState;// live | endedtrack.contentHint;// 内容提示可读写// 方法track.clone();// 克隆轨道track.stop();// 停止轨道track.getCapabilities();// 获取能力track.getConstraints();// 获取约束track.getSettings();// 获取当前设置awaittrack.applyConstraints({});// 应用新约束// 事件track.onended(){console.log(轨道已结束);};track.onmute(){console.log(轨道已静音);};track.onunmute(){console.log(轨道已取消静音);};6.3 RTCSessionDescription// 创建会话描述constdescriptionnewRTCSessionDescription({type:offer,// offer | answer | pranswer | rollbacksdp:sdpString});// 属性description.type;// 类型description.sdp;// SDP 字符串// 转换为 JSONconstjsondescription.toJSON();6.4 RTCIceCandidate// 创建 ICE 候选constcandidatenewRTCIceCandidate({candidate:candidate:...,sdpMid:0,sdpMLineIndex:0,usernameFragment:abcd});// 属性candidate.candidate;// 候选字符串candidate.sdpMid;// 媒体 IDcandidate.sdpMLineIndex;// 媒体行索引candidate.foundation;// 基础标识candidate.component;// rtp | rtcpcandidate.priority;// 优先级candidate.address;// IP 地址candidate.protocol;// udp | tcpcandidate.port;// 端口candidate.type;// host | srflx | prflx | relaycandidate.tcpType;// TCP 类型candidate.relatedAddress;// 相关地址candidate.relatedPort;// 相关端口candidate.usernameFragment;// 用户名片段// 转换为 JSONconstjsoncandidate.toJSON();6.5 RTCDTMFSender用于发送 DTMF 音调电话按键音。constsenderpc.getSenders().find(ss.track?.kindaudio);constdtmfSendersender.dtmf;if(dtmfSender){// 检查是否可以发送 DTMFconsole.log(可发送 DTMF:,dtmfSender.canInsertDTMF);// 发送 DTMFdtmfSender.insertDTMF(1234#,100,70);// 参数音调序列, 每个音调持续时间(ms), 间隔时间(ms)// 当前音调队列console.log(音调队列:,dtmfSender.toneBuffer);// 音调发送事件dtmfSender.ontonechange(event){console.log(发送音调:,event.tone);};}6.6 RTCCertificate// 生成证书constcertificateawaitRTCPeerConnection.generateCertificate({name:ECDSA,namedCurve:P-256});// 或使用 RSAconstrsaCertificateawaitRTCPeerConnection.generateCertificate({name:RSASSA-PKCS1-v1_5,modulusLength:2048,publicExponent:newUint8Array([1,0,1]),hash:SHA-256});// 属性certificate.expires;// 过期时间certificate.getFingerprints();// 获取指纹// 使用证书constpcnewRTCPeerConnection({certificates:[certificate]});7. 总结7.1 API 速查表媒体捕获API用途getUserMedia()获取摄像头/麦克风getDisplayMedia()屏幕共享enumerateDevices()枚举设备媒体流API用途MediaStream媒体流容器MediaStreamTrack单个轨道track.enabled启用/禁用轨道track.stop()停止轨道连接管理API用途RTCPeerConnectionP2P 连接createOffer()创建 OffercreateAnswer()创建 AnswersetLocalDescription()设置本地描述setRemoteDescription()设置远端描述addIceCandidate()添加 ICE 候选RTP 控制API用途RTCRtpSender发送控制RTCRtpReceiver接收控制RTCRtpTransceiver收发器replaceTrack()替换轨道setParameters()设置编码参数数据通道API用途createDataChannel()创建数据通道send()发送数据onmessage接收数据7.2 最佳实践// 1. 始终处理错误try{conststreamawaitnavigator.mediaDevices.getUserMedia({video:true});}catch(error){handleError(error);}// 2. 及时释放资源window.addEventListener(beforeunload,(){localStream?.getTracks().forEach(tracktrack.stop());peerConnection?.close();});// 3. 监控连接状态pc.onconnectionstatechange(){if(pc.connectionStatefailed){// 尝试重连或通知用户}};// 4. 使用统计信息监控质量setInterval(async(){conststatsawaitpc.getStats();monitorQuality(stats);},1000);// 5. 优雅降级constconstraints{video:{width:{ideal:1280},height:{ideal:720}}};try{streamawaitnavigator.mediaDevices.getUserMedia(constraints);}catch(e){// 降级到更低分辨率streamawaitnavigator.mediaDevices.getUserMedia({video:true});}7.3 系列总结恭喜你完成了 WebRTC 基础入门系列的学习让我们回顾一下这五篇文章的核心内容篇章主题核心收获第 1 篇概览篇理解 WebRTC 的定位、能力和应用场景第 2 篇架构篇掌握 WebRTC 的整体架构和组件关系第 3 篇实操篇动手实现一个完整的音视频通话 Demo第 4 篇理论篇深入理解 NAT 穿透、RTP 协议、音频处理第 5 篇API 篇全面掌握 WebRTC API 体系7.4 下一步学习建议深入信令设计学习如何设计可扩展的信令服务器SFU/MCU 架构了解大规模音视频会议的架构设计媒体服务器学习 Janus、mediasoup 等开源媒体服务器性能优化深入学习带宽估计、编码优化等高级主题移动端开发学习 iOS/Android 原生 WebRTC 开发参考资料W3C WebRTC 1.0 SpecificationMDN WebRTC APIWebRTC SamplesWebRTC for the CuriousHigh Performance Browser Networking - WebRTC
版权声明:本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!

艺术设计类网站网站开发的可行性报告

着电商行业进入精细化运营深水区,智能客服已从“可选工具”升级为“核心竞争力枢纽”。据艾瑞咨询数据显示,国内电商行业智能客服渗透率已超75%,人力成本年均涨幅超8%、平台响应时效考核收紧等因素,让越来越多商家将智能客服选型列…

张小明 2026/1/3 6:41:12 网站建设

在线免费货源网站入口做网站需要花费那方面的钱

企业运维视角下的 Elasticsearch 安全加固:从“设置密码”到构建可信访问体系当你的日志平台还在裸奔?是时候正视 Elasticsearch 的安全问题了在一次深夜的应急响应中,某互联网公司发现其 Elasticsearch 集群被加密勒索——所有数据索引被清空…

张小明 2026/1/6 4:50:28 网站建设

无锡建网站滨州北京网站建设

NextStep-1震撼发布:140亿参数AI绘图新突破 【免费下载链接】NextStep-1-Large 项目地址: https://ai.gitcode.com/StepFun/NextStep-1-Large 导语:StepFun AI推出140亿参数的NextStep-1-Large文本到图像生成模型,采用创新的自回归连…

张小明 2026/1/6 4:50:31 网站建设

写个网页多少钱嘉兴网站排名优化公司

Pandoc终极指南:如何用一行命令解决所有文档转换难题 【免费下载链接】pandoc Universal markup converter 项目地址: https://gitcode.com/gh_mirrors/pa/pandoc 还在为不同格式的文档转换而烦恼吗?学术论文需要从Markdown转成PDF,技…

张小明 2026/1/6 4:50:40 网站建设

菏泽郓城网站建设中国互联网百强企业名单

知识建模在逻辑架构上分为两个层次:数据层和模式层。 数据层是以事实为存储单位的图数据库,其事实的基础表达方式是「实体-关系-实体」或者「实体-属性-属性值」。 数据层进行知识提取和知识融合。知识提取是基于已有数据生成「实体-关系-实体」&#…

张小明 2026/1/4 23:26:40 网站建设

php多语言网站开发商城系统网站建设开发

如何用PlotJuggler实现高效时间序列可视化:从入门到精通的终极指南 【免费下载链接】PlotJuggler The Time Series Visualization Tool that you deserve. 项目地址: https://gitcode.com/gh_mirrors/pl/PlotJuggler 面对海量传感器数据却无从下手&#xff1…

张小明 2026/1/6 4:50:46 网站建设