倿§ãªã°ããŒãã«ãã©ãããã©ãŒã ã§ãã·ãŒã ã¬ã¹ã§é«å質ãªãªã¢ã«ã¿ã€ã ã¡ãã£ã¢éä¿¡ãå®çŸããããã«ãWebRTCã®ã³ãŒããã¯éžæã¢ã«ãŽãªãºã ããã¹ã¿ãŒããŸãããã
ããã³ããšã³ãWebRTCã¡ãã£ã¢ããŽã·ãšãŒã·ã§ã³ïŒã³ãŒããã¯éžæã¢ã«ãŽãªãºã ã®è§£èª
ãªã¢ã«ã¿ã€ã ã³ãã¥ãã±ãŒã·ã§ã³ïŒRTCïŒã®ãã€ãããã¯ãªäžçã«ãããŠãWebRTCã¯ãã©ãŠã¶å ã§çŽæ¥ãã¢ããŒãã¢ã®ãªãŒãã£ãªããããªãããŒã¿ãã£ãã«ãå¯èœã«ããéèŠãªãã¯ãããžãŒã§ãããããã®æ¥ç¶ã確ç«ããäžã§ãéèŠã§ãããªãããã°ãã°è€éãªåŽé¢ã¯ãã¡ãã£ã¢ããŽã·ãšãŒã·ã§ã³ããã»ã¹ãç¹ã«ã³ãŒããã¯éžæã®è€éãªãã³ã¹ã§ãããã®ããã»ã¹ã«ãããWebRTCé話ã®äž¡åœäºè ã亀æãããã¡ãã£ã¢ã¹ããªãŒã ãçè§£ããã¬ã³ããªã³ã°ã§ããããã«ãªããŸããããã³ããšã³ãéçºè ã«ãšã£ãŠããã®ã¢ã«ãŽãªãºã ãæ·±ãçè§£ããããšã¯ãå ç¢ã§é«å質ããããŠæ®éçã«äºææ§ã®ããRTCã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã«äžå¯æ¬ ã§ãã
åºç€ïŒã»ãã·ã§ã³èšè¿°ãããã³ã«ïŒSDPïŒ
WebRTCã¡ãã£ã¢ããŽã·ãšãŒã·ã§ã³ã®äžå¿ã«ã¯ãã»ãã·ã§ã³èšè¿°ãããã³ã«ïŒSDPïŒããããŸããSDPã¯ããã«ãã¡ãã£ã¢ã»ãã·ã§ã³ãèšè¿°ããããã«äœ¿çšãããããã¹ãããŒã¹ã®ãã©ãŒãããã§ããã¡ãã£ã¢èªäœã転éããããã§ã¯ãªããã»ãã·ã§ã³ã®æ©èœãšãã©ã¡ãŒã¿ãéä¿¡ããããã«äœ¿çšãããŸãã2ã€ã®ãã¢ãWebRTCæ¥ç¶ãéå§ãããšãSDPã®ãªãã¡ãŒãšã¢ã³ãµãŒã亀æããŸãããã®äº€æã«ããã以äžã詳现ã«äŒéãããŸãã
- éä¿¡ãããã¡ãã£ã¢ã®çš®é¡ïŒãªãŒãã£ãªããããªãããŒã¿ïŒã
- åã¡ãã£ã¢ã¿ã€ãã§ãµããŒããããã³ãŒããã¯ã
- ã¡ãã£ã¢ãéåä¿¡ããããã®ãããã¯ãŒã¯ã¢ãã¬ã¹ãšããŒãã
- æå·åã垯åå¹ ãªã©ããã®ä»ã®ã»ãã·ã§ã³åºæã®ãã©ã¡ãŒã¿ã
ã³ãŒããã¯éžæã¢ã«ãŽãªãºã ã¯ããã®SDP亀æå ã§æ©èœããŸããåãã¢ã¯ãµããŒãããã³ãŒããã¯ãã¢ããã¿ã€ãºããäžé£ã®ããŽã·ãšãŒã·ã§ã³ãéããŠãäž¡æ¹ãå©çšã§ããå ±éã®ã³ãŒããã¯ã»ããã«å°éããŸããããã§è€éããçããŸãããªããªããç°ãªããã©ãŠã¶ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ãããŒããŠã§ã¢ã¯ãããŸããŸãªå¹çãšå質ã¬ãã«ã§ç°ãªãã³ãŒããã¯ããµããŒãããå¯èœæ§ãããããã§ãã
WebRTCã«ãããã³ãŒããã¯ã®çè§£
éžæã¢ã«ãŽãªãºã ã«å ¥ãåã«ãã³ãŒããã¯ãäœã§ããããªãããããéèŠãªã®ããç°¡åã«å®çŸ©ããŸãããã
- ã³ãŒããã¯ïŒCoder-DecoderïŒïŒã³ãŒããã¯ã¯ãããŒã¿ãå§çž®ããã³è§£åããããã€ã¹ãŸãã¯ããã°ã©ã ã§ããWebRTCã§ã¯ãã³ãŒããã¯ã¯çã®ãªãŒãã£ãªããã³ãããªããŒã¿ãããããã¯ãŒã¯çµç±ã§ã®éä¿¡ã«é©ãã圢åŒïŒå§çž®ïŒã«ãšã³ã³ãŒãããåä¿¡åŽã§ãã®å§çž®ããŒã¿ãåçå¯èœãªåœ¢åŒã«è§£åïŒè§£åïŒãã責任ãè² ããŸãã
- ç®çïŒãã®äž»ãªç®çã¯ãã¡ãã£ã¢ã¹ããªãŒã ã®éä¿¡ã«å¿ èŠãªåž¯åå¹ ãåæžããéããã容éã®ãããã¯ãŒã¯ã§ããªã¢ã«ã¿ã€ã éä¿¡ãå¯èœã«ããããšã§ãããŸããç°ãªãããã€ã¹ããã©ãããã©ãŒã éã®äºææ§ã確ä¿ããäžã§ã圹å²ãæãããŸãã
WebRTCã¯éåžžãããŸããŸãªãªãŒãã£ãªããã³ãããªã³ãŒããã¯ããµããŒãããŠããŸããæãäžè¬çã«ééãããã®ã¯æ¬¡ã®ãšããã§ãã
ãªãŒãã£ãªã³ãŒããã¯ïŒ
- OpusïŒWebRTCãªãŒãã£ãªã®äºå®äžã®æšæºã§ããããã¯ãã¹ããŒããšé³æ¥œã®äž¡æ¹ã«å¯Ÿå¿ããããã«èšèšãããå€çšéã§ãªãŒãã³ãœãŒã¹ããã€ã€ãªãã£ããªãŒã®ã³ãŒããã¯ã§ãããããŸããŸãªãããã¯ãŒã¯æ¡ä»¶ãšãããã¬ãŒãã§åªããå質ãæäŸããŸãããã¹ãŠã®WebRTCã¢ããªã±ãŒã·ã§ã³ã§åŒ·ãæšå¥šãããŸãã
- G.711 (PCMU/PCMA)ïŒå€ãããããåºãäºææ§ã®ããã³ãŒããã¯ã§ãããOpusãããäžè¬çã«å¹çã¯äœãã§ããPCMUïŒÎŒ-lawïŒã¯åç±³ãšæ¥æ¬ã§äžè¬çã§ãããPCMAïŒA-lawïŒã¯ãšãŒãããããã³äžçã®ä»ã®å°åã§äœ¿çšãããŠããŸãã
- iSACïŒGoogleã«ãã£ãŠéçºãããå¥ã®ã¯ã€ããã³ããªãŒãã£ãªã³ãŒããã¯ã§ãããŸããŸãªãããã¯ãŒã¯æ¡ä»¶ã«é©å¿ã§ããããšã§ç¥ãããŠããŸãã
- ILBCïŒäœåž¯åå¹ åãã«èšèšãããå€ããããŒãã³ãã³ãŒããã¯ã§ãã
ãããªã³ãŒããã¯ïŒ
- VP8ïŒGoogleã«ãã£ãŠéçºããããªãŒãã³ãœãŒã¹ããã€ã€ãªãã£ããªãŒã®ãããªã³ãŒããã¯ã§ããåºããµããŒããããŠãããè¯å¥œãªããã©ãŒãã³ã¹ãæäŸããŸãã
- VP9ïŒVP8ã®åŸç¶ã§ãããåæ§ã®ãããã¬ãŒãã§å§çž®å¹çã®åäžãšããé«ãå質ãæäŸããŸãããããGoogleã®ãªãŒãã³ãœãŒã¹ã§ãã€ã€ãªãã£ããªãŒã®ã³ãŒããã¯ã§ãã
- H.264 (AVC)ïŒéåžžã«å¹ççã§åºãæ¡çšãããŠãããããã©ã€ãšã¿ãªãªãããªã³ãŒããã¯ã§ããéåžžã«äžè¬çã§ãããã©ã€ã»ã³ã¹ã¯äžéšã®ã¢ããªã±ãŒã·ã§ã³ã§èæ ®äºé ãšãªãå¯èœæ§ããããŸãããã ããã»ãšãã©ã®ãã©ãŠã¶ã¯WebRTCçšã«ããããµããŒãããŠããŸãã
- H.265 (HEVC)ïŒH.264ã®ããã«å¹ççãªåŸç¶ã§ãããã©ã€ã»ã³ã¹ã¯ããè€éã§ããWebRTCã§ã®HEVCã®ãµããŒãã¯ãH.264ãããäžè¬çã§ã¯ãããŸããã
ã³ãŒããã¯éžæã¢ã«ãŽãªãºã ã®åäœ
ã³ãŒããã¯éžæããã»ã¹ã¯ãäž»ã«SDPãªãã¡ãŒ/ã¢ã³ãµãŒã¢ãã«ã«ãã£ãŠé§åãããŸãã以äžã¯ããããäžè¬çã«ã©ã®ããã«æ©èœãããã®ç°¡åãªå èš³ã§ãã
ã¹ããã1ïŒãªãã¡ãŒ
WebRTCãã¢ïŒãã¢AãšåŒã³ãŸãããïŒãé話ãéå§ãããšãSDPãªãã¡ãŒãçæãããŸãããã®ãªãã¡ãŒã«ã¯ããµããŒããããŠãããã¹ãŠã®ãªãŒãã£ãªããã³ãããªã³ãŒããã¯ã®ãªã¹ããšãããã«é¢é£ä»ãããããã©ã¡ãŒã¿ããã³åªå é äœãå«ãŸããŸãããªãã¡ãŒã¯ãã·ã°ããªã³ã°ãµãŒããŒãä»ããŠããäžæ¹ã®ãã¢ïŒãã¢BïŒã«éä¿¡ãããŸãã
SDPãªãã¡ãŒã¯éåžžãæ¬¡ã®ãããªãã®ã«ãªããŸãïŒç°¡ç¥åãããã¹ããããïŒã
v=0 ... a=rtpmap:102 opus/48000/2 a=rtpmap:103 VP8/90000 a=rtpmap:104 H264/90000 ...
ãã®ã¹ããããã§ã¯ïŒ
a=rtpmap
è¡ã¯ã³ãŒããã¯ãèšè¿°ããŸãã- æ°åïŒäŸïŒ102ã103ïŒã¯ããã®ã»ãã·ã§ã³å ã®ã³ãŒããã¯ã®ããŒã«ã«èå¥åã§ãããã€ããŒãã¿ã€ãã§ãã
opus/48000/2
ã¯Opusã³ãŒããã¯ã瀺ãããµã³ãã«ã¬ãŒãã¯48000 Hzããã£ãã«ã¯2ïŒã¹ãã¬ãªïŒã§ããVP8/90000
ããã³H264/90000
ã¯äžè¬çãªãããªã³ãŒããã¯ã§ãã
ã¹ããã2ïŒã¢ã³ãµãŒ
ãã¢Bã¯SDPãªãã¡ãŒãåãåããŸããæ¬¡ã«ããã¢Aãã¢ããã¿ã€ãºããã³ãŒããã¯ã®ãªã¹ãã調ã¹ãèªèº«ã®ãµããŒãããã³ãŒããã¯ã®ãªã¹ããšæ¯èŒããŸããç®æšã¯ãäž¡æ¹ã®ãã¢ãåŠçã§ããæãé«ãå ±éã³ãŒããã¯ãèŠã€ããããšã§ãã
å ±éã³ãŒããã¯ãéžæããããã®ã¢ã«ãŽãªãºã ã¯éåžžãæ¬¡ã®ããã«ãªããŸãã
- ãã¢Aã®ã¢ããã¿ã€ãºãããã³ãŒããã¯ãå埩åŠçããŸããéåžžããªãã¡ãŒã«æç€ºãããé åºïŒãã°ãã°ãã¢Aã®åªå é äœãåæ ããŠããŸãïŒã§åŠçããŸãã
- ãã¢Aã®ãªã¹ãã«ããåã³ãŒããã¯ã«ã€ããŠããã¢Bãåãã³ãŒããã¯ããµããŒãããŠããã確èªããŸãã
- äžèŽãèŠã€ãã£ãå ŽåïŒãã®ã³ãŒããã¯ãããã®ã¡ãã£ã¢ã¿ã€ãïŒãªãŒãã£ãªãŸãã¯ãããªïŒã®éžæãããã³ãŒããã¯ã«ãªããŸãããã¢Bã¯ããã®éžæãããã³ãŒããã¯ãšãã©ã¡ãŒã¿ãå«ã¿ãããã«ãã€ããŒãã¿ã€ããå²ãåœãŠãSDPã¢ã³ãµãŒãçæããŸããã¢ã³ãµãŒã¯ã·ã°ããªã³ã°ãµãŒããŒãä»ããŠãã¢Aã«è¿ä¿¡ãããŸãã
- ãã¹ãŠã®ã³ãŒããã¯ã確èªããåŸãäžèŽãèŠã€ãããªãã£ãå ŽåïŒããã¯ããã®ã¡ãã£ã¢ã¿ã€ãã§ã®å ±éã³ãŒããã¯ã®ããŽã·ãšãŒã·ã§ã³ã®å€±æã瀺ããŸãããã®å Žåããã¢Bã¯ãã¢ã³ãµãŒãããã®ã¡ãã£ã¢ã¿ã€ããçç¥ããïŒäºå®äžãé話ã®ãªãŒãã£ãªãŸãã¯ãããªãç¡å¹ã«ããïŒãããã©ãŒã«ããã¯ãããŽã·ãšãŒãããããšããå¯èœæ§ããããŸãã
ãã¢Bã®SDPã¢ã³ãµãŒã«ã¯ãåæãããã³ãŒããã¯ãå«ãŸããŸãã
v=0 ... m=audio 9 UDP/TLS/RTP/SAVPF 102 ... a=rtpmap:102 opus/48000/2 ... m=video 9 UDP/TLS/RTP/SAVPF 103 ... a=rtpmap:103 VP8/90000 ...
ã¢ã³ãµãŒã¯ããã¢Bãåæãããã³ãŒããã¯ã«äœ¿çšãããã€ããŒãã¿ã€ãïŒäŸïŒOpusã®å Žåã¯102ãVP8ã®å Žåã¯103ïŒãæå®ããŠããããšã«æ³šæããŠãã ããã
ã¹ããã3ïŒæ¥ç¶ç¢ºç«
äž¡æ¹ã®ãã¢ãSDPãªãã¡ãŒãšã¢ã³ãµãŒã亀æããå ±éã®ã³ãŒããã¯ã«åæãããšãã¡ãã£ã¢äº€æãéå§ããããã®å¿ èŠãªãã©ã¡ãŒã¿ã確ç«ãããŸããWebRTCã¹ã¿ãã¯ã¯ããã®æ å ±ã䜿çšããŠã¡ãã£ã¢ãã©ã³ã¹ããŒãïŒUDPäžã®RTPïŒãæ§æãããã¢ããŒãã¢æ¥ç¶ã確ç«ããŸãã
ã³ãŒããã¯éžæã«åœ±é¿ãäžããèŠå
åºæ¬çãªã¢ã«ãŽãªãºã ã¯ïŒæåã®äžèŽããã³ãŒããã¯ãèŠã€ããïŒåçŽã§ãããå®éã®å®è£ ãšå®éã«éžæãããã³ãŒããã¯ã¯ãããã€ãã®èŠå ã«ãã£ãŠåœ±é¿ãããŸãã
1. ãã©ãŠã¶ã®å®è£ ãšããã©ã«ã
ããŸããŸãªãã©ãŠã¶ïŒChromeãFirefoxãSafariãEdgeïŒã¯ãWebRTCã®ç¬èªã®å éšå®è£ ãšç¬èªã®ããã©ã«ãã®ã³ãŒããã¯èšå®ãæã£ãŠããŸããããšãã°ïŒ
- Chrome/ChromiumããŒã¹ã®ãã©ãŠã¶ã¯ãäžè¬çã«VP8ãšOpusãåªå ããŸãã
- FirefoxãOpusãšVP8ã奜ã¿ãŸããããã©ãããã©ãŒã ã«ãã£ãŠã¯H.264ã®åªå é äœãç°ãªãå ŽåããããŸãã
- Safariã¯ãæŽå²çã«H.264ãšOpusã匷ããµããŒãããŠããŸããã
ããã¯ããã©ãŠã¶ãSDPãªãã¡ãŒã§ãµããŒããããŠããã³ãŒããã¯ã®ãªã¹ããæç€ºããé åºããããŽã·ãšãŒã·ã§ã³ã®çµæã«å€§ãã圱é¿ããå¯èœæ§ãããããšãæå³ããŸããéåžžããã©ãŠã¶ã¯ãæãå¹ççãŸãã¯æãäžè¬çã«ãµããŒããããŠãããåªå ãããã³ãŒããã¯ãæåã«ãªã¹ãããŸãã
2. ãªãã¬ãŒãã£ã³ã°ã·ã¹ãã ãšããŒããŠã§ã¢æ©èœ
åºç€ãšãªããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ãšããŒããŠã§ã¢ããã³ãŒããã¯ã®ãµããŒãã«åœ±é¿ãäžããå¯èœæ§ããããŸããããšãã°ïŒ
- äžéšã®ã·ã¹ãã ã§ã¯ãç¹å®ã®ã³ãŒããã¯ïŒäŸïŒH.264ïŒã®ããŒããŠã§ã¢ã¢ã¯ã»ã©ã¬ãŒã·ã§ã³ãšã³ã³ãŒã/ãã³ãŒããå¯èœã§ããã䜿çšãããå¹ççã«ãªããŸãã
- ã¢ãã€ã«ããã€ã¹ã¯ããã¹ã¯ãããã³ã³ãã¥ãŒã¿ãšã¯ç°ãªãã³ãŒããã¯ãµããŒããããã¡ã€ã«ãæã€å ŽåããããŸãã
3. ãããã¯ãŒã¯æ¡ä»¶
åæã®SDPããŽã·ãšãŒã·ã§ã³ã®çŽæ¥çãªäžéšã§ã¯ãããŸãããããããã¯ãŒã¯æ¡ä»¶ã¯éžæãããã³ãŒããã¯ã®ããã©ãŒãã³ã¹ã«éèŠãªåœ¹å²ãæãããŸããWebRTCã«ã¯ã垯åå¹ æšå®ïŒBEïŒãšé©å¿ã®ã¡ã«ããºã ãå«ãŸããŠããŸããã³ãŒããã¯ãéžæããããšïŒ
- ã¢ãããã£ããããã¬ãŒãïŒOpusãVP9ãªã©ã®ææ°ã®ã³ãŒããã¯ã¯ãå©çšå¯èœãªãããã¯ãŒã¯åž¯åå¹ ã«åºã¥ããŠãããã¬ãŒããšå質ãé©å¿ãããããã«èšèšãããŠããŸãã
- ãã±ãããã¹ç§å¿ïŒPLCïŒïŒãã±ããã倱ãããå Žåãã³ãŒããã¯ã¯æ¬ èœããããŒã¿ãæšæž¬ãŸãã¯åæ§ç¯ããæè¡ã䜿çšããŠãå質ã®äœäžãæå°éã«æããŸãã
- ã³ãŒããã¯åãæ¿ãïŒãŸãïŒïŒäžéšã®é«åºŠãªã·ããªãªã§ã¯ããããã¯ãŒã¯æ¡ä»¶ãåçã«å€åããå Žåãã¢ããªã±ãŒã·ã§ã³ã¯åçã«ã³ãŒããã¯ãåãæ¿ããããšããããšããããŸãããããã¯è€éãªäœæ¥ã§ãã
åæã®ããŽã·ãšãŒã·ã§ã³ã¯äºææ§ãç®æããç¶ç¶çãªéä¿¡ã¯éžæãããã³ãŒããã¯ã®é©å¿æ§ã掻çšããŸãã
4. ã¢ããªã±ãŒã·ã§ã³åºæã®èŠä»¶
éçºè ã¯ãSDPãªãã¡ãŒ/ã¢ã³ãµãŒãæäœããããšã«ãããJavaScript APIã䜿çšããŠã³ãŒããã¯ã®éžæã«åœ±é¿ãäžããããšãã§ããŸããããã¯é«åºŠãªãã¯ããã¯ã§ããã以äžãå¯èœã«ããŸãã
- ç¹å®ã®ã³ãŒããã¯ã®åŒ·å¶ïŒã¢ããªã±ãŒã·ã§ã³ãç¹å®ã®ã³ãŒããã¯ã«å¯ŸããŠå³æ ŒãªèŠä»¶ãæã£ãŠããå ŽåïŒäŸïŒã¬ã¬ã·ãŒã·ã¹ãã ãšã®çžäºéçšæ§ã®ããïŒããã®éžæã匷å¶ããããšããããšãã§ããŸãã
- ã³ãŒããã¯ã®åªå é äœä»ãïŒSDPãªãã¡ãŒãŸãã¯ã¢ã³ãµãŒã®ã³ãŒããã¯ã®é åºã倿Žããããšã«ãããã¢ããªã±ãŒã·ã§ã³ã¯åªå é äœã瀺ãããšãã§ããŸãã
- ã³ãŒããã¯ã®ç¡å¹åïŒã³ãŒããã¯ã«åé¡ãããããšãããã£ãŠããå ŽåããŸãã¯å¿ èŠãªãå Žåã¯ãæç€ºçã«é€å€ã§ããŸãã
ããã°ã©ã ã«ããå¶åŸ¡ãšSDPæäœ
ãã©ãŠã¶ã¯SDPããŽã·ãšãŒã·ã§ã³ã®å€ããèªåçã«åŠçããŸãããããã³ããšã³ãéçºè ã¯WebRTC JavaScript APIã䜿çšããŠããã现ããå¶åŸ¡ã§ããŸãã
1. `RTCPeerConnection.createOffer()` ãš `createAnswer()`
ãããã®ã¡ãœããã¯ãSDPãªãã¡ãŒããã³ã¢ã³ãµãŒãªããžã§ã¯ããçæããŸãããããã®èª¬æã`setLocalDescription()`ã䜿çšããŠ`RTCPeerConnection`ã«èšå®ããåã«ãSDPæååã倿Žã§ããŸãã
2. `RTCPeerConnection.setLocalDescription()` ãš `setRemoteDescription()`
ãããã¯ãããããããŒã«ã«ããã³ãªã¢ãŒãã®èª¬æãèšå®ããããã«äœ¿çšãããã¡ãœããã§ããããŽã·ãšãŒã·ã§ã³ã¯ã`setLocalDescription`ïŒãªãã¡ãŒåŽïŒãš`setRemoteDescription`ïŒã¢ã³ãµãŒåŽïŒã®äž¡æ¹ãæ£åžžã«åŒã³åºããããšãã«çºçããŸãã
3. `RTCSessionDescriptionInit`
`RTCSessionDescriptionInit`ã®`sdp`ããããã£ã¯ãSDPãå«ãæååã§ãããã®æååãè§£æãã倿ŽããŠãããåæ§æã§ããŸãã
äŸïŒVP9ãVP8ããåªå ãã
VP9ãVP8ããåªå ãããããã«ããããšããŸãããã©ãŠã¶ã®ããã©ã«ãã®SDPãªãã¡ãŒã¯ã次ã®ãããªé åºã§ãªã¹ããããŠããå¯èœæ§ããããŸãã
a=rtpmap:103 VP8/90000 a=rtpmap:104 VP9/90000
SDPãªãã¡ãŒãã€ã³ã¿ãŒã»ããããŠãVP9ãåªå ããããã«è¡ãå ¥ãæ¿ããããšãã§ããŸãã
let offer = await peerConnection.createOffer(); // SDPæååãå€æŽ let sdpLines = offer.sdp.split(' '); let vp8LineIndex = -1; let vp9LineIndex = -1; for (let i = 0; i < sdpLines.length; i++) { if (sdpLines[i].startsWith('a=rtpmap:') && sdpLines[i].includes('VP8/90000')) { vp8LineIndex = i; } if (sdpLines[i].startsWith('a=rtpmap:') && sdpLines[i].includes('VP9/90000')) { vp9LineIndex = i; } } if (vp8LineIndex !== -1 && vp9LineIndex !== -1) { // VP9ãVP8ããåŸã«ãªã¹ããããŠããå ŽåãVP8ãšVP9ã®è¡ãå ¥ãæ¿ãã if (vp9LineIndex > vp8LineIndex) { [sdpLines[vp8LineIndex], sdpLines[vp9LineIndex]] = [sdpLines[vp9LineIndex], sdpLines[vp8LineIndex]]; } } offer.sdp = sdpLines.join(' '); await peerConnection.setLocalDescription(offer); // ... ãªãã¡ãŒããªã¢ãŒããã¢ã«éä¿¡ ...
泚æïŒçŽæ¥ã®SDPæäœã¯å£ããããå¯èœæ§ããããŸãããã©ãŠã¶ã®ã¢ããããŒãã«ããSDP圢åŒã倿Žãããããäžæ£ç¢ºãªå€æŽã«ããããŽã·ãšãŒã·ã§ã³ã倱æãããããå¯èœæ§ããããŸãããã®ã¢ãããŒãã¯ãäžè¬çã«é«åºŠãªãŠãŒã¹ã±ãŒã¹ããŸãã¯ç¹å®ã®çžäºéçšæ§ãå¿ èŠãªå Žåã«äºçŽãããŠããŸãã
4. `RTCRtpTransceiver` APIïŒã¢ãã³ã¢ãããŒãïŒ
ã³ãŒããã¯éžæã«åœ±é¿ãäžãããããå
ç¢ã§æšå¥šãããæ¹æ³ã¯ã`RTCRtpTransceiver` APIã䜿çšããããšã§ããã¡ãã£ã¢ãã©ãã¯ã远å ãããšïŒäŸïŒ`peerConnection.addTrack(stream.getAudioTracks()[0], 'audio')`ïŒããã©ã³ã·ãŒããŒãäœæãããŸããæ¬¡ã«ããã©ã³ã·ãŒããŒãååŸãããã®direction
ãšåªå
ã³ãŒããã¯ãèšå®ã§ããŸãã
ãã©ã³ã·ãŒããŒã®ãµããŒããããŠããã³ãŒããã¯ãååŸã§ããŸãã
const transceivers = peerConnection.getTransceivers(); transceivers.forEach(transceiver => { if (transceiver.kind === 'audio') { const codecs = transceiver.rtpSender.getCapabilities().codecs; console.log('ãµããŒããããŠãããªãŒãã£ãªã³ãŒããã¯ïŒ', codecs); } });
ãã¹ãŠã®ãã©ãŠã¶ã§æ®éçã«ãã©ã³ã·ãŒããŒã«çŽæ¥`setPreferredCodec`ã¡ãœããã¯ãããŸããããWebRTC仿§ã¯ããã©ãŠã¶ãSDPã«æç€ºãããã³ãŒããã¯ã®é åºãå°éããããšã«ãããçžäºéçšæ§ãç®æããŠããŸããããçŽæ¥çãªå¶åŸ¡ã¯ã`createOffer`/`createAnswer`ã«ããSDPãªãã¡ãŒ/ã¢ã³ãµãŒçæã®æäœãããã³èª¬æãèšå®ããåã®ã³ãŒããã¯ã®ãã£ã«ã¿ãªã³ã°/äžŠã¹æ¿ãã«ãã£ãŠåŸãããããšããããããŸãã
5. `RTCPeerConnection` å¶çŽïŒ`getUserMedia`çšïŒ
`navigator.mediaDevices.getUserMedia()`ã䜿çšããŠã¡ãã£ã¢ã¹ããªãŒã ãååŸããéã«ãèŠæ±ãããã¡ãã£ã¢ã®å質ãŸãã¯ã¿ã€ãã«åœ±é¿ãäžããå¶çŽãæå®ã§ããŸãããã ãããããã®å¶çŽã¯äž»ã«ã¡ãã£ã¢ãã£ããã£èªäœã«åœ±é¿ãããã¢éã®ã³ãŒããã¯ã®ããŽã·ãšãŒã·ã§ã³ã«ã¯åœ±é¿ããŸããã
ã°ããŒãã«ã¢ããªã±ãŒã·ã§ã³ã®èª²é¡ãšãã¹ããã©ã¯ãã£ã¹
ã°ããŒãã«ãªWebRTCã¢ããªã±ãŒã·ã§ã³ã®æ§ç¯ã¯ãã¡ãã£ã¢ããŽã·ãšãŒã·ã§ã³ã«é¢é£ããç¹æã®èª²é¡ããããããŸãã
1. ã°ããŒãã«ãªãã©ãŠã¶ãšããã€ã¹ã®æçå
äžçã¯ãããŸããŸãªããã€ã¹ããªãã¬ãŒãã£ã³ã°ã·ã¹ãã ããã©ãŠã¶ããŒãžã§ã³ã䜿çšããŠããŸããWebRTCã¢ããªã±ãŒã·ã§ã³ããã®æçåå šäœã§ã·ãŒã ã¬ã¹ã«åäœããããšãä¿èšŒããããšã¯ã倧ããªããŒãã«ã§ãã
- äŸïŒå€ãAndroidããã€ã¹ã䜿çšããŠããåç±³ã®ãŠãŒã¶ãŒã¯ãæ±ã¢ãžã¢ã®æè¿ã®iOSããã€ã¹ã䜿çšããŠãããŠãŒã¶ãŒãšã¯ç°ãªãH.264ãããã¡ã€ã«ãŸãã¯ã³ãŒããã¯ãµããŒããæã£ãŠããå¯èœæ§ããããŸãã
2. ãããã¯ãŒã¯ã®å€åæ§
ã€ã³ã¿ãŒãããã€ã³ãã©ã¹ãã©ã¯ãã£ã¯ãäžçäžã§å€§ããç°ãªããŸããã¬ã€ãã³ã·ããã±ãããã¹ãå©çšå¯èœãªåž¯åå¹ ã¯åçã«ç°ãªãå ŽåããããŸãã
- äŸïŒè¥¿ãšãŒãããã®é«éãã¡ã€ããŒãªããã£ãã¯ãããã¯ãŒã¯ã䜿çšããŠãã2人ã®ãŠãŒã¶ãŒéã®é話ã¯ãæ±åã¢ãžã¢ã®èŸ²æéšã§ã¢ãã€ã«ãããã¯ãŒã¯ã䜿çšããŠãããŠãŒã¶ãŒéã®é話ãšã¯å€§ããç°ãªãäœéšã«ãªããŸãã
3. ã¬ã¬ã·ãŒã·ã¹ãã ãšã®çžäºéçšæ§
å€ãã®çµç¹ã¯ãææ°ã®WebRTCã³ãŒããã¯ãŸãã¯ãããã³ã«ãå®å šã«ãµããŒãããŠããªãå¯èœæ§ã®ããæ¢åã®ãããªäŒè°ããŒããŠã§ã¢ãŸãã¯ãœãããŠã§ã¢ã«äŸåããŠããŸãããã®ã®ã£ãããåããã«ã¯ãG.711ãH.264ãªã©ã®ãããäžè¬çã§ã¯ãããå¹çã®äœãã³ãŒããã¯ã®ãµããŒããå®è£ ããå¿ èŠããããŸãã
ãã¹ããã©ã¯ãã£ã¹ïŒ
- ãªãŒãã£ãªã«ã¯Opusãåªå ããïŒOpusã¯ãWebRTCã§æãå€çšéã§åºããµããŒããããŠãããªãŒãã£ãªã³ãŒããã¯ã§ããããŸããŸãªãããã¯ãŒã¯æ¡ä»¶ã§éåžžã«åªããããã©ãŒãã³ã¹ãçºæ®ãããã¹ãŠã®ã¢ããªã±ãŒã·ã§ã³ã«åŒ·ãæšå¥šãããŸããSDPãªãã¡ãŒã§ç®ç«ã€ããã«ãªã¹ããããŠããããšã確èªããŠãã ããã
- ãããªã«ã¯VP8/VP9ãåªå ããïŒVP8ãšVP9ã¯ãªãŒãã³ãœãŒã¹ã§åºããµããŒããããŠããŸããH.264ãäžè¬çã§ãããVP8/VP9ã¯ã©ã€ã»ã³ã¹ã®åé¡ãªãã«è¯å¥œãªäºææ§ãæäŸããŸããã¿ãŒã²ãããã©ãããã©ãŒã å šäœã§ãµããŒããäžè²«ããŠããå Žåã¯ãããåªããå§çž®å¹çã®ããã«VP9ãæ€èšããŠãã ããã
- å ç¢ãªã·ã°ããªã³ã°ãµãŒããŒã䜿çšããïŒä¿¡é Œæ§ã®é«ãã·ã°ããªã³ã°ãµãŒããŒã¯ãããŸããŸãªå°åã§SDPãªãã¡ãŒãšã¢ã³ãµãŒãå¹ççãã€å®å šã«äº€æããããã«äžå¯æ¬ ã§ãã
- ããŸããŸãªãããã¯ãŒã¯ãšããã€ã¹ã§åŸ¹åºçã«ãã¹ãããïŒå®éã®ãããã¯ãŒã¯æ¡ä»¶ãã·ãã¥ã¬ãŒãããã°ããŒãã«ãŠãŒã¶ãŒããŒã¹ã代衚ããå¹ åºãããã€ã¹ãšãã©ãŠã¶ã§ã¢ããªã±ãŒã·ã§ã³ããã¹ãããŠãã ããã
- WebRTCçµ±èšæ å ±ãç£èŠããïŒ`RTCPeerConnection.getStats()` APIãå©çšããŠãã³ãŒããã¯ã®äœ¿çšç¶æ³ããã±ãããã¹ããžãã¿ãŒããã®ä»ã®ã¡ããªãã¯ãç£èŠããŸãããã®ããŒã¿ã¯ãããŸããŸãªå°åã§ããã©ãŒãã³ã¹ã®ããã«ããã¯ãã³ãŒããã¯é¢é£ã®åé¡ãç¹å®ããã®ã«éåžžã«åœ¹ç«ã¡ãŸãã
- ãã©ãŒã«ããã¯æŠç¥ãå®è£ ããïŒæé«ãç®æãäžæ¹ã§ãç¹å®ã®ã³ãŒããã¯ã®ããŽã·ãšãŒã·ã§ã³ã倱æããå¯èœæ§ã®ããã·ããªãªã«åããŠãã ãããåªé ãªãã©ãŒã«ããã¯ã¡ã«ããºã ãæºåããŠãã ããã
- è€éãªã·ããªãªã«ã¯ãµãŒããŒãµã€ãåŠçïŒSFU/MCUïŒãæ€èšããïŒåå è ãå€ãã¢ããªã±ãŒã·ã§ã³ããé²ç»ããã©ã³ã¹ã¯ãªããã£ã³ã°ãªã©ã®é«åºŠãªæ©èœãå¿ èŠãªå Žåã¯ãéžæç転éãŠãããïŒSFUïŒãŸãã¯ãã«ããã€ã³ãå¶åŸ¡ãŠãããïŒMCUïŒã䜿çšãããšãåŠçããªãããŒãããã¯ã©ã€ã¢ã³ããµã€ãã®ããŽã·ãšãŒã·ã§ã³ãç°¡çŽ åã§ããŸãããã ããããã«ã¯ãµãŒããŒã€ã³ãã©ã¹ãã©ã¯ãã£ã®ã³ã¹ãã远å ãããŸãã
- ãã©ãŠã¶æšæºã®ææ°æ å ±ãå ¥æããïŒWebRTCã¯åžžã«é²åããŠããŸããæ°ããã³ãŒããã¯ãµããŒããæšæºå€æŽããã©ãŠã¶åºæã®åäœã«ã€ããŠåžžã«ææ¡ããŠãã ããã
çµè«
WebRTCã¡ãã£ã¢ããŽã·ãšãŒã·ã§ã³ããã³ã³ãŒããã¯éžæã¢ã«ãŽãªãºã ã¯ãäžèŠè€éã§ãããåºæ¬çã«2ã€ã®ãã¢éã®å ±éç¹ãèŠã€ããããšã§ããSDPãªãã¡ãŒ/ã¢ã³ãµãŒã¢ãã«ã掻çšããããšã«ãããWebRTCã¯å ±æã®ãªãŒãã£ãªããã³ãããªã³ãŒããã¯ãç¹å®ããããšã«ãã£ãŠãäºææ§ã®ããéä¿¡ãã£ãã«ã確ç«ããããšããŸããã°ããŒãã«ã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ããããã³ããšã³ãéçºè ã«ãšã£ãŠããã®ããã»ã¹ãçè§£ããããšã¯ãåã«ã³ãŒããæžãã ãã§ãªããæ®éæ§ã®ããã«èšèšããããšã§ãã
Opusããã³VP8/VP9ãªã©ã®å ç¢ã§åºããµããŒããããŠããã³ãŒããã¯ãåªå ããããŸããŸãªã°ããŒãã«ç°å¢ã§ã®å³å¯ãªãã¹ããšçµã¿åãããããšã§ãã·ãŒã ã¬ã¹ã§é«å質ãªãªã¢ã«ã¿ã€ã éä¿¡ã®åºç€ãç¯ãããŸããã³ãŒããã¯ããŽã·ãšãŒã·ã§ã³ã®ãã¥ã¢ã³ã¹ããã¹ã¿ãŒããããšã§ãWebRTCã®å¯èœæ§ãæå€§éã«åŒãåºããäžçäžã®èŠèŽè ã«åªãããŠãŒã¶ãŒãšã¯ã¹ããªãšã³ã¹ãæäŸã§ããŸãã