{ "version": "https://jsonfeed.org/version/1", "title": "WebRTC", "description": "WebRTC is a free, open project that enables web browsers with Real-Time Communications (RTC) capabilities via simple Javascript APIs.", "home_page_url": "go/webrtc", "feed_url": "feed/webrtc.json", "icon": "https://cdn.v2ex.com/navatar/b4a5/2895/701_large.png?m=1368991576", "favicon": "https://cdn.v2ex.com/navatar/b4a5/2895/701_normal.png?m=1368991576", "items": [ { "author": { "url": "member/tangknox1", "name": "tangknox1", "avatar": "https://cdn.v2ex.com/gravatar/a1a7952e770bca1b3c559bfdba68ac5b?s=73&d=retro" }, "url": "t/1135756", "title": "\u6709\u7528 LiveKit \u5f00\u53d1\u8fc7\u89c6\u9891\u8bed\u97f3\u4f1a\u8bae\u7cfb\u7edf\u7684\u561b\uff1f", "id": "t/1135756", "date_published": "2025-06-01T14:12:14+00:00", "content_html": "\u6709\u7528 LiveKit \u5f00\u53d1\u8fc7\u89c6\u9891\u8bed\u97f3\u4f1a\u8bae\u7cfb\u7edf\u7684\u561b\uff1f
https://docs.livekit.io/home/
\u9047\u5230\u70b9\u6280\u672f\u95ee\u9898\uff0c\u60f3\u4ed8\u8d39\u627e\u4eba\u89e3\u51b3\u6216\u8005\u4e8c\u5f00\u4e0b\u3002
\u6709\u7528\u8fc7 livekit \u7684 \u56de\u590d\u4e0b\uff0c\u53ef\u76f4\u63a5\u8054\u7cfb\u6211\uff1abmlrZXNyQHllYWgubmV0" }, { "author": { "url": "member/Feabauer", "name": "Feabauer", "avatar": "https://cdn.v2ex.com/gravatar/bc99c0abbb562598a1895e795180b31d?s=73&d=retro" }, "url": "t/1130800", "title": "\u5728 window \u5982\u4f55\u5904\u7406\u97f3\u9891 aec?", "id": "t/1130800", "date_published": "2025-05-09T19:57:08+00:00", "content_html": "

\u5c0f\u5f1f\u6700\u8fd1\u5728\u505a\u7684\u5c0f\u667a ai \u5ba2\u6237\u7aef\uff0c\u9047\u5230\u4e86\u95ee\u9898\u5b9e\u65f6\u5bf9\u8bdd\uff0cpython \u5f00\u53d1\u7684\uff0c\u4f46\u662f webrtc_audio_processing \u65e0\u6cd5\u5728 window \u4f7f\u7528\uff0c\u6709\u6ca1\u6709\u4ec0\u4e48\u529e\u6cd5\u80fd\u5728 python \u548c window\\mac\\linux \u5b9e\u73b0 aec \u56de\u58f0\u6d88\u9664\uff0c\u73b0\u5728\u5b9e\u65f6\u5bf9\u8bdd\u4e00\u76f4\u88ab\u626c\u58f0\u5668\u7684\u58f0\u97f3\u5e72\u6270\u81ea\u95ee\u81ea\u7b54

\n" }, { "author": { "url": "member/as9567585", "name": "as9567585", "avatar": "https://cdn.v2ex.com/avatar/fd96/27b5/160446_large.png?m=1718352966" }, "url": "t/990070", "title": "\u6709\u5728\u751f\u4ea7\u73af\u5883\u7528\u8fc7\u7684 livekit \u7684\u5417\uff1f\u4f53\u9a8c\u600e\u4e48\u6837\uff1f", "id": "t/990070", "date_published": "2023-11-08T19:50:58+00:00", "content_html": "https://github.com/livekit/livekit" }, { "author": { "url": "member/qxqsxbd", "name": "qxqsxbd", "avatar": "https://cdn.v2ex.com/gravatar/4396fc43b496e1ecc257eae7ec06a149?s=73&d=retro" }, "url": "t/987383", "date_modified": "2023-11-01T02:56:07+00:00", "content_html": "

\u6211\u7684\u97f3\u89c6\u9891\u6570\u636e\u6765\u81ea\u7b2c\u4e09\u65b9\u7684 sdk \uff0c\u76ee\u524d\u89c6\u9891\u53ef\u4ee5\uff0c\u4f46\u662f\u6ca1\u627e\u5230\u5982\u4f55\u5728 webrtc \u4e2d\u4f7f\u7528\u81ea\u5b9a\u4e49\u97f3\u9891\u7684\u65b9\u6cd5\uff0c\u97f3\u9891\u6570\u636e\u662f pcm \uff0c\u5404\u4f4d\u5927\u4f6c\u6709\u4ec0\u4e48\u5efa\u8bae\u5417\uff1f

\n", "date_published": "2023-11-01T02:51:33+00:00", "title": "\u5b89\u5353 WebRTC \u5982\u4f55\u4f7f\u7528\u81ea\u5b9a\u4e49\u7684\u97f3\u9891\u6570\u636e\uff1f", "id": "t/987383" }, { "author": { "url": "member/hanguofu", "name": "hanguofu", "avatar": "https://cdn.v2ex.com/gravatar/108099cd4cea8dd2f44cffc10e0ae2b9?s=73&d=retro" }, "url": "t/889858", "title": "\u8bf7\u63a8\u8350\u4e00\u4e2a\u652f\u6301\u5728\u7ebf\u4f1a\u8bae\uff08\u4ec5\u9650\u4e8e\u97f3\u9891\uff09\u7684 SFU", "id": "t/889858", "date_published": "2022-10-25T16:18:03+00:00", "content_html": "

\u8981\u6c42\u652f\u6301 30 \u4eba\u540c\u65f6\u5728\u7ebf\uff0c\u591a\u5bf9\u591a\uff0c\u670d\u52a1\u5668\u7684\u5f00\u9500\u5c0f\uff0c\u5ba2\u6237\u7aef\u5b89\u5353\u6216\u8005 LINUX PC \u3002\u6c42\u63a8\u8350\u4e00\u4e2a\u73b0\u6210\u7684\u6536\u8d39\u6216\u8005\u514d\u8d39\u7684\u89e3\u51b3\u65b9\u6848\uff0c\u8c22\u8c22\uff01

\n" }, { "author": { "url": "member/cookiezmq", "name": "cookiezmq", "avatar": "https://cdn.v2ex.com/avatar/f768/e986/348395_large.png?m=1665998100" }, "url": "t/880041", "title": "\u57fa\u4e8e\u58f0\u7f51 SDK \u5b9e\u73b0 iOS \u7aef\u7684\u4e00\u5bf9\u4e00\u89c6\u9891\u901a\u8bdd", "id": "t/880041", "date_published": "2022-09-14T09:26:08+00:00", "content_html": "

\u5728\u5f88\u591a\u4ea7\u54c1\uff0c\u52a0\u5165\u5b9e\u65f6\u89c6\u9891\u901a\u8bdd\u5df2\u7ecf\u4e0d\u662f\u65b0\u9c9c\u4e8b\u60c5\u4e86\uff0c\u5c24\u5176\u662f\u8fd1\u51e0\u5e74\u7684\u75ab\u60c5\u5f71\u54cd\uff0c\u4e2a\u4eba\u516c\u53f8\u56fd\u5bb6\u5bf9\u4e8e\u5b9e\u65f6\u97f3\u89c6\u9891\u7684\u9700\u6c42\u4e00\u76f4\u5728\u5feb\u901f\u7684\u589e\u957f\u3002\u4f8b\u5982\u89c6\u9891\u4f1a\u8bae\u3001\u793e\u4ea4\u5e94\u7528\u3001\u5b9e\u65f6\u6e38\u620f\uff0c\u751a\u81f3\u4e5f\u53ef\u80fd\u51fa\u73b0\u5728\u4e00\u4e9b\u5143\u5b87\u5b99\u7684\u573a\u666f\u4e2d\u3002

\n

\u672c\u6587\u5c06\u6559\u4f60\u5982\u4f55\u901a\u8fc7\u58f0\u7f51\u89c6\u9891 SDK \u5728 iOS \u5e73\u53f0\u4e0a\u5b9e\u73b0\u4e00\u4e2a\u89c6\u9891\u901a\u8bdd\u5e94\u7528\u3002\u4e3a\u6b64\u4f60\u9700\u8981\u5148\u6ce8\u518c\u4e00\u4e2a\u58f0\u7f51\u5f00\u53d1\u8005\u8d26\u53f7\uff0c\u5f00\u53d1\u8005\u6bcf\u4e2a\u6708\u53ef\u83b7\u5f97 10000 \u5206\u949f\u7684\u514d\u8d39\u4f7f\u7528\u989d\u5ea6\uff0c\u53ef\u5b9e\u73b0\u5404\u7c7b\u5b9e\u65f6\u97f3\u89c6\u9891\u573a\u666f\u3002

\n

\u4e00\u3001\t\u901a\u8fc7\u5f00\u6e90 Demo \uff0c\u4f53\u9a8c\u89c6\u9891\u901a\u8bdd

\n

\u53ef\u80fd\u6709\u4e9b\u4eba\uff0c\u8fd8\u4e0d\u4e86\u89e3\u6211\u4eec\u8981\u5b9e\u73b0\u7684\u529f\u80fd\u6700\u540e\u662f\u600e\u6837\u7684\u3002\u6240\u4ee5\u6211\u4eec\u5728 GitHub \u4e0a\u63d0\u4f9b\u4e00\u4e2a\u5f00\u6e90\u7684\u57fa\u7840\u89c6\u9891\u901a\u8bdd\u793a\u4f8b\u9879\u76ee\uff0c\u5728\u5f00\u59cb\u5f00\u53d1\u4e4b\u524d\u4f60\u53ef\u4ee5\u901a\u8fc7\u8be5\u793a\u4f8b\u9879\u76ee\u4f53\u9a8c\u89c6\u9891\u901a\u8bdd\u7684\u4f53\u9a8c\u6548\u679c\u3002

\n

Agora \u5728 https://github.com/AgoraIO/Basic-Video-Call/tree/master/One-to-One-Video \u4e0a\u63d0\u4f9b\u5f00\u6e90\u7684\u5b9e\u65f6\u97f3\u89c6\u9891\u901a\u8bdd\u793a\u4f8b\u9879\u76ee Agora-iOS-Tutorial-Objective-C-1to1 \u4e0e Agora-iOS-Tutorial-Swift-1to1 \u3002\n\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"

\n

\u4e8c\u3001\t\u89c6\u9891\u901a\u8bdd\u7684\u6280\u672f\u539f\u7406

\n

\u6211\u4eec\u5728\u8fd9\u91cc\u8981\u5b9e\u73b0\u7684\u662f\u4e00\u5bf9\u4e00\u7684\u89c6\u9891\u901a\u8bdd\u3002\u4f60\u53ef\u4ee5\u7406\u89e3\u4e3a\u662f\u4e24\u4e2a\u7528\u6237\u901a\u8fc7\u52a0\u5165\u540c\u4e00\u4e2a\u9891\u9053\uff0c\u5b9e\u73b0\u7684\u97f3\u89c6\u9891\u7684\u4e92\u901a\u3002\u800c\u8fd9\u4e2a\u9891\u9053\u7684\u6570\u636e\uff0c\u4f1a\u901a\u8fc7\u58f0\u7f51\u7684 Agora SD-RTN \u5b9e\u65f6\u7f51\u7edc\u6765\u8fdb\u884c\u4f4e\u5ef6\u65f6\u4f20\u8f93\u7684\u3002\n\u4e0b\u56fe\u5c55\u793a\u5728 App \u4e2d\u96c6\u6210 Agora \u89c6\u9891\u901a\u8bdd\u7684\u57fa\u672c\u5de5\u4f5c\u6d41\u7a0b\uff1a\n\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"

\n

\u5982\u56fe\u6240\u793a\uff0c\u5b9e\u73b0\u89c6\u9891\u901a\u8bdd\u7684\u6b65\u9aa4\u5982\u4e0b\uff1a

\n
    \n
  1. \u83b7\u53d6 Token\uff1a\u5f53 app \u5ba2\u6237\u7aef\u52a0\u5165\u9891\u9053\u65f6\uff0c\u4f60\u9700\u8981\u4f7f\u7528 Token \u9a8c\u8bc1\u7528\u6237\u8eab\u4efd\u3002\u5728\u6d4b\u8bd5\u6216\u751f\u4ea7\u73af\u5883\u4e2d\uff0c\u4ece app \u670d\u52a1\u5668\u4e2d\u83b7\u53d6 Token \u3002
  2. \n
  3. \u52a0\u5165\u9891\u9053\uff1a\u8c03\u7528 joinChannel \u521b\u5efa\u5e76\u52a0\u5165\u9891\u9053\u3002\u4f7f\u7528\u540c\u4e00\u9891\u9053\u540d\u79f0\u7684 app \u5ba2\u6237\u7aef\u9ed8\u8ba4\u52a0\u5165\u540c\u4e00\u9891\u9053\u3002\u9891\u9053\u53ef\u7406\u89e3\u4e3a\u4e13\u7528\u4e8e\u4f20\u8f93\u5b9e\u65f6\u97f3\u89c6\u9891\u6570\u636e\u7684\u901a\u9053\u3002
  4. \n
  5. \u5728\u9891\u9053\u5185\u53d1\u5e03\u548c\u8ba2\u9605\u97f3\u89c6\u9891\u6d41\uff1a\u52a0\u5165\u9891\u9053\u540e\uff0capp \u5ba2\u6237\u7aef\u5747\u53ef\u4ee5\u5728\u9891\u9053\u5185\u53d1\u5e03\u548c\u8ba2\u9605\u97f3\u89c6\u9891\u3002
  6. \n
\n

App \u5ba2\u6237\u7aef\u52a0\u5165\u9891\u9053\u9700\u8981\u4ee5\u4e0b\u4fe1\u606f\uff1a

\n
    \n
  1. App ID\uff1aAgora \u968f\u673a\u751f\u6210\u7684\u5b57\u7b26\u4e32\uff0c\u7528\u4e8e\u8bc6\u522b\u4f60\u7684 App \uff0c\u53ef\u4ece Agora \u63a7\u5236\u53f0\u83b7\u53d6\uff0c\uff08 Agora \u63a7\u5236\u53f0\u94fe\u63a5\uff1a https://console.agora.io/\uff09\u3002\u8be6\u7ec6\u65b9\u6cd5\u53ef\u89c1\u8fd9\u7bc7\u6559\u7a0b\uff08\u8fd9\u7bc7\u6559\u7a0b\u94fe\u63a5\uff1a https://www.agora.io/cn/community/blog-119-category-21344 \uff09\u3002
  2. \n
  3. \u7528\u6237 ID\uff1a\u7528\u6237\u7684\u552f\u4e00\u6807\u8bc6\u3002\u4f60\u9700\u8981\u81ea\u884c\u8bbe\u7f6e\u7528\u6237 ID \uff0c\u5e76\u786e\u4fdd\u5b83\u5728\u9891\u9053\u5185\u662f\u552f\u4e00\u7684\u3002
  4. \n
  5. Token\uff1a\u5728\u6d4b\u8bd5\u6216\u751f\u4ea7\u73af\u5883\u4e2d\uff0capp \u5ba2\u6237\u7aef\u4ece\u4f60\u7684\u670d\u52a1\u5668\u4e2d\u83b7\u53d6 Token \u3002\u5728\u672c\u6587\u4ecb\u7ecd\u7684\u6d41\u7a0b\u4e2d\uff0c\u4f60\u53ef\u4ee5\u4ece Agora \u63a7\u5236\u53f0\u83b7\u53d6\u4e34\u65f6 Token \u3002\u4e34\u65f6 Token \u7684\u6709\u6548\u671f\u4e3a 24 \u5c0f\u65f6\u3002
  6. \n
  7. \u9891\u9053\u540d\u79f0\uff1a\u7528\u4e8e\u6807\u8bc6\u89c6\u9891\u901a\u8bdd\u9891\u9053\u7684\u5b57\u7b26\u4e32\u3002
  8. \n
\n

\u4e09\u3001\t\u5f00\u53d1\u73af\u5883

\n

\u58f0\u7f51 Agora SDK \u7684\u517c\u5bb9\u6027\u826f\u597d\uff0c\u5bf9\u786c\u4ef6\u8bbe\u5907\u548c\u8f6f\u4ef6\u7cfb\u7edf\u7684\u8981\u6c42\u4e0d\u9ad8\uff0c\u5f00\u53d1\u73af\u5883\u548c\u6d4b\u8bd5\u73af\u5883\u6ee1\u8db3\u4ee5\u4e0b\u6761\u4ef6\u5373\u53ef\uff1a

\n\n

\u4ee5\u4e0b\u662f\u672c\u6587\u7684\u5f00\u53d1\u73af\u5883\u548c\u6d4b\u8bd5\u73af\u5883\uff1a

\n

\u5f00\u53d1\u73af\u5883

\n

\u2022\tmacOS 11.6 \u7248\u672c\n\u2022\tXcode Version 13.1

\n

\u6d4b\u8bd5\u73af\u5883

\n

\u2022\tiPhone7 (iOS 15.3)

\n

\u5982\u679c\u4f60\u6b64\u524d\u8fd8\u672a\u63a5\u89e6\u8fc7\u58f0\u7f51 Agora SDK \uff0c\u90a3\u4e48\u4f60\u8fd8\u9700\u8981\u505a\u4ee5\u4e0b\u51c6\u5907\u5de5\u4f5c\uff1a

\n

\u2022\t\u6ce8\u518c\u4e00\u4e2a\u58f0\u7f51\u8d26\u53f7\uff0c\u8fdb\u5165\u540e\u53f0\u521b\u5efa AppID \u3001\u83b7\u53d6 Token \uff0c\n\u2022\t\u4e0b\u8f7d\u58f0\u7f51\u5b98\u65b9\u6700\u65b0\u7684\u89c6\u9891\u901a\u8bdd SDK \uff1b\uff08\u89c6\u9891\u901a\u8bdd SDK \u94fe\u63a5\uff1a https://docs.agora.io/cn/Video/downloads?platform=iOS \uff09

\n

\u56db\u3001\t\u9879\u76ee\u8bbe\u7f6e

\n

1.\t\u5b9e\u73b0\u89c6\u9891\u901a\u8bdd\u4e4b\u524d\uff0c\u53c2\u8003\u5982\u4e0b\u6b65\u9aa4\u8bbe\u7f6e\u4f60\u7684\u9879\u76ee\uff1a

\n

a)\t\u5982\u9700\u521b\u5efa\u65b0\u9879\u76ee, Xcode \u91cc\uff0c\u6253\u5f00 Xcode \u5e76\u70b9\u51fb Create a new Xcode project \u3002\uff08\u521b\u5efa iOS \u9879\u76ee\u94fe\u63a5\uff1a https://developer.apple.com/documentation/xcode/creating-an-xcode-project-for-an-app \uff09\nb)\t\u9009\u62e9\u5e73\u53f0\u7c7b\u578b\u4e3a iOS \u3001\u9879\u76ee\u7c7b\u578b\u4e3a Single View App \uff0c\u5e76\u70b9\u51fb Next \u3002\nc)\t\u8f93\u5165\u9879\u76ee\u540d\u79f0\uff08 Product Name \uff09\u3001\u5f00\u53d1\u56e2\u961f\u4fe1\u606f\uff08 Team \uff09\u3001\u7ec4\u7ec7\u540d\u79f0\uff08 Organization Name \uff09\u548c\u8bed\u8a00\uff08 Language \uff09\u7b49\u9879\u76ee\u4fe1\u606f\uff0c\u5e76\u70b9\u51fb Next \u3002\n\u6ce8\u610f\uff1a\u5982\u679c\u4f60\u6ca1\u6709\u6dfb\u52a0\u8fc7\u5f00\u53d1\u56e2\u961f\u4fe1\u606f\uff0c\u4f1a\u770b\u5230 Add account\u2026 \u6309\u94ae\u3002\u70b9\u51fb\u8be5\u6309\u94ae\u5e76\u6309\u7167\u5c4f\u5e55\u63d0\u793a\u767b\u5165 Apple ID \uff0c\u5b8c\u6210\u540e\u5373\u53ef\u9009\u62e9\u4f60\u7684 Apple \u8d26\u6237\u4f5c\u4e3a\u5f00\u53d1\u56e2\u961f\u3002\nd)\t\u9009\u62e9\u9879\u76ee\u5b58\u50a8\u8def\u5f84\uff0c\u5e76\u70b9\u51fb Create \u3002

\n

2.\t\u96c6\u6210 SDK

\n

\u9009\u62e9\u5982\u4e0b\u4efb\u610f\u4e00\u79cd\u65b9\u5f0f\u83b7\u53d6\u6700\u65b0\u7248 Agora iOS SDK \u3002

\n

\u65b9\u6cd5\u4e00\uff1a\u4f7f\u7528 CocoaPods \u83b7\u53d6 SDK\na)\t\u5f00\u59cb\u524d\u786e\u4fdd\u4f60\u5df2\u5b89\u88c5 Cocoapods \u3002\u53c2\u8003 Getting Started with CocoaPods \u5b89\u88c5\u8bf4\u660e\u3002\uff08 Getting Started with CocoaPods \u5b89\u88c5\u8bf4\u660e\u94fe\u63a5\uff1a https://guides.cocoapods.org/using/getting-started.html#getting-started \uff09\nb)\t\u5728\u7ec8\u7aef\u91cc\u8fdb\u5165\u9879\u76ee\u6839\u76ee\u5f55\uff0c\u5e76\u8fd0\u884c pod init \u547d\u4ee4\u3002\u9879\u76ee\u6587\u4ef6\u5939\u4e0b\u4f1a\u751f\u6210\u4e00\u4e2a Podfile \u6587\u672c\u6587\u4ef6\u3002\nc)\t\u6253\u5f00 Podfile \u6587\u4ef6\uff0c\u4fee\u6539\u6587\u4ef6\u4e3a\u5982\u4e0b\u5185\u5bb9\u3002\u6ce8\u610f\u5c06 Your App \u66ff\u6362\u4e3a\u4f60\u7684 Target \u540d\u79f0\u3002

\n

\u65b9\u6cd5\u4e8c\uff1a\u4ece\u5b98\u7f51\u83b7\u53d6 SDK\na)\t\u524d\u5f80 SDK \u4e0b\u8f7d\u9875\u9762\uff0c\u83b7\u53d6\u6700\u65b0\u7248\u7684 Agora iOS SDK \uff0c\u7136\u540e\u89e3\u538b\u3002\uff08\u89c6\u9891\u901a\u8bdd SDK \u94fe\u63a5\uff1a https://docs.agora.io/cn/Video/downloads?platform=iOS \uff09\nb)\t\u6839\u636e\u4f60\u7684\u9700\u6c42\uff0c\u5c06 libs \u6587\u4ef6\u5939\u4e2d\u7684\u52a8\u6001\u5e93\u590d\u5236\u5230\u9879\u76ee\u7684 ./project_name \u6587\u4ef6\u5939\u4e0b\uff08 project_name \u4e3a\u4f60\u7684\u9879\u76ee\u540d\u79f0\uff09\u3002\nc)\t\u6253\u5f00 Xcode \uff0c\u8fdb\u5165 TARGETS > Project Name > Build Phases > Link Binary with Libraries \u83dc\u5355\uff0c\u70b9\u51fb + \u6dfb\u52a0\u5982\u4e0b\u5e93\uff08\u5982\uff1a\uff09\u3002\u5728\u6dfb\u52a0 AgoraRtcEngineKit.framework \u6587\u4ef6\u65f6\uff0c\u8fd8\u9700\u5728\u70b9\u51fb + \u540e\u70b9\u51fb Add Other\u2026\uff0c\u627e\u5230\u672c\u5730\u6587\u4ef6\u5e76\u6253\u5f00\u3002

\n

[\u5916\u94fe\u56fe\u7247\u8f6c\u5b58\u5931\u8d25,\u6e90\u7ad9\u53ef\u80fd\u6709\u9632\u76d7\u94fe\u673a\u5236,\u5efa\u8bae\u5c06\u56fe\u7247\u4fdd\u5b58\u4e0b\u6765\u76f4\u63a5\u4e0a\u4f20(img-RMM224bm-1663063848743)(upload://gOFc9CzhWzmOk7Ef4Dh0QVyu5kp.png)]

\n

\u5171\u9700\u8981\u6dfb\u52a0 11 \u4e2a\u5e93\u6587\u4ef6\uff1a\ni.\tAgoraRtcEngineKit.framework\nii.\tAccelerate.framework\niii.\tAudioToolbox.framework\niv.\tAVFoundation.framework\nv.\tCoreMedia.framework\nvi.\tCoreML.framework\nvii.\tCoreTelephony.framework\nviii.\tlibc++.tbd\nix.\tlibresolv.tbd\nx.\tSystemConfiguration.framework\nxi.\tVideoToolbox.framework\n\u6ce8\u610f\uff1a \u5982\u9700\u652f\u6301 iOS 9.0 \u6216\u66f4\u4f4e\u7248\u672c\u7684\u8bbe\u5907\uff0c\u8bf7\u5728 Xcode \u4e2d\u5c06\u5bf9 CoreML.framework \u7684\u4f9d\u8d56\u8bbe\u4e3a Optional \u3002

\n

d)\t\u6253\u5f00 Xcode \uff0c\u8fdb\u5165 TARGETS > Project Name > General > Frameworks, Libraries, and Embedded Content \u83dc\u5355\u3002\ne)\t\u70b9\u51fb + > Add Other\u2026 > Add Files \u6dfb\u52a0\u5bf9\u5e94\u52a8\u6001\u5e93\uff0c\u5e76\u786e\u4fdd\u6dfb\u52a0\u7684\u52a8\u6001\u5e93 Embed \u5c5e\u6027\u8bbe\u7f6e\u4e3a Embed & Sign \u3002\u6dfb\u52a0\u5b8c\u6210\u540e\uff0c\u9879\u76ee\u4f1a\u81ea\u52a8\u94fe\u63a5\u6240\u9700\u7cfb\u7edf\u5e93\u3002

\n

\u6ce8\u610f\uff1a

\n\n

3.\t\u6743\u9650\u8bbe\u7f6e

\n
    \n
  1. \n

    Xcode \u8fdb\u5165 TARGETS > Project Name > General > Signing \u83dc\u5355\uff0c\u9009\u62e9 Automatically manage signing \uff0c\u5e76\u5728\u5f39\u51fa\u83dc\u5355\u4e2d\u70b9\u51fb Enable Automatic \u3002\n\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"

    \n
  2. \n
  3. \n

    \u6dfb\u52a0\u5a92\u4f53\u8bbe\u5907\u6743\u9650\n\u6839\u636e\u573a\u666f\u9700\u8981\uff0c\u5728 info.plist \u6587\u4ef6\u4e2d\uff0c\u70b9\u51fb + \u56fe\u6807\u5f00\u59cb\u6dfb\u52a0\u5982\u4e0b\u5185\u5bb9\uff0c\u83b7\u53d6\u76f8\u5e94\u7684\u8bbe\u5907\u6743\u9650\uff1a\n\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"\n\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"

    \n
  4. \n
\n

4.\t\u5bfc\u5165 Agora \u76f8\u5173\u7684\u7c7b

\n

\u5728\u9879\u76ee\u4e2d\u5bfc\u5165 AgoraRtcEngineKit \u7c7b\uff1a

\n
// Objective-C\n// ViewController.h\n// \u5bfc\u5165 AgoraRtcKit \u7c7b\n// \u81ea 3.0.0 \u7248\u672c\u8d77\uff0cAgoraRtcEngineKit \u7c7b\u540d\u66f4\u6362\u4e3a AgoraRtcKit\n// \u5982\u679c\u83b7\u53d6\u7684\u662f 3.0.0 \u4ee5\u4e0b\u7248\u672c\u7684 SDK \uff0c\u8bf7\u6539\u7528 #import <AgoraRtcEngineKit/AgoraRtcEngineKit.h>\n#import <AgoraRtcKit/AgoraRtcEngineKit.h>\n// \u58f0\u660e AgoraRtcEngineDelegate \uff0c\u7528\u4e8e\u76d1\u542c\u56de\u8c03\n@interface ViewController : UIViewController <AgoraRtcEngineDelegate>\n// \u5b9a\u4e49 agoraKit \u53d8\u91cf\n@property (strong, nonatomic) AgoraRtcEngineKit *agoraKit;\n\n\n\n// Swift\n// ViewController.swift\n// \u5bfc\u5165 AgoraRtcKit \u7c7b\n// \u81ea 3.0.0 \u7248\u672c\u8d77\uff0cAgoraRtcEngineKit \u7c7b\u540d\u66f4\u6362\u4e3a AgoraRtcKit\n// \u5982\u679c\u83b7\u53d6\u7684\u662f 3.0.0 \u4ee5\u4e0b\u7248\u672c\u7684 SDK \uff0c\u8bf7\u6539\u7528 import AgoraRtcEngineKit\nimport AgoraRtcKit\nclass ViewController: UIViewController {\n ...\n // \u5b9a\u4e49 agoraKit \u53d8\u91cf\n var agoraKit: AgoraRtcEngineKit?\n}\n
\n

5.\t\u8bbe\u7f6e Agora \u8d26\u53f7\u4fe1\u606f

\n

\u5728 AppID.swift \u6587\u4ef6\u4e2d\uff0c\u5c06\u4f60\u7684 AppID \u586b\u5199\u5230 let AppID \uff0c\u53ef\u66ff\u6362\u201cYour App ID\u201d;

\n
// Objective-C\n// AppID.m\n// Agora iOS Tutorial Objective-C\n#import <Foundation/Foundation.h>\nNSString *const appID = <#Your App ID#>;\n\n// Swift\n// AppID.swift\n// Agora iOS Tutorial\nlet AppID: String = Your App ID\n
\n

\u4e94\u3001\t\u5ba2\u6237\u7aef\u5b9e\u73b0

\n

\u672c\u8282\u4ecb\u7ecd\u5982\u4f55\u4f7f\u7528 Agora \u89c6\u9891 SDK \u5728\u4f60\u7684 App \u91cc\u5b9e\u73b0\u89c6\u9891\u901a\u8bdd\u7684\u51e0\u4e2a\u5c0f\u8d34\u58eb\uff1a

\n

1.\t\u521b\u5efa\u7528\u6237\u754c\u9762

\n

\u6839\u636e\u573a\u666f\u9700\u8981\uff0c\u4e3a\u4f60\u7684\u9879\u76ee\u521b\u5efa\u89c6\u9891\u901a\u8bdd\u7684\u7528\u6237\u754c\u9762\u3002\u6211\u4eec\u63a8\u8350\u4f60\u5728\u9879\u76ee\u4e2d\u6dfb\u52a0\u5143\u7d20\uff1a\u672c\u5730\u89c6\u9891\u7a97\u53e3\u3001\u8fdc\u7aef\u89c6\u9891\u7a97\u53e3\u3002\n\u4f60\u53ef\u4ee5\u53c2\u8003\u4ee5\u4e0b\u4ee3\u7801\u521b\u5efa\u4e00\u4e2a\u57fa\u7840\u7684\u7528\u6237\u754c\u9762\u3002

\n
// Objective-C\n// ViewController.m\n// \u5bfc\u5165 UIKit\n#import <UIKit/UIKit.h>\n@interface ViewController ()\n// \u5b9a\u4e49 localView \u53d8\u91cf\n@property (nonatomic, strong) UIView *localView;\n// \u5b9a\u4e49 remoteView \u53d8\u91cf\n@property (nonatomic, strong) UIView *remoteView;\n@end\n@implementation ViewController\n...\n- (void)viewDidLoad {\n [super viewDidLoad];\n // \u8c03\u7528\u521d\u59cb\u5316\u89c6\u9891\u7a97\u53e3\u51fd\u6570\n [self initViews];\n // \u540e\u7eed\u6b65\u9aa4\u8c03\u7528 Agora API \u4f7f\u7528\u7684\u51fd\u6570\n [self initializeAgoraEngine];\n [self setupLocalVideo];\n [self joinChannel];\n}\n// \u8bbe\u7f6e\u89c6\u9891\u7a97\u53e3\u5e03\u5c40\n- (void)viewDidLayoutSubviews {\n [super viewDidLayoutSubviews];\n self.remoteView.frame = self.view.bounds;\n self.localView.frame = CGRectMake(self.view.bounds.size.width - 90, 0, 90, 160);\n}\n- (void)initViews {\n // \u521d\u59cb\u5316\u8fdc\u7aef\u89c6\u9891\u7a97\u53e3\n self.remoteView = [[UIView alloc] init];\n [self.view addSubview:self.remoteView];\n // \u521d\u59cb\u5316\u672c\u5730\u89c6\u9891\u7a97\u53e3\n self.localView = [[UIView alloc] init];\n [self.view addSubview:self.localView];\n}\n\n// Swift\n// ViewController.swift\n// \u5bfc\u5165 UIKit\nimport UIKit\nclass ViewController: UIViewController {\n ...\n // \u5b9a\u4e49 localView \u53d8\u91cf\n var localView: UIView!\n // \u5b9a\u4e49 remoteView \u53d8\u91cf\n var remoteView: UIView!\n override func viewDidLoad() {\n super.viewDidLoad()\n // \u8c03\u7528\u521d\u59cb\u5316\u89c6\u9891\u7a97\u53e3\u51fd\u6570\n initView()\n // \u540e\u7eed\u6b65\u9aa4\u8c03\u7528 Agora API \u4f7f\u7528\u7684\u51fd\u6570\n initializeAgoraEngine()\n setupLocalVideo()\n joinChannel()\n }\n // \u8bbe\u7f6e\u89c6\u9891\u7a97\u53e3\u5e03\u5c40\n override func viewDidLayoutSubviews() {\n super.viewDidLayoutSubviews()\n remoteView.frame = self.view.bounds\n localView.frame = CGRect(x: self.view.bounds.width - 90, y: 0, width: 90, height: 160)\n }\n func initView() {\n // \u521d\u59cb\u5316\u8fdc\u7aef\u89c6\u9891\u7a97\u53e3\n remoteView = UIView()\n self.view.addSubview(remoteView)\n // \u521d\u59cb\u5316\u672c\u5730\u89c6\u9891\u7a97\u53e3\n localView = UIView()\n self.view.addSubview(localView)\n }\n}\n
\n

2.\t\u5b9e\u73b0\u89c6\u9891\u901a\u8bdd\u903b\u8f91

\n

\u73b0\u5728\uff0c\u6211\u4eec\u5df2\u7ecf\u5c06 Agora iOS SDK \u96c6\u6210\u5230\u9879\u76ee\u4e2d\u4e86\u3002\u63a5\u4e0b\u6765\u6211\u4eec\u8981\u5728 ViewController \u4e2d\u8c03\u7528 Agora iOS SDK \u63d0\u4f9b\u7684\u6838\u5fc3 API \u5b9e\u73b0\u57fa\u7840\u7684\u89c6\u9891\u901a\u8bdd\u529f\u80fd\u3002\u4f60\u53ef\u4ee5\u5728 Agora-iOS-Tutorial-Objective-C-1to1/Agora-iOS-Tutorial-Swift-1to1 \u793a\u4f8b\u9879\u76ee\u7684 VideoChatViewController.m/VideoChatViewController.swift \u6587\u4ef6\u4e2d\u67e5\u770b\u5b8c\u6574\u7684\u6e90\u7801\u548c\u4ee3\u7801\u903b\u8f91\u3002

\n

API \u8c03\u7528\u65f6\u5e8f\u89c1\u4e0b\u56fe\uff1a

\n

\"\u5728\u8fd9\u91cc\u63d2\u5165\u56fe\u7247\u63cf\u8ff0\"

\n

\u6309\u7167\u4ee5\u4e0b\u6b65\u9aa4\u5b9e\u73b0\u8be5\u903b\u8f91\uff1a

\n

a)\t\u521d\u59cb\u5316 AgoraRtcEngineKit \u5bf9\u8c61\n\u5728\u8c03\u7528\u5176\u4ed6 Agora API \u524d\uff0c\u9700\u8981\u521b\u5efa\u5e76\u521d\u59cb\u5316 AgoraRtcEngineKit \u5bf9\u8c61\u3002\u8c03\u7528 sharedEngineWithAppId \u65b9\u6cd5\uff0c\u4f20\u5165\u83b7\u53d6\u5230\u7684 App ID \uff0c\u5373\u53ef\u521d\u59cb\u5316 AgoraRtcEngineKit \u3002

\n
// Objective-C\n- (void)initializeAgoraEngine {\n // \u8f93\u5165 App ID \u5e76\u521d\u59cb\u5316 AgoraRtcEngineKit \u7c7b\u3002\n self.agoraKit = [AgoraRtcEngineKit sharedEngineWithAppId:appID delegate:self];\n}\n\n// Swift\nfunc initializeAgoraEngine() {\n // \u8f93\u5165 App ID \u5e76\u521d\u59cb\u5316 AgoraRtcEngineKit \u7c7b\u3002\n agoraKit = AgoraRtcEngineKit.sharedEngine(withAppId: AppID, delegate: self)\n}\n
\n

\u4f60\u8fd8\u53ef\u4ee5\u6839\u636e\u573a\u666f\u9700\u8981\uff0c\u5728\u521d\u59cb\u5316\u65f6\u6ce8\u518c\u60f3\u8981\u76d1\u542c\u7684\u56de\u8c03\u4e8b\u4ef6\uff0c\u5982\u672c\u5730\u7528\u6237\u52a0\u5165\u9891\u9053\uff0c\u53ca\u89e3\u7801\u8fdc\u7aef\u7528\u6237\u89c6\u9891\u9996\u5e27\u7b49\u3002

\n

b)\t\u8bbe\u7f6e\u672c\u5730\u89c6\u56fe\n\u6210\u529f\u521d\u59cb\u5316 AgoraRtcEngineKit \u5bf9\u8c61\u540e\uff0c\u9700\u8981\u5728\u52a0\u5165\u9891\u9053\u524d\u8bbe\u7f6e\u672c\u5730\u89c6\u56fe\uff0c\u4ee5\u4fbf\u5728\u901a\u8bdd\u4e2d\u770b\u5230\u672c\u5730\u56fe\u50cf\u3002\u53c2\u8003\u4ee5\u4e0b\u6b65\u9aa4\u8bbe\u7f6e\u672c\u5730\u89c6\u56fe\uff1a\n\u00b7\t\u8c03\u7528 enableVideo \u65b9\u6cd5\u542f\u7528\u89c6\u9891\u6a21\u5757\u3002\n\u00b7\t\u8c03\u7528 setupLocalVideo \u65b9\u6cd5\u8bbe\u7f6e\u672c\u5730\u89c6\u56fe\u3002

\n
// Objective-C\n// \u542f\u7528\u89c6\u9891\u6a21\u5757\u3002\n[self.agoraKit enableVideo];\n- (void)setupLocalVideo {\n AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];\n videoCanvas.uid = 0;\n videoCanvas.view = self.localVideo;\n videoCanvas.renderMode = AgoraVideoRenderModeHidden;\n // \u8bbe\u7f6e\u672c\u5730\u89c6\u56fe\u3002\n [self.agoraKit setupLocalVideo:videoCanvas];\n}\n\n// Swift\n// \u542f\u7528\u89c6\u9891\u6a21\u5757\u3002\nagoraKit.enableVideo()\nfunc setupLocalVideo() {\n let videoCanvas = AgoraRtcVideoCanvas()\n videoCanvas.uid = 0\n videoCanvas.view = localVideo\n videoCanvas.renderMode = .hidden\n // \u8bbe\u7f6e\u672c\u5730\u89c6\u56fe\u3002\n agoraKit.setupLocalVideo(videoCanvas)\n}\n
\n

c)\t\u52a0\u5165\u9891\u9053\n\u9891\u9053\u662f\u4eba\u4eec\u5728\u540c\u4e00\u4e2a\u89c6\u9891\u901a\u8bdd\u4e2d\u7684\u516c\u5171\u7a7a\u95f4\u3002\u5b8c\u6210\u521d\u59cb\u5316\u548c\u8bbe\u7f6e\u672c\u5730\u89c6\u56fe\u540e\uff08\u89c6\u9891\u901a\u8bdd\u573a\u666f\uff09\uff0c\u4f60\u5c31\u53ef\u4ee5\u8c03\u7528 joinChannelByToken \u65b9\u6cd5\u52a0\u5165\u9891\u9053\u3002\u4f60\u9700\u8981\u5728\u8be5\u65b9\u6cd5\u4e2d\u4f20\u5165\u5982\u4e0b\u53c2\u6570\uff1a

\n
    \n
  1. channelId: \u4f20\u5165\u80fd\u6807\u8bc6\u9891\u9053\u7684\u9891\u9053 ID \u3002\u8f93\u5165\u9891\u9053 ID \u76f8\u540c\u7684\u7528\u6237\u4f1a\u8fdb\u5165\u540c\u4e00\u4e2a\u9891\u9053\u3002
  2. \n
  3. token: \u4f20\u5165\u80fd\u6807\u8bc6\u7528\u6237\u89d2\u8272\u548c\u6743\u9650\u7684 Token \u3002\u4f60\u53ef\u4ee5\u8bbe\u7f6e\u5982\u4e0b\u503c\uff1a\na)\tnil \u3002\nb)\t\u63a7\u5236\u53f0\u4e2d\u751f\u6210\u7684\u4e34\u65f6 Token \u3002\u4e00\u4e2a\u4e34\u65f6 Token \u7684\u6709\u6548\u671f\u4e3a 24 \u5c0f\u65f6\uff0c\u8be6\u60c5\u89c1\u83b7\u53d6\u4e34\u65f6 Token \u3002\nc)\t\u4f60\u7684\u670d\u52a1\u5668\u7aef\u751f\u6210\u7684\u6b63\u5f0f Token \u3002\u9002\u7528\u4e8e\u5bf9\u5b89\u5168\u8981\u6c42\u8f83\u9ad8\u7684\u751f\u4ea7\u73af\u5883\uff0c\u8be6\u60c5\u89c1\u751f\u6210 Token \u3002\u82e5\u9879\u76ee\u5df2\u542f\u7528 App \u8bc1\u4e66\uff0c\u8bf7\u4f7f\u7528 Token \u3002\nd)\tuid: \u672c\u5730\u7528\u6237\u7684 ID \u3002\u6570\u636e\u7c7b\u578b\u4e3a\u6574\u578b\uff0c\u4e14\u9891\u9053\u5185\u6bcf\u4e2a\u7528\u6237\u7684 uid \u5fc5\u987b\u662f\u552f\u4e00\u7684\u3002\u82e5\u5c06 uid \u8bbe\u4e3a 0 \uff0c\u5219 SDK \u4f1a\u81ea\u52a8\u5206\u914d\u4e00\u4e2a uid \uff0c\u5e76\u5728 joinSuccessBlock \u56de\u8c03\u4e2d\u62a5\u544a\u3002\ne)\tjoinSuccessBlock\uff1a\u6210\u529f\u52a0\u5165\u9891\u9053\u56de\u8c03\u3002joinSuccessBlock \u4f18\u5148\u7ea7\u9ad8\u4e8e didJoinChannel \uff0c2 \u4e2a\u540c\u65f6\u5b58\u5728\u65f6\uff0cdidJoinChannel \u4f1a\u88ab\u5ffd\u7565\u3002\u9700\u8981\u6709 didJoinChannel \u56de\u8c03\u65f6\uff0c\u8bf7\u5c06 joinSuccessBlock \u8bbe\u7f6e\u4e3a nil \u3002
  4. \n
\n

\u66f4\u591a\u7684\u53c2\u6570\u8bbe\u7f6e\u6ce8\u610f\u4e8b\u9879\u8bf7\u53c2\u8003 joinChannelByToken \u63a5\u53e3\u4e2d\u7684\u53c2\u6570\u63cf\u8ff0\u3002

\n
// Objective-C\n- (void)joinChannel {\n // \u52a0\u5165\u9891\u9053\u3002\n [self.agoraKit joinChannelByToken:token channelId:@\"demoChannel1\" info:nil uid:0 joinSuccess:^(NSString *channel, NSUInteger uid, NSInteger elapsed) {\n }];\n}\n\n// Swift\nfunc joinChannel() {\n // \u52a0\u5165\u9891\u9053\u3002\n agoraKit.joinChannel(byToken: Token, channelId: \"demoChannel1\", info:nil, uid:0) { [unowned self] (channel, uid, elapsed) -> Void in}\n self.isLocalVideoRender = true\n self.logVC?.log(type: .info, content: \"did join channel\")\n }\n isStartCalling = true\n}\n
\n

d)\t\u8bbe\u7f6e\u8fdc\u7aef\u89c6\u56fe\n\u89c6\u9891\u901a\u8bdd\u4e2d\uff0c\u901a\u5e38\u4f60\u4e5f\u9700\u8981\u770b\u5230\u5176\u4ed6\u7528\u6237\u3002\u5728\u52a0\u5165\u9891\u9053\u540e\uff0c\u53ef\u901a\u8fc7\u8c03\u7528 setupRemoteVideo \u65b9\u6cd5\u8bbe\u7f6e\u8fdc\u7aef\u7528\u6237\u7684\u89c6\u56fe\u3002

\n

\u8fdc\u7aef\u7528\u6237\u6210\u529f\u52a0\u5165\u9891\u9053\u540e\uff0cSDK \u4f1a\u89e6\u53d1 firstRemoteVideoDecodedOfUid \u56de\u8c03\uff0c\u8be5\u56de\u8c03\u4e2d\u4f1a\u5305\u542b\u8fd9\u4e2a\u8fdc\u7aef\u7528\u6237\u7684 uid \u4fe1\u606f\u3002\u5728\u8be5\u56de\u8c03\u4e2d\u8c03\u7528 setupRemoteVideo \u65b9\u6cd5\uff0c\u4f20\u5165\u83b7\u53d6\u5230\u7684 uid \uff0c\u8bbe\u7f6e\u8fdc\u7aef\u7528\u6237\u7684\u89c6\u56fe\u3002

\n
\n// Objective-C\n// \u76d1\u542c firstRemoteVideoDecodedOfUid \u56de\u8c03\u3002\n// SDK \u63a5\u6536\u5230\u7b2c\u4e00\u5e27\u8fdc\u7aef\u89c6\u9891\u5e76\u6210\u529f\u89e3\u7801\u65f6\uff0c\u4f1a\u89e6\u53d1\u8be5\u56de\u8c03\u3002\n// \u53ef\u4ee5\u5728\u8be5\u56de\u8c03\u4e2d\u8c03\u7528 setupRemoteVideo \u65b9\u6cd5\u8bbe\u7f6e\u8fdc\u7aef\u89c6\u56fe\u3002\n- (void)rtcEngine:(AgoraRtcEngineKit *)engine firstRemoteVideoDecodedOfUid:(NSUInteger)uid size: (CGSize)size elapsed:(NSInteger)elapsed {\n if (self.remoteVideo.hidden) {\n self.remoteVideo.hidden = NO;\n }\n AgoraRtcVideoCanvas *videoCanvas = [[AgoraRtcVideoCanvas alloc] init];\n videoCanvas.uid = uid;\n videoCanvas.view = self.remoteVideo;\n videoCanvas.renderMode = AgoraVideoRenderModeHidden;\n // \u8bbe\u7f6e\u8fdc\u7aef\u89c6\u56fe\u3002\n [self.agoraKit setupRemoteVideo:videoCanvas];\n}\n\n// Swift\n// \u76d1\u542c firstRemoteVideoDecodedOfUid \u56de\u8c03\u3002\n// SDK \u63a5\u6536\u5230\u7b2c\u4e00\u5e27\u8fdc\u7aef\u89c6\u9891\u5e76\u6210\u529f\u89e3\u7801\u65f6\uff0c\u4f1a\u89e6\u53d1\u8be5\u56de\u8c03\u3002\n// \u53ef\u4ee5\u5728\u8be5\u56de\u8c03\u4e2d\u8c03\u7528 setupRemoteVideo \u65b9\u6cd5\u8bbe\u7f6e\u8fdc\u7aef\u89c6\u56fe\u3002\nfunc rtcEngine(_ engine: AgoraRtcEngineKit, firstRemoteVideoDecodedOfUid uid:UInt, size:CGSize, elapsed:Int) {\n isRemoteVideoRender = true\n let videoCanvas = AgoraRtcVideoCanvas()\n videoCanvas.uid = uid\n videoCanvas.view = remoteVideo\n videoCanvas.renderMode = .hidden\n // \u8bbe\u7f6e\u8fdc\u7aef\u89c6\u56fe\u3002\n agoraKit.setupRemoteVideo(videoCanvas)\n }\n
\n

e)\t\u79bb\u5f00\u9891\u9053\n\u6839\u636e\u573a\u666f\u9700\u8981\uff0c\u5982\u7ed3\u675f\u901a\u8bdd\u3001\u5173\u95ed App \u6216 App \u5207\u6362\u81f3\u540e\u53f0\u65f6\uff0c\u8c03\u7528 leaveChannel \u79bb\u5f00\u5f53\u524d\u901a\u8bdd\u9891\u9053\u3002

\n
// Objective-C\n- (void)leaveChannel {\n // \u79bb\u5f00\u9891\u9053\u3002\n [self.agoraKit leaveChannel:^(AgoraChannelStats *stat)\n}\n\n// Swift\nfunc leaveChannel() {\n // \u79bb\u5f00\u9891\u9053\u3002\n agoraKit.leaveChannel(nil)\n isRemoteVideoRender = false\n isLocalVideoRender = false\n isStartCalling = false\n self.logVC?.log(type: .info, content: \"did leave channel\")\n }\n
\n

f)\t\u9500\u6bc1 AgoraRtcEngineKit \u5bf9\u8c61\n\u6700\u540e\uff0c\u79bb\u5f00\u9891\u9053\uff0c\u6211\u4eec\u9700\u8981\u8c03\u7528 destroy \u9500\u6bc1 AgoraRtcEngineKit \u5bf9\u8c61\uff0c\u91ca\u653e Agora SDK \u4f7f\u7528\u7684\u6240\u6709\u8d44\u6e90\u3002

\n
// Objective-C\n// ViewController.m\n// \u5c06\u4ee5\u4e0b\u4ee3\u7801\u586b\u5165\u4f60\u5b9a\u4e49\u7684\u51fd\u6570\u4e2d\n[AgoraRtcEngineKit destroy];\n\n// Swift\n// ViewController.swift\n// \u5c06\u4ee5\u4e0b\u4ee3\u7801\u586b\u5165\u4f60\u5b9a\u4e49\u7684\u51fd\u6570\u4e2d\nAgoraRtcEngineKit.destroy()\n
\n

\u81f3\u6b64\uff0c\u5b8c\u6210\uff0c\u8fd0\u884c\u770b\u770b\u6548\u679c\u3002\u62ff\u4e24\u90e8 iOS \u624b\u673a\u5b89\u88c5\u7f16\u8bd1\u597d\u7684 App \uff0c\u52a0\u5165\u540c\u4e00\u4e2a\u9891\u9053\u540d\uff0c\u5982\u679c 2 \u4e2a\u624b\u673a\u90fd\u80fd\u770b\u89c1\u672c\u5730\u548c\u8fdc\u7aef\u89c6\u9891\u56fe\u50cf\uff0c\u8bf4\u660e\u4f60\u6210\u529f\u4e86\u3002

\n

\u5982\u679c\u4f60\u5728\u5f00\u53d1\u8fc7\u7a0b\u4e2d\u9047\u5230\u95ee\u9898\uff0c\u53ef\u4ee5\u8bbf\u95ee\u8bba\u575b\u63d0\u95ee\u4e0e\u58f0\u7f51\u5de5\u7a0b\u5e08\u4ea4\u6d41https://rtcdeveloper.agora.io/

\n" }, { "author": { "url": "member/sss007", "name": "sss007", "avatar": "https://cdn.v2ex.com/avatar/66ee/e9ca/277657_large.png?m=1769416187" }, "url": "t/830697", "title": "webrtc \u6709\u4ec0\u4e48\u5c01\u88c5\u6bd4\u8f83\u597d\u7684 c/c++\u5e93\u5417", "id": "t/830697", "date_published": "2022-01-26T04:19:41+00:00", "content_html": "

\u770b\u4e86\u8bba\u575b\u4e00\u8001\u54e5\u505a\u7684 webrtc \u8bed\u97f3\u804a\u5929\uff0c\u4e86\u89e3\u4e86\u4e0b webrtc,web \u8c03\u7528\u662f\u771f\u65b9\u4fbf\uff0c\u4f46\u662f\u8c8c\u4f3c\u6ca1\u6709\u6bd4\u8f83\u5b8c\u5584\u7684 c/c++\u5ba2\u6237\u7aef\u7684\u5e93

\n" }, { "author": { "url": "member/silverdog", "name": "silverdog", "avatar": "https://cdn.v2ex.com/gravatar/37348b8ef93b566c714a5c238b0b2bdd?s=73&d=retro" }, "url": "t/767622", "date_modified": "2021-04-02T09:28:17+00:00", "content_html": "\u5982\u4f55\u89e3\u51b3\u7740\u6025\uff01\uff01\uff01\uff01\uff01\uff01\uff01

// \u8c03\u7528\u7b2c\u4e09\u65b9\u7f8e\u989c\u7b97\u6cd5\uff08 mMHBeautyManager.render \uff09 \u8fd4\u56de\u65b0\u7684 textureId
// textureId \u751f\u6210 VideoFrame
// s.onFrame()


// \u62a5\u9519
11-24 16:01:59.673: E/org.webrtc.Logging(25509): MediaCodecVideoEncoder: encodeTexture failed
11-24 16:01:59.673: E/org.webrtc.Logging(25509): MediaCodecVideoEncoder: java.lang.RuntimeException: glUseProgram: GLES20 error: 1282
11-24 16:01:59.676: E/org.webrtc.Logging(25509): MediaCodecVideoEncoder: java.lang.RuntimeException: glUseProgram: GLES20 error: 1282
11-24 16:01:59.676: E/org.webrtc.Logging(25509): at org.webrtc.GlUtil.checkNoGLES2Error(GlUtil.java:29)
11-24 16:01:59.676: E/org.webrtc.Logging(25509): at org.webrtc.GlShader.useProgram(GlShader.java:110)
11-24 16:01:59.676: E/org.webrtc.Logging(25509): at org.webrtc.GlRectDrawer.prepareShader(GlRectDrawer.java:195)
11-24 16:01:59.676: E/org.webrtc.Logging(25509): at org.webrtc.GlRectDrawer.drawOes(GlRectDrawer.java:118)
11-24 16:01:59.676: E/org.webrtc.Logging(25509): at org.webrtc.MediaCodecVideoEncoder.encodeTexture(MediaCodecVideoEncoder.java:592)



// \u5173\u952e\u4ee3\u7801\u5982\u4e0b
val buffer = p0.buffer as TextureBuffer
val textureId = mMHBeautyManager.render(
buffer.textureId,
buffer.width,
buffer.height,1,1
)
val textureBufferImpl= TextureBufferImpl(
buffer.width,
buffer.height,
buffer.type,
textureId,
buffer.transformMatrix,
surfaceTextureHelper?.handler,
yuvConverter,
null
)

val new = VideoFrame(textureBufferImpl, 270, System.nanoTime())
s.onFrame(new)", "date_published": "2021-04-02T09:27:28+00:00", "title": "android google \u539f\u751f webrtc setVideoProcessor \u5982\u4f55\u6d88\u8d39 VideoFrame", "id": "t/767622" }, { "author": { "url": "member/VideoCloudTech", "name": "VideoCloudTech", "avatar": "https://cdn.v2ex.com/avatar/9612/8e04/513669_large.png?m=1610098421" }, "url": "t/767568", "title": "\u963f\u91cc\u4e91 RTC QoS \u5f31\u7f51\u5bf9\u6297\u4e4b\u53d8\u5206\u8fa8\u7387\u7f16\u7801", "id": "t/767568", "date_published": "2021-04-02T07:16:02+00:00", "content_html": "

\u4f5c\u8005\uff5c\u5b89\u57fa\u7a0b\u3001\u7530\u4f1f\u5cf0

\n

\u5ba1\u6821\uff5c \u6cf0\u4e00

\n

\u89c6\u9891\u7f16\u7801\u4e2d\u7684\u53d8\u5206\u8fa8\u7387\u95ee\u9898\u53ca\u89e3\u51b3

\n

\u53d8\u5206\u8fa8\u7387\u5728\u5f31\u7f51\u573a\u666f\u7684\u5b9e\u9645\u5e94\u7528\u4e2d\u975e\u5e38\u5e38\u89c1\uff0c\u7f51\u7edc\u72b6\u51b5\u4e0d\u597d\u7684\u65f6\u5019\u964d\u4f4e\u5206\u8fa8\u7387\u53ef\u4ee5\u964d\u4f4e\u7801\u7387\uff0c\u51cf\u5c11\u5757\u6548\u5e94\uff0c\u7f51\u7edc\u597d\u7684\u65f6\u5019\u589e\u52a0\u5206\u8fa8\u7387\u53ef\u4ee5\u63d0\u5347\u6e05\u6670\u5ea6\u53ca\u4e3b\u89c2\u4f53\u9a8c\u3002

\n

\u76ee\u524d\u4e3b\u6d41\u7684\u89c6\u9891\u7f16\u7801\u6807\u51c6\uff0c\u6bd4\u5982 H.264 \u3001H.265 \uff0c\u5728\u7f16\u7801\u8fc7\u7a0b\u4e2d\u5982\u679c\u8981\u8fdb\u884c\u5206\u8fa8\u7387\u5207\u6362\uff0c\u5219\u5fc5\u987b\u8981\u5148\u7f16\u7801\u4e00\u4e2a I \u5e27\uff0c\u800c I \u5e27\u53ea\u80fd\u4f7f\u7528\u5e27\u5185\u9884\u6d4b\uff0c\u7f16\u7801\u6548\u7387\u4f4e\u4e0b\u3002\u8fd9\u5728\u5f31\u7f51\u53d8\u5206\u8fa8\u7387\u7684\u65f6\u5019\u5c31\u5bb9\u6613\u9020\u6210\u5361\u987f\u3002\u4e0b\u56fe\u4e2d\u5c55\u793a\u4e86\u6bcf\u79d2\u949f\u5207\u6362\u5206\u8fa8\u7387\u7684\u7801\u7387\u6ce2\u52a8\u6548\u679c\uff0c\u9ad8\u4f4e\u4e24\u4e2a\u5206\u8fa8\u7387\uff0c\u6bcf\u79d2\u949f\u5207\u6362\u4e00\u6b21\u3002

\n

\"\"

\n

\u4e0a\u56fe\u4e2d\u6a2a\u5750\u6807\u8868\u793a\u7f16\u7801\u7684\u5e27\u6570\uff0c\u7eb5\u5750\u6807\u8868\u793a\u6bcf\u5e27\u7684\u5927\u5c0f\uff0c\u56fe\u4e2d\u6700\u9ad8\u7684 4 \u4e2a\u5c16\u5cf0\u8868\u793a\u4ece\u4f4e\u5206\u8fa8\u7387\u5207\u6362\u5230\u9ad8\u5206\u8fa8\u7387\u65f6\u7f16\u7684 I \u5e27\uff0c\u5728\u8fd9 4 \u4e2a\u5c16\u5cf0\u4e2d\u95f4\u7684\u8f83\u4f4e\u5c16\u5cf0\u662f\u4ece\u9ad8\u5206\u8fa8\u7387\u5207\u6362\u5230\u4f4e\u5206\u8fa8\u7387\u7f16\u7801\u7684 I \u5e27\u3002\u53ef\u89c1\u7f16\u7801 I \u5e27\u5e26\u6765\u7684\u7801\u7387\u6ce2\u52a8\u8fd8\u662f\u975e\u5e38\u660e\u663e\u7684\uff0c\u8fd9\u5728\u5f31\u7f51\u4e0b\u5c31\u5f88\u6709\u53ef\u80fd\u9020\u6210\u5982\u4e0b\u56fe\u6240\u793a\u7684\u5361\u987f\u3002

\n

https://v.youku.com/v_show/id_XNTEzMTY3MzU5Ng==.html

\n

\u89c6\u9891\u4e2d\u5de6\u4e00\u7684\u7537\u58eb\u5728\u4f38\u624b\u521a\u63a5\u5230\u5de6\u4e09\u5973\u58eb\u9012\u51fa\u7684\u4f20\u5355\u4e4b\u65f6\u8fdb\u5165\u5f31\u7f51\uff0c\u5207\u6362\u5206\u8fa8\u7387\uff0c\u4ea7\u751f\u4e86\u5361\u987f\u3002

\n

\u65b0\u4e00\u4ee3\u7684\u538b\u7f29\u6807\u51c6\uff0c\u5982 VP9 \u3001AV1 \u3001VVC/H.266 \u7b49\u90fd\u652f\u6301\u5728\u505a\u5e27\u95f4\u9884\u6d4b\u7684\u65f6\u5019\u5f53\u524d\u5e27\u548c\u5176\u53c2\u8003\u5e27\u4f7f\u7528\u4e0d\u540c\u7684\u5206\u8fa8\u7387\uff0c\u5176\u57fa\u672c\u601d\u60f3\u662f\u5bf9\u53c2\u8003\u5e27\u505a\u91cd\u91c7\u6837 (re-sampling) \u4ee5\u4f7f\u5f97\u5176\u548c\u5f53\u524d\u5e27\u7684\u5206\u8fa8\u7387\u5339\u914d\uff0c\u4ece\u800c\u8fdb\u884c\u5e27\u95f4\u9884\u6d4b\uff0c\u4ee5\u5b9e\u73b0\u5206\u8fa8\u7387\u5207\u6362\u7684\u65f6\u5019\u4e0d\u7528\u7f16 I \u5e27\u7684\u76ee\u7684\u3002

\n

\u963f\u91cc\u4e91 RTC codec \u7684\u53d8\u5206\u8fa8\u7387\u7f16\u7801 (resolution change coding, \u4ee5\u4e0b\u7b80\u79f0 RCC) \u4e5f\u4f7f\u7528\u548c\u4e0a\u8ff0\u6807\u51c6\u7c7b\u4f3c\u7684\u57fa\u672c\u601d\u60f3\uff0c\u901a\u8fc7\u53c2\u8003\u5e27\u91cd\u91c7\u6837\u7b49\u624b\u6bb5\u4f7f\u5f97\u4e4b\u524d\u5df2\u7f16\u7801\u7684\u5176\u4ed6\u5206\u8fa8\u7387\u7684\u53c2\u8003\u5e27\u4e5f\u80fd\u4e3a\u5f53\u524d\u5e27\u6240\u7528\uff0c\u7ef4\u6301\u5e27\u95f4\u7684\u53c2\u8003\u94fe\u4e0d\u65ad\uff0c\u5145\u5206\u5229\u7528\u5e27\u95f4\u4fe1\u606f\u5197\u4f59\u63d0\u5347\u538b\u7f29\u6548\u7387\uff0c\u7701\u53bb\u7f16\u7801\u6548\u7387\u4f4e\u4e0b\u7684 I \u5e27\u3002

\n

Codec level \u538b\u7f29\u6027\u80fd\u6d4b\u8bd5

\n

\u672c\u6587\u5bf9\u963f\u91cc\u4e91 RTC codec \u7684 RCC \u7279\u6027\u8fdb\u884c\u6d4b\u8bd5\uff0c\u4f7f\u7528 6 \u4e2a\u89c6\u9891\u4f1a\u8bae\u5e8f\u5217\uff08\u80cc\u666f\u4e0d\u52a8\uff0c\u8fd0\u52a8\u5e45\u5ea6\u8f83\u5c0f\uff09\uff0c\u548c 5 \u4e2a\u8fd0\u52a8\u7a0b\u5ea6\u8f83\u5927\u7684\u5e8f\u5217\uff0c\u9ad8\u4f4e\u4e24\u4e2a\u5206\u8fa8\u7387\uff0c\u4e00\u79d2\u949f\u5207\u6362\u4e00\u6b21\uff0c\u53ea\u8bc4\u4ef7\u5206\u8fa8\u7387\u5207\u6362\u5e27\u7684\u7801\u7387\u548c\u89c6\u9891\u8d28\u91cf\uff0c\u56e0\u4e3a\u5bf9\u4e8e\u540e\u7eed\u7684\u5e27\uff0c\u4f7f\u7528 RCC \u4e0e\u5426\uff0c\u7f16\u7801\u65b9\u5f0f\u5e76\u6ca1\u6709\u53d8\u5316\u3002

\n

\u5bf9\u4e8e\u89c6\u9891\u4f1a\u8bae\u5e8f\u5217\uff0c\u76f8\u540c\u89c6\u9891\u8d28\u91cf\u4e0b\u7801\u7387\u6709 70% \u8282\u7701\uff0c\u5bf9\u4e8e\u8fd0\u52a8\u5e8f\u5217\uff0c\u76f8\u540c\u89c6\u9891\u8d28\u91cf\u4e0b\u7801\u7387\u6709 58% \u7684\u8282\u7701\uff0c\u56e0\u4e3a\u89c6\u9891\u5185\u5bb9\u8d8a\u9759\u6b62\u4e0d\u52a8\uff0c\u5e27\u95f4\u7f16\u7801\u7684\u6bd4\u4f8b\u8d8a\u9ad8\uff0c\u5219 RCC \u7684\u4f18\u52bf\u8d8a\u660e\u663e\uff0c\u6240\u4ee5\u89c6\u9891\u4f1a\u8bae\u5e8f\u5217 RCC \u7684\u589e\u76ca\u6bd4\u8fd0\u52a8\u5e8f\u5217\u8981\u9ad8\uff0c\u662f\u5408\u7406\u7684\u3002

\n

\u4e0b\u56fe\u5c55\u793a\u4e86\u4e00\u4e2a\u6d4b\u8bd5\u5e8f\u5217\u4f7f\u7528 RCC \u540e\u7801\u7387\u6ce2\u52a8\u7684\u53d8\u5316\uff0c\u84dd\u7ebf\u8868\u793a\u7684\u662f\u672a\u52a0 RCC \u7684\u7801\u7387\u6ce2\u52a8\uff0c\u7ea2\u7ebf\u8868\u793a\u7684\u662f\u52a0\u4e86 RCC \u4e4b\u540e\u7684\u7801\u7387\u6ce2\u52a8\uff0c\u53ef\u4ee5\u770b\u5230\u4f7f\u7528 RCC \u540e\u5206\u8fa8\u7387\u5207\u6362\u5904\u7684\u7f16\u7801 I \u5e27\u7801\u7387\u5c16\u5cf0\u660e\u663e\u6ca1\u6709\u4e86\uff0c\u7801\u7387\u66f4\u52a0\u5e73\u7a33\uff0c\u800c\u4e14\u89c6\u9891\u8d28\u91cf PSNR \u4e5f\u6709\u6240\u63d0\u5347\u3002

\n

\"\"

\n

\u84dd\u7ebf\u4e2d\u5206\u8fa8\u7387\u5207\u6362\u5904\u7684 I \u5e27\u5e73\u5747\u7801\u7387\u4e3a 840kbps, PSNR=33.5db, 39.7db, 40.6db for Y, U, V \u4e09\u4e2a\u5206\u91cf\uff1b\u800c\u7ea2\u7ebf\u4e2d\u5206\u8fa8\u7387\u5207\u6362\u5e27\u7684\u5e73\u5747\u7801\u7387\u4e3a 360kbps, PSNR=36.3db, 40.9db, 42.0db for Y, U, V \u4e09\u4e2a\u5206\u91cf\u3002

\n

\u5373\u5f00\u4e86 RCC \u4e4b\u540e\uff0c\u5206\u8fa8\u7387\u5207\u6362\u65f6\u7684 I \u5e27\u7801\u7387\u964d\u4f4e\u4e86\u8fd1 60%\uff0c\u540c\u65f6\u4eae\u5ea6\u7684 PSNR \u63d0\u5347\u4e86\u8fd1 3 \u4e2a db \u3002

\n

RTC level \u6548\u679c

\n

\u9664\u4e86\u524d\u8ff0\u7684\u5355\u7eaf codec level \u53d8\u5206\u8fa8\u7387\u4e0d\u7f16 I \u5e27\u5e26\u6765\u7684\u4e00\u5e27\u7684\u538b\u7f29\u6027\u80fd\u63d0\u5347\u4e4b\u5916\uff0cRCC \u5728\u548c LTR (Long Term Reference) \u7ed3\u5408\u540e\u4f1a\u8fdb\u4e00\u6b65\u964d\u4f4e\u5f31\u7f51\u4e0b\u9891\u7e41\u8bf7\u6c42 I \u5e27\u7684\u53ef\u80fd\u6027\u3002

\n

LTR \u6297\u5f31\u7f51\u7684\u539f\u7406\u5728\u4e0a\u4e00\u7bc7\u5206\u4eab\u300a\u963f\u91cc\u4e91 RTC QoS \u5c4f\u5e55\u5171\u4eab\u5f31\u7f51\u4f18\u5316\u4e4b\u82e5\u5e72\u7f16\u7801\u5668\u76f8\u5173\u4f18\u5316\u300b\u4e2d\u5df2\u6709\u6240\u4ecb\u7ecd\uff0c\u5728\u6b64\u7ed3\u5408 RCC \u4f1a\u8fdb\u4e00\u6b65\u63d0\u5347\u5176\u6297\u5f31\u7f51\u6548\u679c\uff0c\u539f\u7406\u5982\u4e0b\uff1a

\n
    \n
  1. \u6ca1\u6709 LTR \u65f6\uff0c\u5728\u5f31\u7f51\u573a\u666f\u4e0b\u5982\u679c\u4e22\u5305\u6216\u5361\u987f\u65e0\u6cd5\u6062\u590d\uff0c\u5219\u4f1a\u8bf7\u6c42 I \u5e27\uff1b
  2. \n
  3. \u589e\u52a0\u4e86 LTR \u4e4b\u540e\uff0c\u5219\u4e0d\u4f1a\u8bf7\u6c42 I \u5e27\uff0c\u800c\u662f\u4f1a\u8bf7\u6c42 LTR \u5e27\u6062\u590d\uff0c\u7f16\u7801\u6548\u7387\u63d0\u5347\u5f88\u591a\uff1b
  4. \n
  5. \u5982\u679c\u662f\u5f31\u7f51\u4e0b\u53d1\u751f\u4e86\u5206\u8fa8\u7387\u5207\u6362\uff0c\u6ca1\u6709 RCC \u7684\u60c5\u51b5\u4e0b\uff0c\u7531\u4e8e\u5fc5\u987b\u7f16\u7801 IDR \u5e27\uff0c\u6240\u4ee5 LTR \u88ab\u6e05\u7a7a\uff0c\u5982\u679c\u6b64 I \u5e27\u592a\u5927\uff0c\u5bfc\u81f4\u63a5\u6536\u7aef\u6536\u4e0d\u5230\uff0c\u5219\u5176\u4f1a\u518d\u6b21\u8bf7\u6c42 I \u5e27\uff0c\u9677\u5165\u4e00\u4e2a\u6076\u6027\u5faa\u73af\u4e2d\u3002
  6. \n
  7. \u5982\u679c\u5f00\u4e86 RCC\uff0c\u4e0d\u4ec5\u5206\u8fa8\u7387\u5207\u6362\u5e27\u672c\u5e27\u4e0d\u4f1a\u7f16\u7801 I \u5e27\uff0c\u5176\u4ed6\u7684\u53c2\u8003\u5e27\u7ba1\u7406\u4e5f\u548c\u4e4b\u524d\u4e00\u6837\uff0cLTR \u4e5f\u4e0d\u4f1a\u88ab\u6e05\u7a7a\uff0c\u5206\u8fa8\u7387\u5207\u6362\u5e27\u672c\u5e27\u7684\u5927\u5c0f\u6bd4 I \u5e27\u51cf\u5c11\u4e86\u5f88\u591a\uff0c\u63a5\u6536\u7aef\u6536\u4e0d\u5230\u7684\u6982\u7387\u5927\u5927\u964d\u4f4e\uff0c\u5373\u4f7f\u6536\u4e0d\u5230\uff0c\u4e5f\u53ef\u4ee5\u8bf7\u6c42 LTR \u6062\u590d\uff0c\u800c\u4e0d\u662f I \u5e27\u6062\u590d\u3002
  8. \n
\n

\u672c\u6587\u5728 RTC level \u6a21\u62df\u5f31\u7f51\u573a\u666f\uff0c\u4f7f\u5176\u4e00\u79d2\u949f\u5207\u6362\u4e00\u6b21\u5206\u8fa8\u7387\uff0c\u4e0b\u9762\u4e24\u56fe\u5206\u522b\u662f\u672a\u52a0 RCC \u548c \u52a0\u4e86 RCC \u4e4b\u540e\u7684\u6548\u679c\uff0c\u53ef\u4ee5\u770b\u5230\u672a\u52a0 RCC \u7684\u753b\u9762\u5728\u5206\u8fa8\u7387\u5207\u6362\u65f6\u4f1a\u6709\u660e\u663e\u7684\u5361\u987f\u4ee5\u53ca\u7f16 I \u5e27\u9020\u6210\u7684 flicker \u6548\u5e94\uff0c\u800c\u52a0\u4e86 RCC \u7684\u5219\u4f1a\u5f88\u6d41\u7545\uff0c\u753b\u9762\u4e5f\u6ca1\u6709 flicker \u6548\u5e94\u3002

\n

\"\"

\n

\u4e0a\u56fe\u662f\u672a\u52a0 RCC\uff0c\u4e00\u79d2\u949f\u5207\u6362\u4e00\u6b21\u5206\u8fa8\u7387\u7684\u6548\u679c\uff0c\u6709\u591a\u6b21\u660e\u663e\u7684\u5c0f\u5361\u987f\uff0c\u4e14\u753b\u9762\u6709\u9891\u7e41 I \u5e27\u9020\u6210\u7684 flicker \u6548\u5e94\u3002

\n

\"\"

\n

\u4e0a\u56fe\u662f\u52a0\u4e86 RCC\uff0c\u4e00\u79d2\u949f\u5207\u6362\u4e00\u6b21\u5206\u8fa8\u7387\u7684\u6548\u679c\uff0c\u6574\u4f53\u6bd4\u8f83\u6d41\u7545\uff0c\u611f\u89c9\u4e0d\u5230\u5361\u987f\uff0c\u89c6\u9891\u8d28\u91cf\u4e5f\u6bd4\u8f83\u5e73\u7a33\uff0c\u6ca1\u6709 flicker \u6548\u5e94\u3002

\n" }, { "author": { "url": "member/mirzatanvir00", "name": "mirzatanvir00", "avatar": "https://cdn.v2ex.com/avatar/4660/29e8/540572_large.png?m=1617183438" }, "url": "t/767175", "title": "I need help froma software engineer who can work with Janus gateway (WebRTC server technologies ) system .", "id": "t/767175", "date_published": "2021-04-01T04:22:46+00:00", "content_html": "some partial work for our apps development, he can work few hours for us from his home or office, we will pay for this support. We need some help regarding some libaries .
mail : mirzatanvir00@gmail.com
wechat : mirzatanvir" }, { "author": { "url": "member/silverdog", "name": "silverdog", "avatar": "https://cdn.v2ex.com/gravatar/37348b8ef93b566c714a5c238b0b2bdd?s=73&d=retro" }, "url": "t/765116", "title": "WebRTC \u5982\u4f55\u5b9e\u73b0\u7f8e\u989c\u529f\u80fd", "id": "t/765116", "date_published": "2021-03-25T09:25:28+00:00", "content_html": "

\u54ea\u4f4d\u5927\u4f6c\u80fd\u5426\u7ed9\u4e2a\u5efa\u8bae\u3002

\n" }, { "author": { "url": "member/VideoCloudTech", "name": "VideoCloudTech", "avatar": "https://cdn.v2ex.com/avatar/9612/8e04/513669_large.png?m=1610098421" }, "url": "t/762064", "title": "\u767d\u8bdd\u89e3\u8bfb WebRTC \u97f3\u9891 NetEQ \u53ca\u4f18\u5316\u5b9e\u8df5", "id": "t/762064", "date_published": "2021-03-16T03:58:39+00:00", "content_html": "

NetEQ \u662f WebRTC \u97f3\u89c6\u9891\u6838\u5fc3\u6280\u672f\u4e4b\u4e00\uff0c\u5bf9\u4e8e\u63d0\u9ad8 VoIP \u8d28\u91cf\u6709\u660e\u663e\u7684\u6548\u679c\uff0c\u672c\u6587\u5c06\u4ece\u66f4\u4e3a\u5b8f\u89c2\u7684\u89c6\u89d2\uff0c\u7528\u901a\u4fd7\u767d\u8bdd\u4ecb\u7ecd WebRTC \u4e2d\u97f3\u9891 NetEQ \u7684\u76f8\u5173\u6982\u5ff5\u80cc\u666f\u548c\u6846\u67b6\u539f\u7406\uff0c\u4ee5\u53ca\u76f8\u5173\u7684\u4f18\u5316\u5b9e\u8df5\u3002

\n

\u4f5c\u8005\uff5c \u826f\u9038
\n\u5ba1\u6821\uff5c \u6cf0\u4e00

\n

\u4e3a\u4ec0\u4e48\u8981 \u201c\u767d\u8bdd\u201d NetEQ?

\n

\u968f\u4fbf\u641c\u7d22\u4e00\u4e0b\uff0c\u6211\u4eec\u5c31\u80fd\u5728\u7f51\u4e0a\u627e\u5230\u5f88\u591a\u5173\u4e8e WebRTC \u4e2d\u97f3\u9891 NetEQ \u7684\u6587\u7ae0\uff0c\u6bd4\u5982\u4e0b\u9762\u7684\u51e0\u7bc7\u6587\u7ae0\u90fd\u662f\u975e\u5e38\u4e0d\u9519\u7684\u5b66\u4e60\u8d44\u6599\u548c\u53c2\u8003\u3002\u7279\u522b\u662f\u897f\u5b89\u7535\u5b50\u79d1\u6280\u5927\u5b66 2013 \u5e74\u5434\u6c5f\u9510\u7684\u7855\u58eb\u8bba\u6587\u300a WebRTC \u8bed\u97f3\u5f15\u64ce\u4e2d NetEQ \u6280\u672f\u7684\u7814\u7a76\u300b\uff0c\u975e\u5e38\u8be6\u5c3d\u5730\u4ecb\u7ecd\u4e86 NetEQ \u5b9e\u73b0\u7ec6\u8282\uff0c\u4e5f\u88ab\u5f15\u7528\u5230\u4e86\u5f88\u591a\u5f88\u591a\u7684\u6587\u7ae0\u4e2d\u3002

\n\n

\u8fd9\u4e9b\u6587\u7ae0\u5927\u90e8\u5206\u4ece\u6bd4\u8f83 \u201c\u5b66\u672f\u201d \u7684\u6216 \u201c\u7b97\u6cd5\u201d \u7684\u89d2\u5ea6\uff0c\u5bf9 NetEQ \u7684\u7ec6\u8282\u505a\u4e86\u975e\u5e38\u900f\u5f7b\u7684\u5206\u6790\uff0c\u6240\u4ee5\u8fd9\u91cc\u6211\u60f3\u4ece\u66f4\u5b8f\u89c2\u4e00\u4e9b\u7684\u89d2\u5ea6\uff0c\u8bf4\u4e00\u4e0b\u6211\u4e2a\u4eba\u7684\u7406\u89e3\u3002\u767d\u8bdd\u66f4\u5bb9\u6613\u88ab\u5927\u5bb6\u63a5\u53d7\uff0c\u4e89\u53d6\u4e00\u4e2a\u6570\u5b66\u516c\u5f0f\u90fd\u4e0d\u7528\uff0c\u4e00\u884c\u4ee3\u7801\u90fd\u4e0d\u4e0a\u5c31\u628a\u601d\u8def\u8bf4\u6e05\u695a\uff0c\u6709\u7406\u89e3\u4e0d\u5bf9\u7684\u5730\u65b9\uff0c\u8fd8\u8bf7\u5927\u5bb6\u4e0d\u541d\u8d50\u6559\u3002

\n

\u4e22\u5305\u3001\u6296\u52a8\u548c\u4f18\u5316\u7684\u7406\u89e3

\n

\u5728\u97f3\u89c6\u9891\u5b9e\u65f6\u901a\u4fe1\u9886\u57df\uff0c\u7279\u522b\u662f\u79fb\u52a8\u529e\u516c\uff08 4G \uff09\uff0c\u75ab\u60c5\u4e0b\u7684\u5c45\u5bb6\u529e\u516c\u548c\u5728\u7ebf\u8bfe\u5802 \uff08 WIFI \uff09\uff0c\u7f51\u7edc\u73af\u5883\u6210\u4e86\u5f71\u54cd\u97f3\u89c6\u9891\u8d28\u91cf\u6700\u5173\u952e\u7684\u56e0\u7d20\uff0c\u5728\u5dee\u7684\u7f51\u7edc\u8d28\u91cf\u9762\u524d\uff0c\u518d\u597d\u7684\u97f3\u89c6\u9891\u7b97\u6cd5\u90fd\u663e\u5f97\u6709\u4e9b\u676f\u6c34\u8f66\u85aa\u3002\u7f51\u7edc\u8d28\u91cf\u5dee\u7684\u8868\u73b0\u4e3b\u8981\u6709\u5ef6\u65f6\u3001\u4e71\u5e8f\u3001\u4e22\u5305\u3001\u6296\u52a8\uff0c\u8c01\u80fd\u5904\u7406\u548c\u5e73\u8861\u597d\u8fd9\u51e0\u7c7b\u95ee\u9898\uff0c\u8c01\u5c31\u80fd\u83b7\u5f97\u66f4\u597d\u7684\u97f3\u89c6\u9891\u4f53\u9a8c\u3002\u7531\u4e8e\u7f51\u7edc\u7684\u57fa\u7840\u5ef6\u65f6\u662f\u94fe\u8def\u7684\u9009\u62e9\u51b3\u5b9a\u7684\uff0c\u9700\u4f18\u5316\u94fe\u8def\u8c03\u5ea6\u5c42\u6765\u89e3\u51b3\uff1b\u800c\u4e71\u5e8f\u5728\u5927\u90e8\u5206\u7f51\u7edc\u6761\u4ef6\u4e0b\u5e76\u4e0d\u662f\u5f88\u591a\uff0c\u800c\u4e14\u4e71\u5e8f\u7684\u7a0b\u5ea6\u4e5f\u4e0d\u662f\u5f88\u4e25\u91cd\uff0c\u6240\u4ee5\u63a5\u4e0b\u6765\u6211\u4eec\u4e3b\u8981\u4f1a\u8ba8\u8bba\u4e22\u5305\u548c\u6296\u52a8\u3002

\n

\u6296\u52a8\u662f\u6570\u636e\u5728\u7f51\u7edc\u4e0a\u7684\u4f20\u8f93\u5ffd\u5feb\u5ffd\u6162\uff0c\u4e22\u5305\u662f\u6570\u636e\u5305\u7ecf\u8fc7\u7f51\u7edc\u4f20\u8f93\uff0c\u56e0\u4e3a\u5404\u79cd\u539f\u56e0\u88ab\u4e22\u6389\u4e86\uff0c\u7ecf\u8fc7\u51e0\u6b21\u91cd\u4f20\u540e\u88ab\u6210\u529f\u6536\u5230\u662f\u6062\u590d\u5305\uff0c\u91cd\u4f20\u4e5f\u5931\u8d25\u7684\u6216\u8005\u6062\u590d\u5305\u8fc7\u65f6\u7684\uff0c\u90fd\u4f1a\u5f62\u6210\u771f\u6b63\u7684\u4e22\u5305\uff0c\u9700\u8981\u4e22\u5305\u6062\u590d PLC \u7b97\u6cd5\u6765\u65e0\u4e2d\u751f\u6709\u7684\u4ea7\u751f\u4e00\u4e9b\u5047\u6570\u636e\u6765\u8865\u507f\u3002\u4e22\u5305\u548c\u6296\u52a8\u4ece\u65f6\u95f4\u7ef4\u5ea6\u4e0a\u53c8\u662f\u7edf\u4e00\u7684\uff0c\u7b49\u4e00\u4f1a\u6765\u4e86\u7684\u662f\u6296\u52a8\uff0c\u8fdf\u5230\u5f88\u4e45\u624d\u6765\u7684\u662f\u91cd\u4f20\u5305\uff0c\u7b49\u4e00\u8f88\u5b50\u4e5f\u4e0d\u6765\u7684\u5c31\u662f \u201c\u771f\u4e22\u5305\u201d\uff0c\u6211\u4eec\u7684\u76ee\u6807\u5c31\u662f\u8981\u5c3d\u91cf\u964d\u4f4e\u6570\u636e\u5305\u53d8\u6210 \u201c\u771f\u4e22\u5305\u201d \u7684\u6982\u7387\u3002

\n

\u4f18\u5316\uff0c\u76f4\u89c2\u6765\u8bb2\u5c31\u662f\u67d0\u4e2a\u6570\u636e\u6307\u6807\uff0c\u7ecf\u8fc7\u4e00\u987f\u731b\u5982\u864e\u7684\u64cd\u4f5c\u4e4b\u540e\uff0c\u4ece xxx \u63d0\u5347\u5230\u4e86 xxx \u3002\u4f46\u6211\u89c9\u5f97\uff0c\u8bc4\u5224\u4f18\u5316\u597d\u574f\u4e0d\u80fd\u4ec5\u4ec5\u505c\u7559\u5728\u8fd9\u4e2a\u7ef4\u5ea6\uff0c\u4f18\u5316\u662f\u8981 \u201c\u77e5\u5df1\u77e5\u5f7c\u201d\uff0c\u5df1\u662f\u81ea\u5df1\u7684\u4ea7\u54c1\u9700\u6c42\uff0c\u5f7c\u662f\u73b0\u6709\u7b97\u6cd5\u7684\u80fd\u529b\uff0c\u5df1\u5f7c\u5408\u4e00\u624d\u662f\u6700\u597d\u7684\u4f18\u5316\uff0c\u4e0d\u7ba1\u7b97\u6cd5\u662f\u7b80\u5355\u8fd8\u662f\u590d\u6742\uff0c\u53ea\u8981\u80fd\u5b8c\u7f8e\u7684\u5339\u914d\u81ea\u5df1\u7684\u4ea7\u54c1\u9700\u6c42\uff0c\u5c31\u662f\u6700\u597d\u7684\u7b97\u6cd5\uff0c\u201c\u80fd\u6349\u5230\u8001\u9f20\u7684\u5c31\u662f\u597d\u732b\u201d\u3002

\n

NetEQ \u53ca\u76f8\u5173\u6a21\u5757

\n

NetEQ \u7684\u51fa\u5904

\n

\u300a GIPS NetEQ \u539f\u59cb\u6587\u6863\u300b\uff0c\u8fd9\u662f\u7531 GIPS \u516c\u53f8\u63d0\u4f9b\u7684\u6700\u539f\u59cb\u7684 NetEQ \u7684\u8bf4\u660e\u6587\u6863\uff08\u4e2d\u6587\u7ffb\u8bd1\uff09\uff0c\u91cc\u9762\u4ecb\u7ecd\u4e86\u4ec0\u4e48\u662f NetEQ \u4ee5\u53ca\u5bf9\u5176\u6027\u80fd\u7684\u7b80\u5355\u8bf4\u660e\u3002NetEQ \u672c\u8d28\u4e0a\u5c31\u662f\u4e00\u4e2a\u97f3\u9891\u7684 JitterBuffer \uff08\u6296\u52a8\u7f13\u51b2\u5668\uff09\uff0c\u540d\u5b57\u8d77\u7684\u975e\u5e38\u8d34\u5207\uff0cNetwork Equalizer \uff08\u7f51\u7edc\u5747\u8861\u5668\uff09\u3002\u5927\u5bb6\u90fd\u77e5\u9053 Audio Equalizer \u662f\u7528\u6765\u5747\u8861\u58f0\u97f3\u7684\u6548\u679c\u5668\uff0c\u800c\u8fd9\u91cc\u7684 NetEQ \u662f\u7528\u6765\u5747\u8861\u7f51\u7edc\u6296\u52a8\u7684\u6548\u679c\u5668\u3002\u800c\u4e14 GIPS \u8fd8\u7ed9\u8fd9\u4e2a\u540d\u5b57\u6ce8\u518c\u4e86\u5546\u6807\uff0c\u6240\u4ee5\u5f88\u591a\u5730\u65b9\u770b\u5230\u7684\u662f NetEQ (TM) \u3002\n\u4e0a\u9762\u7684\u5b98\u65b9\u6587\u6863\u4e2d\uff0c\u6709\u4e00\u6761\u5f88\u91cd\u8981\u4fe1\u606f\uff0c\u201c\u6700\u5c0f\u5316\u6296\u52a8\u7f13\u51b2\u5e26\u6765\u7684\u5ef6\u65f6\u5f71\u54cd\u201d\uff0c\u8fd9\u8bf4\u660e NetEQ \u7684\u8bbe\u8ba1\u76ee\u6807\u4e4b\u4e00\u5c31\u662f\uff1a\u201c\u8ffd\u6c42\u6781\u4f4e\u5ef6\u65f6\u201d\u3002\u8fd9\u4e2a\u4fe1\u606f\u5f88\u5173\u952e\uff0c\u4e3a\u6211\u4eec\u540e\u7eed\u7684\u4f18\u5316\u63d0\u4f9b\u4e86\u91cd\u8981\u7ebf\u7d22\u3002
\n\"\"\n\"\"\n\"\"

\n

NetEQ \u5728\u97f3\u89c6\u9891\u901a\u8baf QoS \u6d41\u7a0b\u4e2d\u7684\u4f4d\u7f6e

\n

\u97f3\u89c6\u9891\u901a\u8baf\u5bf9\u4e8e\u666e\u901a\u7528\u6237\u6765\u8bf4\uff0c\u53ea\u8981\u7f51\u7edc\u662f\u901a\u7684\uff0cWIFI \u548c 4G \u90fd\u53ef\u4ee5\uff0c\u4e00\u4e2a\u547c\u53eb\u8fc7\u53bb\uff0c\u770b\u5230\u4eba\u4e14\u542c\u5230\u58f0\u97f3\uff0c\u5c31 OK \u4e86\uff0c\u5f88\u7b80\u5355\u7684\u4e8b\u60c5\uff0c\u4f46\u5bf9\u4e8e\u5e95\u5c42\u7684\u5b9e\u73b0\u5374\u6ca1\u6709\u770b\u8d77\u6765\u90a3\u4e48\u7b80\u5355\u3002\u5355 WebRTC \u5f00\u6e90\u5f15\u64ce\u7684\u76f8\u5173\u4ee3\u7801\u6587\u4ef6\u6570\u91cf\u5c31\u6709 20 \u4e07\u4e2a\u5de6\u53f3\uff0c\u4ee3\u7801\u884c\u6570\u4e0d\u77e5\u9053\u6709\u6ca1\u6709\u4eba\u5177\u4f53\u7b97\u8fc7\uff0c\u5e94\u8be5\u4e5f\u662f\u5343\u4e07\u6570\u91cf\u7ea7\u7684\u4e86\u3002\u4e0d\u77e5\u9053\u591a\u5c11\u7801\u519c\u4e3a\u6b64\u6389\u5149\u4e86\u5934\u53d1 :)\u3002

\n

\u4e0b\u9762\u8fd9\u5f20\u56fe\uff0c\u662f\u5bf9\u5b9e\u9645\u4e0a\u66f4\u590d\u6742\u7684\u97f3\u89c6\u9891\u901a\u8baf\u6d41\u7a0b\u7684\u62bd\u8c61\u548c\u7b80\u5316\u3002\u5de6\u8fb9\u662f\u53d1\u9001 (\u63a8\u6d41) \u4fa7\uff1a\u7ecf\u8fc7\u91c7\u96c6\u3001\u7f16\u7801\u3001\u5c01\u88c5\u3001\u53d1\u9001\uff1b\u4e2d\u95f4\u7ecf\u8fc7\u7f51\u7edc\u4f20\u8f93\uff1b\u53f3\u8fb9\u662f\u63a5\u6536 (\u62c9\u6d41) \u4fa7\uff1a\u63a5\u6536\u3001\u89e3\u5305\u3001\u89e3\u7801\u3001\u64ad\u653e\uff1b\u8fd9\u91cc\u91cd\u70b9\u4f53\u73b0\u4e86 QoS \uff08 Quality of Service\uff0c\u670d\u52a1\u8d28\u91cf\uff09\u7684\u51e0\u4e2a\u5927\u7684\u529f\u80fd\uff0c\u4ee5\u53ca\u8ddf\u63a8\u62c9\u6d41\u6570\u636e\u4e3b\u8981\u6d41\u7a0b\u7684\u5173\u7cfb\u3002\u53ef\u4ee5\u770b\u5230 QoS \u529f\u80fd\u5206\u6563\u5728\u97f3\u89c6\u9891\u901a\u8baf\u6d41\u7a0b\u4e2d\u7684\u5404\u4e2a\u4f4d\u7f6e\uff0c\u5bfc\u81f4\u8981\u4e86\u89e3\u6574\u4e2a\u6d41\u7a0b\u4e4b\u540e\u624d\u80fd\u5bf9 QoS \u6709\u6bd4\u8f83\u5168\u9762\u7684\u7406\u89e3\u3002\u56fe\u4e0a\u770b\u8d77\u6765\u5de6\u8fb9\u53d1\u9001\u4fa7\u7684 QoS \u529f\u80fd\u8981\u591a\u4e00\u4e9b\uff0c\u8fd9\u662f\u56e0\u4e3a QoS \u7684\u76ee\u7684\u5c31\u662f\u8981\u89e3\u51b3\u901a\u8baf\u8fc7\u7a0b\u4e2d\u7684\u7528\u6237\u4f53\u9a8c\u95ee\u9898\uff0c\u8981\u89e3\u51b3\u95ee\u9898\uff0c\u6700\u597d\u5c31\u662f\u627e\u5230\u95ee\u9898\u7684\u6e90\u5934\uff0c\u80fd\u4ece\u6e90\u5934\u89e3\u51b3\u7684\uff0c\u90fd\u662f\u6bd4\u8f83\u597d\u7684\u89e3\u51b3\u65b9\u5f0f\u3002\u4f46\u603b\u6709\u4e00\u90e8\u5206\u95ee\u9898\u662f\u4e0d\u80fd\u4ece\u6e90\u5934\u6765\u89e3\u51b3\u7684\uff0c\u6bd4\u5982\u5728\u591a\u4eba\u4f1a\u8bae\u7684\u573a\u666f\uff0c\u4e00\u4e2a\u4eba\u7684\u6536\u6d41\u4fa7\u7f51\u7edc\u574f\u4e86\uff0c\u4e0d\u80fd\u5f71\u54cd\u5176\u5b83\u4eba\u7684\u5f00\u4f1a\u4f53\u9a8c\uff0c\u4e0d\u80fd\u51fa\u73b0 \u201c\u4e00\u9897\u8001\u9f20\u5c4e\u574f\u6389\u4e00\u9505\u7ca5\u201d \u7684\u60c5\u51b5\uff0c\u4e0d\u80fd\u6c61\u67d3\u6e90\u5934\u3002\u6240\u4ee5\u6536\u6d41\u4e5f\u8981\u505a QoS \u7684\u529f\u80fd\uff0c\u76ee\u524d\u6536\u6d41\u4fa7\u7684\u5fc5\u5907\u529f\u80fd\u5c31\u662f JitterBuffer\uff0c\u5305\u62ec\u89c6\u9891\u7684\u548c\u97f3\u9891\u7684\uff0c\u672c\u6587\u91cd\u70b9\u5206\u6790\u97f3\u9891\u7684 JitterBuffer -- NetEQ \u3002\n\"\"

\n

NetEQ \u539f\u7406\u53ca\u76f8\u5173\u6a21\u5757\u7684\u5173\u7cfb

\n

\"\"\n\u4e0a\u9762\u8fd9\u5f20\u56fe\u662f\u5bf9 NetEQ \u53ca\u5176\u76f8\u5173\u6a21\u5757\u5de5\u4f5c\u6d41\u7a0b\u7684\u62bd\u8c61\uff0c\u4e3b\u8981\u5305\u542b 4 \u4e2a\u90e8\u5206\uff0cNetEQ \u7684\u8f93\u5165\u3001NetEQ \u7684\u8f93\u51fa\u3001\u97f3\u9891\u91cd\u4f20 Nack \u8bf7\u6c42\u6a21\u5757\u3001\u97f3\u89c6\u9891\u540c\u6b65\u6a21\u5757\u3002\u4e3a\u4ec0\u4e48\u8981\u628a Nack \u8bf7\u6c42\u6a21\u5757\u548c\u97f3\u89c6\u9891\u540c\u6b65\u6a21\u5757\u4e5f\u653e\u8fdb NetEQ \u7684\u5206\u6790\u4e2d\uff1f\u56e0\u4e3a\u8fd9\u4e24\u4e2a\u6a21\u5757\u90fd\u76f4\u63a5\u8ddf NetEQ \u6709\u4f9d\u8d56\uff0c\u76f8\u4e92\u5f71\u54cd\u3002\u56fe\u91cc\u9762\u7684\u865a\u7ebf\uff0c\u6807\u8bc6\u6bcf\u4e2a\u6a21\u5757\u4f9d\u8d56\u7684\u5176\u5b83\u6a21\u5757\u7684\u4fe1\u606f\uff0c\u4ee5\u53ca\u8fd9\u4e9b\u4fe1\u606f\u7684\u6765\u6e90\u3002\u63a5\u4e0b\u6765\u4ecb\u7ecd\u4e00\u4e0b\u6574\u4e2a\u6d41\u7a0b\u3002

\n

1. \u9996\u5148\u662f NetEQ \u7684\u8f93\u5165\u90e8\u5206\uff1a

\n

\u5e95\u5c42 Socket \u6536\u5230\u4e00\u4e2a UDP \u5305\u540e\uff0c\u89e6\u53d1\u4ece UDP \u5305\u5230 RTP \u5305\u7684\u89e3\u6790\uff0c\u7ecf\u8fc7\u5bf9 SSRC \u548c PayloadType \u7684\u5339\u914d\uff0c\u627e\u5230\u5bf9\u5e94\u7684\u97f3\u9891\u6d41\u63a5\u6536\u7684 Channel\uff0c\u7136\u540e\u4ece InsertPacketInternal \u8f93\u5165\u5230 NetEQ \u7684\u63a5\u6536\u6a21\u5757\u4e2d\u3002

\n

\u6536\u5230\u7684\u97f3\u9891 RTP \u5305\u5f88\u53ef\u80fd\u4f1a\u5e26\u6709 RED \u5197\u4f59\u5305\uff08 redundance \uff09\uff0c\u6309\u7167 RFC2198 \u7684\u6807\u51c6\u6216\u8005\u4e00\u4e9b\u79c1\u6709\u7684\u5c01\u88c5\u683c\u5f0f\uff0c\u5bf9\u5176\u8fdb\u884c\u89e3\u5305\uff0c\u8fd8\u539f\u51fa\u539f\u59cb\u5305\uff0c\u91cd\u590d\u7684\u539f\u59cb\u5305\u5c06\u4f1a\u88ab\u5ffd\u7565\u6389\u3002\u89e3\u51fa\u6765\u7684\u539f\u59cb RTP \u6570\u636e\u5305\u4f1a\u88ab\u6309\u4e00\u5b9a\u7684\u7b97\u6cd5\u63d2\u5165\u5230 packet buffer \u7f13\u5b58\u91cc\u9762\u53bb\u3002\u4e4b\u540e\u4f1a\u5c06\u6536\u5230\u7684\u6bcf\u4e00\u4e2a\u539f\u59cb\u5305\u7684\u5e8f\u5217\u53f7\uff0c\u901a\u8fc7 UpdateLastReceivedPacket \u51fd\u6570\u66f4\u65b0\u5230 Nack \u91cd\u4f20\u8bf7\u6c42\u6a21\u5757\uff0cNack \u6a21\u5757\u4f1a\u901a\u8fc7 RTP \u6536\u5305\u6216\u5b9a\u65f6\u5668\u89e6\u53d1\u4e24\u79cd\u6a21\u5f0f\uff0c\u8c03\u7528 GetNackList \u51fd\u6570\u6765\u751f\u6210\u91cd\u4f20\u8bf7\u6c42\uff0c\u4ee5 NACK RTCP \u5305\u7684\u683c\u5f0f\u53d1\u9001\u7ed9\u63a8\u6d41\u4fa7\u3002

\n

\u540c\u65f6\uff0c\u89e3\u5b8c\u7684\u6bcf\u4e00\u4e2a\u539f\u59cb\u5305\uff0c\u5f97\u5230\u4e86\u65f6\u95f4\u8f74\u4e0a\u552f\u4e00\u7684\u4e00\u4e2a\u63a5\u6536\u65f6\u523b\uff0c\u5305\u548c\u5305\u4e4b\u95f4\u7684\u63a5\u6536\u65f6\u95f4\u5dee\u4e5f\u80fd\u7b97\u51fa\u6765\u4e86\uff0c\u8fd9\u4e2a\u63a5\u6536\u65f6\u95f4\u5dee\u9664\u4ee5\u6bcf\u4e2a\u5305\u7684\u6253\u5305\u65f6\u957f\u5c31\u662f NetEQ \u5185\u90e8\u7528\u6765\u505a\u6296\u52a8\u4f30\u8ba1\u7684 IAT \uff08 interarrival time \uff09\uff0c\u6bd4\u5982\uff0c\u4e24\u4e2a\u5305\u65f6\u95f4\u5dee\u662f 120ms\uff0c\u800c\u6253\u5305\u65f6\u957f\u662f 20ms\uff0c\u5219\u5f53\u524d\u5305\u7684 IAT \u503c\u5c31\u662f 120/20=6 \u3002\u4e4b\u540e\u6bcf\u4e2a\u5305\u7684 IAT \u503c\u7ecf\u8fc7\u6838\u5fc3\u7684\u7f51\u7edc\u6296\u52a8\u4f30\u8ba1\u6a21\u5757\uff08 DelayManager \uff09\u5904\u7406\u4e4b\u540e\uff0c\u5f97\u5230\u6700\u7ec8\u7684\u76ee\u6807\u6c34\u4f4d\uff08 TargetLevel \uff09\uff0c\u5230\u6b64 NetEQ \u7684\u8f93\u5165\u5904\u7406\u90e8\u5206\u5c31\u7ed3\u675f\u4e86\u3002

\n

2. \u5176\u6b21\u662f NetEQ \u7684\u8f93\u51fa\u90e8\u5206\uff1a

\n

\u8f93\u51fa\u662f\u7531\u97f3\u9891\u786c\u4ef6\u64ad\u653e\u8bbe\u5907\u7684\u64ad\u653e\u7ebf\u7a0b\u5b9a\u65f6\u89e6\u53d1\u7684\uff0c\u64ad\u653e\u8bbe\u5907\u4f1a\u6bcf 10ms \u901a\u8fc7 GetAudioInternal \u63a5\u53e3\u4ece NetEQ \u91cc\u9762\u53d6 10ms \u957f\u5ea6\u7684\u6570\u636e\u6765\u64ad\u653e\u3002

\n

\u8fdb\u5165 GetAudioInternal \u7684\u51fd\u6570\u4e4b\u540e\uff0c\u7b2c\u4e00\u6b65\u8981\u51b3\u7b56\u5982\u4f55\u5e94\u5bf9\u5f53\u524d\u6570\u636e\u8bf7\u6c42\uff0c\u8fd9\u4e2a\u4efb\u52a1\u4ea4\u7ed9\u64cd\u4f5c\u51b3\u7b56\u6a21\u5757\u6765\u5b8c\u6210\uff0c\u51b3\u7b56\u6a21\u5757\u6839\u636e\u4e4b\u524d\u7684\u548c\u5f53\u524d\u7684\u6570\u636e\u548c\u64cd\u4f5c\u7684\u72b6\u6001\uff0c\u7ed9\u51fa\u6700\u7ec8\u7684\u64cd\u4f5c\u7c7b\u578b\u5224\u65ad\u3002NetEQ \u91cc\u9762\u5b9a\u4e49\u4e86\u51e0\u79cd\u64cd\u4f5c\u7c7b\u578b\uff1a\u6b63\u5e38\u3001\u52a0\u901f\u3001\u51cf\u901f\u3001\u878d\u5408\u3001\u62c9\u4f38\uff08\u4e22\u5305\u8865\u507f\uff09\u3001\u9759\u97f3\uff0c\u8fd9\u51e0\u79cd\u64cd\u4f5c\u7684\u610f\u4e49\uff0c\u540e\u9762\u518d\u8be6\u7ec6\u7684\u8bf4\u3002\u6709\u4e86\u51b3\u7b56\u7684\u64cd\u4f5c\u7c7b\u578b\uff0c\u518d\u4ece\u8f93\u5165\u90e8\u5206\u7684\u5305\u7f13\u5b58\uff08 packet buffer \uff09\u91cc\u9762\u53d6\u51fa\u4e00\u4e2a RTP \u5305\uff0c\u9001\u7ed9\u62bd\u8c61\u7684\u89e3\u7801\u5668\uff0c\u62bd\u8c61\u7684\u89e3\u7801\u5668\u901a\u8fc7 DecodeLoop \u51fd\u6570\u5c42\u5c42\u8c03\u7528\u5230\u771f\u6b63\u7684\u89e3\u7801\u5668\u8fdb\u884c\u89e3\u7801\uff0c\u5e76\u628a\u89e3\u7801\u540e\u7684 PCM \u97f3\u9891\u6570\u636e\u653e\u5230 DecodedBuffer \u91cc\u9762\u53bb\u3002\u7136\u540e\u5c31\u662f\u5f00\u59cb\u6267\u884c\u4e0d\u540c\u7684\u64cd\u4f5c\u4e86\uff0cNetEQ \u91cc\u9762\u4e3a\u6bcf\u4e00\u79cd\u64cd\u4f5c\u90fd\u5b9e\u73b0\u4e86\u4e0d\u540c\u7684\u97f3\u9891\u6570\u5b57\u4fe1\u53f7\u5904\u7406\u7b97\u6cd5\uff08 DSP \uff09\uff0c\u9664\u4e86 \u201c\u6b63\u5e38\u201d \u64cd\u4f5c\u4f1a\u76f4\u63a5\u4f7f\u7528 DecodedBuffer \u91cc\u7684\u89e3\u7801\u6570\u636e\uff0c\u5176\u5b83\u64cd\u4f5c\u90fd\u4f1a\u7ed3\u5408\u89e3\u7801\u7684\u6570\u636e\u8fdb\u884c\u4e8c\u6b21 DSP \u5904\u7406\uff0c\u5904\u7406\u7ed3\u679c\u4f1a\u5148\u88ab\u653e\u5230\u7b97\u6cd5\u7f13\u5b58\uff08 Algorithm Buffer \uff09\u91cc\u9762\u53bb\uff0c\u7136\u540e\u518d\u63d2\u5165\u5230 Sync Buffer \u91cc\u9762\u3002Sync Buffer \u662f\u4e00\u4e2a\u5faa\u73af buffer\uff0c\u8bbe\u8ba1\u7684\u6bd4\u8f83\u5de7\u5999\uff0c\u5b58\u653e\u4e86\u5df2\u7ecf\u64ad\u653e\u8fc7\u7684\u6570\u636e\u3001\u89e3\u7801\u540e\u672a\u64ad\u653e\u7684\u6570\u636e\uff0c\u521a\u521a\u4ece\u7b97\u6cd5\u7f13\u5b58\u91cc\u63d2\u5165\u7684\u6570\u636e\u653e\u5728 Sync Buffer \u7684\u672b\u5c3e\uff0c\u5982\u4e0a\u56fe\u6240\u793a\u3002\u6700\u540e\u5c31\u662f\u4ece Sync Buffer \u53d6\u51fa\u6700\u65e9\u89e3\u7801\u540e\u7684\u6570\u636e\uff0c\u9001\u51fa\u53bb\u7ed9\u5916\u90e8\u7684\u6df7\u97f3\u6a21\u5757\uff0c\u6df7\u97f3\u4e4b\u540e\u518d\u9001\u5230\u97f3\u9891\u786c\u4ef6\u6765\u64ad\u653e\u3002

\n

\u53e6\u5916\uff0c\u4ece\u56fe\u4e0a\u53ef\u4ee5\u770b\u51fa\u51b3\u7b56\u6a21\u5757\uff08 BufferLevelFilter \uff09\u4f1a\u7ed3\u5408\u5f53\u524d\u5305\u7f13\u5b58 packet buffer \u91cc\u7f13\u5b58\u7684\u65f6\u957f\uff0c\u548c Sync Buffer \u91cc\u7f13\u5b58\u7684\u6570\u636e\u65f6\u957f\uff0c\u7ecf\u8fc7\u7b97\u6cd5\u8fc7\u6ee4\u540e\u5f97\u5230\u97f3\u9891\u5f53\u524d\u7684\u7f13\u5b58\u6c34\u4f4d\u3002\u97f3\u89c6\u9891\u540c\u6b65\u6a21\u5757\u4f1a\u4f7f\u7528\u5f53\u524d\u97f3\u9891\u7f13\u5b58\u6c34\u4f4d\uff0c\u548c\u89c6\u9891\u5f53\u524d\u7f13\u5b58\u6c34\u4f4d\uff0c\u7ed3\u5408\u6700\u65b0 RTP \u5305\u7684\u65f6\u95f4\u6233\u548c\u97f3\u89c6\u9891\u7684 SR \u5305\u83b7\u5f97\u7684\u65f6\u95f4\u6233\uff0c\u8ba1\u7b97\u51fa\u97f3\u89c6\u9891\u7684\u4e0d\u540c\u6b65\u7a0b\u5ea6\uff0c\u518d\u901a\u8fc7 SetMinimumPlayoutDelay \u6700\u7ec8\u8bbe\u7f6e\u5230 NetEQ \u91cc\u9762\u7684\u6700\u5c0f\u76ee\u6807\u6c34\u4f4d\uff0c\u6765\u63a7\u5236 TargetLevel\uff0c\u5b9e\u73b0\u97f3\u89c6\u9891\u540c\u6b65\u3002

\n

NetEQ \u5185\u90e8\u6a21\u5757

\n

NetEQ \u6296\u52a8\u4f30\u8ba1\u6a21\u5757\uff08 DelayManager \uff09

\n

1. \u5e73\u7a33\u6296\u52a8\u4f30\u8ba1\u90e8\u5206\uff1a

\n

\u5c06\u6bcf\u4e2a\u5305\u7684 IAT \u503c\uff0c\u6309\u7167\u4e00\u5b9a\u7684\u6bd4\u4f8b\uff08\u53d6\u591a\u5c11\u6bd4\u4f8b\u662f\u7531\u4e0b\u9762\u7684\u9057\u5fd8\u56e0\u5b50\u90e8\u5206\u7684\u8ba1\u7b97\u51b3\u5b9a\u7684\uff09\uff0c\u7d2f\u52a0\u5230\u4e0b\u9762\u7684 IAT \u7edf\u8ba1\u7684\u76f4\u65b9\u56fe\u91cc\u9762\uff0c\u6700\u540e\u8ba1\u7b97\u4ece\u5de6\u5f80\u53f3\u7d2f\u52a0\u503c\u7684 0.95 \u4f4d\u7f6e\uff0c\u6b64\u4f4d\u7f6e\u7684 IAT \u503c\u4f5c\u4e3a\u6700\u540e\u7684\u6296\u52a8 IAT \u4f30\u8ba1\u503c\u3002\u4f8b\u5982\u4e0b\u56fe\uff0c\u5047\u5b9a\u76ee\u6807\u6c34\u4f4d TargetLevel \u662f 9\uff0c\u610f\u5473\u7740\u76ee\u6807\u7f13\u5b58\u6570\u636e\u65f6\u957f\u5c06\u4f1a\u662f 180ms \uff08\u5047\u5b9a\u6253\u5305\u65f6\u957f 20ms \uff09\u3002

\n

\"\"

\n

2. \u5e73\u7a33\u6296\u52a8\u9057\u5fd8\u56e0\u5b50\u8ba1\u7b97\uff1a

\n

\u9057\u5fd8\u56e0\u5b50\u662f\u7528\u6765\u63a7\u5236\u5f53\u524d\u5305\u7684 IAT \u503c\u53d6\u591a\u5c11\u6bd4\u4f8b\u7d2f\u52a0\u5230\u4e0a\u9762\u7684\u76f4\u65b9\u56fe\u91cc\u9762\u53bb\u7684\u7cfb\u6570\uff0c\u8ba1\u7b97\u8fc7\u7a0b\u7528\u4e86\u4e00\u4e2a\u770b\u8d77\u6765\u6bd4\u8f83\u590d\u6742\u7684\u516c\u5f0f\uff0c\u7ecf\u8fc7\u5206\u6790\uff0c\u5176\u672c\u8d28\u5c31\u662f\u4e0b\u9762\u7684\u9ec4\u8272\u66f2\u7ebf\uff0c\u610f\u601d\u662f\u5f00\u59cb\u7684\u65f6\u5019\u9057\u5fd8\u56e0\u5b50\u5c0f\uff0c\u4f1a\u53d6\u66f4\u591a\u7684\u5f53\u524d\u5305\u7684 IAT \u503c\u6765\u7d2f\u52a0\uff0c\u968f\u7740\u65f6\u95f4\u63a8\u79fb\uff0c\u9057\u5fd8\u56e0\u5b50\u9010\u6e10\u53d8\u5927\uff0c\u4f1a\u53d6\u66f4\u5c11\u7684\u5f53\u524d\u5305 IAT \u503c\u6765\u7d2f\u52a0\u3002\u8fd9\u4e2a\u8fc7\u7a0b\u641e\u7684\u6709\u70b9\u590d\u6742\uff0c\u4ece\u5de5\u7a0b\u89d2\u5ea6\u770b\u5b8c\u5168\u53ef\u4ee5\u7b80\u5316\u6210\u76f4\u7ebf\u4e4b\u7c7b\u7684\uff0c\u56e0\u4e3a\u6d4b\u8bd5\u4e0b\u6765 5s \u5de6\u53f3\u7684\u65f6\u95f4\uff0c\u57fa\u672c\u5c31\u6536\u655b\u5230\u76ee\u6807\u503c 0.9993 \u4e86\uff0c\u5176\u5b9e\u8fd9\u4e2a 0.9993 \u624d\u662f\u5f71\u54cd\u6296\u52a8\u4f30\u8ba1\u7684\u6700\u4e3b\u8981\u7684\u56e0\u7d20\uff0c\u5f88\u591a\u4f18\u5316\u4e5f\u662f\u76f4\u63a5\u4fee\u6539\u8fd9\u4e2a\u7cfb\u6570\u6765\u8c03\u8282\u4f30\u8ba1\u7684\u7075\u654f\u5ea6\u3002\n\"\"

\n

3. \u5cf0\u503c\u6296\u52a8\u4f30\u8ba1\uff1a

\n

DelayManager \u4e2d\u6709\u4e00\u4e2a\u5cf0\u503c\u68c0\u6d4b\u5668 PeakDetector \u7528\u6765\u8bc6\u522b\u5cf0\u503c\uff0c\u5982\u679c\u9891\u7e41\u68c0\u6d4b\u5230\u5cf0\u503c\uff0c\u4f1a\u8fdb\u5165\u5cf0\u503c\u6296\u52a8\u7684\u4f30\u8ba1\u72b6\u6001\uff0c\u53d6\u6700\u5927\u7684\u5cf0\u503c\u4f5c\u4e3a\u6700\u7ec8\u4f30\u8ba1\u7ed3\u679c\uff0c\u800c\u4e14\u4e00\u65e6\u8fdb\u5165\u8fd9\u4e2a\u72b6\u6001\u4f1a\u4e00\u76f4\u7ef4\u6301 20s \u65f6\u95f4\uff0c\u4e0d\u7ba1\u5f53\u524d\u6296\u52a8\u662f\u5426\u5df2\u7ecf\u6062\u590d\u6b63\u5e38\u4e86\u3002\u4e0b\u9762\u662f\u4e00\u4e2a\u793a\u610f\u56fe\u3002\n\"\"

\n

NetEQ \u64cd\u4f5c\u51b3\u7b56\u6a21\u5757\uff08 DecisionLogic \uff09

\n

\u51b3\u7b56\u6a21\u5757\u7684\u7b80\u5316\u540e\u7684\u57fa\u672c\u5224\u5b9a\u903b\u8f91\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff0c\u6bd4\u8f83\u7b80\u6d01\u4e0d\u7528\u89e3\u91ca\u3002\u8fd9\u91cc\u89e3\u91ca\u4e00\u4e0b\u4e0b\u9762\u8fd9\u51e0\u4e2a\u64cd\u4f5c\u7c7b\u578b\u7684\u610f\u4e49\uff1a

\n\n

NetEQ \u76f8\u5173\u6a21\u5757\u4f18\u5316\u70b9

\n

NetEQ \u6297\u6296\u52a8\u4f18\u5316

\n
    \n
  1. \u7531\u4e8e NetEQ \u7684\u8bbe\u8ba1\u76ee\u6807\u662f \u201c\u6781\u4f4e\u5ef6\u65f6\u201d\uff0c\u4e0d\u80fd\u5f88\u597d\u7684\u5339\u914d\uff0c\u89c6\u9891\u4f1a\u8bae\uff0c\u5728\u7ebf\u8bfe\u5802\uff0c\u76f4\u64ad\u8fde\u9ea6\u7b49\u975e\u6781\u4f4e\u5ef6\u65f6\u573a\u666f\uff0c\u9700\u8981\u5bf9\u5176\u654f\u611f\u5ea6\u8fdb\u884c\u8c03\u6574\uff0c\u4e3b\u8981\u8c03\u6574\u6296\u52a8\u4f30\u8ba1\u6a21\u5757\u76f8\u5173\u7684\u7075\u654f\u5ea6\uff1b
  2. \n
  3. \u76f4\u64ad\u573a\u666f\uff0c\u7531\u4e8e\u5bf9\u4e8e\u5ef6\u65f6\u654f\u611f\u5ea6\u53ef\u4ee5\u5230\u79d2\u7ea7\u4ee5\u4e0a\uff0c\u6240\u4ee5\u9700\u8981\u542f\u7528 StreamMode \u7684\u529f\u80fd\uff08\u65b0\u7248\u672c\u4e2d\u597d\u50cf\u53bb\u6389\u4e86\uff09\uff0c\u800c\u4e14\u4e5f\u9700\u8981\u5bf9\u5176\u4e2d\u53c2\u6570\u8fdb\u884c\u9002\u914d\uff1b
  4. \n
  5. \u670d\u52a1\u4e8e\u6781\u4f4e\u5ef6\u65f6\u76ee\u6807\uff0c\u539f\u59cb\u7684\u5305\u7f13\u5b58 packetbuffer \u592a\u5c0f\uff0c\u5bb9\u6613\u9020\u6210 flush\uff0c\u9700\u8981\u6309\u4e1a\u52a1\u9700\u8981\u8c03\u5927\u4e00\u4e9b\uff1b
  6. \n
  7. \u8fd8\u6709\u4e00\u4e9b\u4e1a\u52a1\u4f1a\u6839\u636e\u81ea\u5df1\u7684\u4e1a\u52a1\u573a\u666f\u4e3b\u52a8\u8bc6\u522b\u7f51\u7edc\u72b6\u51b5\uff0c\u7136\u540e\u76f4\u63a5\u8bbe\u7f6e\u6700\u5c0f TargetLevel\uff0c\u7b80\u5355\u7c97\u66b4\u7684\u63a7\u5236 NetEQ \u7684\u6c34\u4f4d\u3002\n\"\"
  8. \n
\n

NetEQ \u6297\u4e22\u5305\u4f18\u5316\uff1a

\n
    \n
  1. \u539f\u59cb\u7684 WebRTC \u7684 Nack \u4e22\u5305\u8bf7\u6c42\u7684\u89e6\u53d1\u673a\u5236\u662f\u7528\u5305\u89e6\u53d1\u7684\uff0c\u5728\u5f31\u7f51\u4e0b\u4f1a\u6076\u5316\u91cd\u4f20\u6548\u679c\uff0c\u53ef\u4ee5\u6539\u4e3a\u5b9a\u65f6\u89e6\u53d1\u6765\u89e3\u51b3\uff1b
  2. \n
  3. \u4e22\u5305\u573a\u666f\u4f1a\u6709\u91cd\u4f20\uff0c\u4f46\u5982\u679c buffer \u592a\u5c0f\uff0c\u91cd\u4f20\u4e5f\u4f1a\u88ab\u4e22\u5f03\uff0c\u6240\u4ee5\u4e3a\u4e86\u63d0\u9ad8\u91cd\u4f20\u6548\u7387\uff0c\u589e\u52a0 ARQ \u5ef6\u65f6\u9884\u7559\u529f\u80fd\uff0c\u53ef\u660e\u663e\u964d\u4f4e\u62c9\u4f38\u7387\uff1b
  4. \n
  5. \u6bd4\u8f83\u7b97\u6cd5\u7ea7\u7684\u4f18\u5316\u662f\u5bf9\u4e22\u5305\u8865\u507f PLC \u7b97\u6cd5\u7684\u4f18\u5316\uff0c\u8c03\u6574\u73b0\u6709 NetEQ \u7684\u62c9\u4f38\u673a\u5236\uff0c\u4f18\u5316\u542c\u611f\u6548\u679c\uff1b
  6. \n
  7. \u5f00\u542f Opus \u7684 Dtx \u529f\u80fd\u4e4b\u540e\uff0c\u5728\u4e22\u5305\u573a\u666f\u4f1a\u5bfc\u81f4\u97f3\u9891 Buffer \u53d8\u5927\uff0c\u9700\u8981\u5355\u72ec\u4f18\u5316 Dtx \u76f8\u5173\u5904\u7406\u903b\u8f91\u3002\n\"\"\n\u4e0b\u9762\u662f ARQ \u5ef6\u65f6\u9884\u7559\u529f\u80fd\u5f00\u542f\u540e\u7684\u6548\u679c\u5bf9\u6bd4\uff0c\u5e73\u5747\u62c9\u4f38\u7387\u964d\u4f4e 50%\uff0c\u5ef6\u65f6\u4e5f\u4f1a\u76f8\u5e94\u589e\u52a0\uff1a\n\"\"
  8. \n
\n

\u97f3\u89c6\u9891\u540c\u6b65\u4f18\u5316\uff1a

\n

\"\"

\n
    \n
  1. \u539f\u59cb\u7684 WebRTC \u7684 P2P \u97f3\u89c6\u9891\u540c\u6b65\u7b97\u6cd5\u662f\u6ca1\u6709\u95ee\u9898\u7684\uff0c\u4f46\u662f\u76ee\u524d\u67b6\u6784\u4e0a\u9762\u4e00\u822c\u90fd\u6709\u5a92\u4f53\u8f6c\u53d1\u670d\u52a1\u5668\uff08 SFU \uff09\uff0c\u800c\u670d\u52a1\u5668\u7684 SR \u5305\u751f\u6210\u7b97\u6cd5\u53ef\u80fd\u4f1a\u7531\u4e8e\u67d0\u4e9b\u9650\u5236\u6216\u8005\u9519\u8bef\u4f1a\u4e0d\u5b8c\u5168\u6b63\u786e\uff0c\u5bfc\u81f4\u65e0\u6cd5\u6b63\u5e38\u540c\u6b65\uff0c\u4e3a\u89c4\u907f SR \u5305\u751f\u6210\u9519\u8bef\uff0c\u9700\u8981\u4f18\u5316\u97f3\u89c6\u9891\u540c\u6b65\u6a21\u5757\u7684\u8ba1\u7b97\u65b9\u5f0f\uff0c\u4f7f\u7528\u6c34\u4f4d\u4e3a\u4e3b\u8981\u53c2\u8003\u6765\u540c\u6b65\uff0c\u5373\u5728\u63a5\u6536\u7aef\u4fdd\u8bc1\u97f3\u89c6\u9891\u7684\u7f13\u5b58\u65f6\u95f4\u662f\u5dee\u4e0d\u591a\u5927\u5c0f\u7684\u3002\u4e0b\u9762\u662f\u4f18\u5316\u6548\u679c\u7684\u5bf9\u6bd4\uff1a\n\"\"\n\"\"
  2. \n
  3. \u8fd8\u6709\u4e00\u79cd\u97f3\u89c6\u9891\u540c\u6b65\u7684\u95ee\u9898\uff0c\u5176\u5b9e\u4e0d\u662f\u97f3\u89c6\u9891\u540c\u6b65\u673a\u5236\u5bfc\u81f4\u7684\uff0c\u800c\u662f\u8bbe\u5907\u6027\u80fd\u6709\u95ee\u9898\uff0c\u4e0d\u80fd\u53ca\u65f6\u5904\u7406\u89c6\u9891\u7684\u89e3\u7801\u548c\u6e32\u67d3\uff0c\u5bfc\u81f4\u89c6\u9891\u6570\u636e\u7d2f\u79ef\uff0c\u4ece\u800c\u5f62\u6210\u7684\u97f3\u89c6\u9891\u4e0d\u540c\u6b65\u3002\u8fd9\u79cd\u95ee\u9898\u53ef\u4ee5\u901a\u8fc7\u5bf9\u6bd4\u4e0d\u540c\u6b65\u65f6\u957f\u7684\u8d8b\u52bf\uff0c\u8ddf\u89c6\u9891\u89e3\u7801\u548c\u6e32\u67d3\u65f6\u957f\u7684\u8d8b\u52bf\uff0c\u4e24\u8005\u5339\u914d\u5ea6\u4f1a\u5f88\u9ad8\uff0c\u5982\u4e0b\u56fe\u6240\u793a\uff1a\n\"\"
  4. \n
\n

\u603b\u7ed3

\n

NetEQ \u4f5c\u4e3a\u97f3\u9891\u63a5\u6536\u4fa7\u7684\u6838\u5fc3\u529f\u80fd\uff0c\u57fa\u672c\u4e0a\u5305\u542b\u4e86\u5404\u4e2a\u65b9\u9762\uff0c\u6240\u4ee5\u5f88\u591a\u5f88\u591a\u97f3\u89c6\u9891\u901a\u8baf\u7684\u6280\u672f\u5b9e\u73b0\u91cc\u90fd\u4f1a\u6709\u5b83\u7684\u8e2a\u8ff9\uff0c\u4e58\u7740 WebRTC \u5f00\u6e90\u5feb 10 \u5e74\u7684\u4e1c\u98ce\uff0cNetEQ \u4e5f\u53d8\u7684\u975e\u5e38\u666e\u53ca\uff0c\u5e0c\u671b\u8fd9\u7bc7\u767d\u8bdd\u6587\u7ae0\u80fd\u5e2e\u5927\u5bb6\u66f4\u597d\u7684\u7406\u89e3 NetEQ \u3002

\n

\u4f5c\u8005\u6700\u540e\u7684\u8bdd\uff1a\u9700\u6c42\u4e0d\u505c\u6b47\uff0c\u4f18\u5316\u65e0\u6b62\u5883\uff01

\n" }, { "author": { "url": "member/VideoCloudTech", "name": "VideoCloudTech", "avatar": "https://cdn.v2ex.com/avatar/9612/8e04/513669_large.png?m=1610098421" }, "url": "t/759886", "title": "WebRTC \u97f3\u89c6\u9891\u540c\u6b65\u539f\u7406\u4e0e\u5b9e\u73b0", "id": "t/759886", "date_published": "2021-03-09T02:55:02+00:00", "content_html": "
\n

\u6240\u6709\u7684\u57fa\u4e8e\u7f51\u7edc\u4f20\u8f93\u7684\u97f3\u89c6\u9891\u91c7\u96c6\u64ad\u653e\u7cfb\u7edf\u90fd\u4f1a\u5b58\u5728\u97f3\u89c6\u9891\u540c\u6b65\u7684\u95ee\u9898\uff0c\u4f5c\u4e3a\u73b0\u4ee3\u4e92\u8054\u7f51\u5b9e\u65f6\u97f3\u89c6\u9891\u901a\u4fe1\u7cfb\u7edf\u7684\u4ee3\u8868\uff0cWebRTC \u4e5f\u4e0d\u4f8b\u5916\u3002\u672c\u6587\u5c06\u5bf9\u97f3\u89c6\u9891\u540c\u6b65\u7684\u539f\u7406\u4ee5\u53ca WebRTC \u7684\u5b9e\u73b0\u505a\u6df1\u5165\u5206\u6790\u3002

\n
\n

\u65f6\u95f4\u6233 (timestamp)

\n

\u540c\u6b65\u95ee\u9898\u5c31\u662f\u5feb\u6162\u7684\u95ee\u9898\uff0c\u5c31\u4f1a\u7275\u626f\u5230\u65f6\u95f4\u8ddf\u97f3\u89c6\u9891\u6d41\u5a92\u4f53\u7684\u5bf9\u5e94\u5173\u7cfb\uff0c\u5c31\u6709\u4e86\u65f6\u95f4\u6233\u7684\u6982\u5ff5\u3002

\n

\u65f6\u95f4\u6233\u7528\u6765\u5b9a\u4e49\u5a92\u4f53\u8d1f\u8f7d\u6570\u636e\u7684\u91c7\u6837\u65f6\u523b\uff0c\u4ece\u5355\u8c03\u7ebf\u6027\u9012\u589e\u7684\u65f6\u949f\u4e2d\u83b7\u53d6\uff0c\u65f6\u949f\u7684\u7cbe\u5ea6\u7531 RTP \u8d1f\u8f7d\u6570\u636e\u7684\u91c7\u6837\u9891\u7387\u51b3\u5b9a\u3002\u97f3\u9891\u548c\u89c6\u9891\u7684\u91c7\u6837\u9891\u7387\u662f\u4e0d\u4e00\u6837\u7684\uff0c\u4e00\u822c\u97f3\u9891\u7684\u91c7\u6837\u9891\u7387\u6709 16KHz \u300144.1KHz \u300148KHz \u7b49\uff0c\u800c\u89c6\u9891\u53cd\u6620\u5728\u91c7\u6837\u5e27\u7387\u4e0a\uff0c\u4e00\u822c\u5e27\u7387\u6709 25fps \u300129.97fps \u300130fps \u7b49\u3002

\n

\u4e60\u60ef\u4e0a\u97f3\u9891\u7684\u65f6\u95f4\u6233\u7684\u589e\u901f\u5c31\u662f\u5176\u91c7\u6837\u7387\uff0c\u6bd4\u5982 16KHz \u91c7\u6837\uff0c\u6bcf 10ms \u91c7\u96c6\u4e00\u5e27\uff0c\u5219\u4e0b\u4e00\u5e27\u7684\u65f6\u95f4\u6233\uff0c\u6bd4\u4e0a\u4e00\u5e27\u7684\u65f6\u95f4\u6233\uff0c\u4ece\u6570\u503c\u4e0a\u591a 16 x10=160\uff0c\u5373\u97f3\u9891\u65f6\u95f4\u6233\u589e\u901f\u4e3a 16/ms \u3002\u800c\u89c6\u9891\u7684\u91c7\u6837\u9891\u7387\u4e60\u60ef\u4e0a\u662f\u6309\u7167 90KHz \u6765\u8ba1\u7b97\u7684\uff0c\u5c31\u662f\u6bcf\u79d2 90K \u4e2a\u65f6\u949f tick\uff0c\u4e4b\u6240\u4ee5\u7528 90K \u662f\u56e0\u4e3a\u5b83\u6b63\u597d\u662f\u4e0a\u9762\u6240\u8bf4\u7684\u89c6\u9891\u5e27\u7387\u7684\u500d\u6570\uff0c\u6240\u4ee5\u5c31\u91c7\u7528\u4e86 90K \u3002\u6240\u4ee5\u89c6\u9891\u5e27\u7684\u65f6\u95f4\u6233\u7684\u589e\u957f\u901f\u7387\u5c31\u662f 90/ms \u3002

\n

\u65f6\u95f4\u6233\u7684\u751f\u6210

\n

\u97f3\u9891\u5e27\u65f6\u95f4\u6233\u7684\u751f\u6210

\n

WebRTC \u7684\u97f3\u9891\u5e27\u7684\u65f6\u95f4\u6233\uff0c\u4ece\u7b2c\u4e00\u4e2a\u5305\u4e3a 0\uff0c\u5f00\u59cb\u7d2f\u52a0\uff0c\u6bcf\u4e00\u5e27\u589e\u52a0 = \u7f16\u7801\u5e27\u957f (ms) x \u91c7\u6837\u7387 / 1000\uff0c\u5982\u679c\u91c7\u6837\u7387 16KHz\uff0c\u7f16\u7801\u5e27\u957f 20ms\uff0c\u5219\u6bcf\u4e2a\u97f3\u9891\u5e27\u7684\u65f6\u95f4\u6233\u9012\u589e 20 x 16000/1000 = 320 \u3002\u8fd9\u91cc\u53ea\u662f\u8bf4\u7684\u672a\u6253\u5305\u4e4b\u524d\u7684\u97f3\u9891\u5e27\u7684\u65f6\u95f4\u6233\uff0c\u800c\u5c01\u88c5\u5230 RTP \u5305\u91cc\u9762\u7684\u65f6\u5019\uff0c\u4f1a\u5c06\u8fd9\u4e2a\u97f3\u9891\u5e27\u7684\u65f6\u95f4\u6233\u518d\u7d2f\u52a0\u4e0a\u4e00\u4e2a\u968f\u673a\u504f\u79fb\u91cf\uff08\u6784\u9020\u51fd\u6570\u91cc\u751f\u6210\uff09\uff0c\u7136\u540e\u4f5c\u4e3a\u6b64 RTP \u5305\u7684\u65f6\u95f4\u6233\uff0c\u53d1\u9001\u51fa\u53bb\uff0c\u5982\u4e0b\u9762\u4ee3\u7801\u6240\u793a\uff0c\u6ce8\u610f\uff0c\u8fd9\u4e2a\u903b\u8f91\u540c\u6837\u9002\u7528\u4e8e\u89c6\u9891\u5305\u3002\n\"\"

\n

\u89c6\u9891\u5e27\u65f6\u95f4\u6233\u7684\u751f\u6210

\n

WebRTC \u7684\u89c6\u9891\u5e27\uff0c\u751f\u6210\u673a\u5236\u8ddf\u97f3\u9891\u5e27\u5b8c\u5168\u4e0d\u540c\u3002\u89c6\u9891\u5e27\u7684\u65f6\u95f4\u6233\u6765\u6e90\u4e8e\u7cfb\u7edf\u65f6\u949f\uff0c\u91c7\u96c6\u5b8c\u6210\u540e\u81f3\u7f16\u7801\u4e4b\u524d\u7684\u67d0\u4e2a\u65f6\u523b\uff08\u8fd9\u4e2a\u4f20\u9012\u94fe\u8def\u975e\u5e38\u957f\uff0c\u4e0d\u540c\u914d\u7f6e\u7684\u89c6\u9891\u5e27\uff0c\u8d70\u4e0d\u540c\u7684\u903b\u8f91\uff0c\u4f1a\u6709\u4e0d\u540c\u7684\u83b7\u53d6\u4f4d\u7f6e\uff09\uff0c\u83b7\u53d6\u5f53\u524d\u7cfb\u7edf\u7684\u65f6\u95f4 timestamp_us_ \uff0c\u7136\u540e\u7b97\u51fa\u6b64\u7cfb\u7edf\u65f6\u95f4\u5bf9\u5e94\u7684 ntp_time_ms_ \uff0c\u518d\u6839\u636e\u6b64 ntp \u65f6\u95f4\u7b97\u51fa\u539f\u59cb\u89c6\u9891\u5e27\u7684\u65f6\u95f4\u6233 timestamp_rtp_ \uff0c\u53c2\u770b\u4e0b\u9762\u7684\u4ee3\u7801\uff0c\u8ba1\u7b97\u903b\u8f91\u4e5f\u5728 OnFrame \u8fd9\u4e2a\u51fd\u6570\u4e2d\u3002\n\"\"\n\u4e3a\u4ec0\u4e48\u89c6\u9891\u5e27\u91c7\u7528\u4e86\u8ddf\u97f3\u9891\u5e27\u4e0d\u540c\u7684\u65f6\u95f4\u6233\u8ba1\u7b97\u673a\u5236\u5462\uff1f\u6211\u7684\u7406\u89e3\uff0c\u4e00\u822c\u60c5\u51b5\u97f3\u9891\u7684\u91c7\u96c6\u8bbe\u5907\u7684\u91c7\u6837\u95f4\u9694\u548c\u65f6\u949f\u7cbe\u5ea6\u66f4\u52a0\u51c6\u786e\uff0c10ms \u4e00\u5e27\uff0c\u6bcf\u79d2\u662f 100 \u5e27\uff0c\u4e00\u822c\u4e0d\u4f1a\u51fa\u73b0\u5927\u7684\u6296\u52a8\uff0c\u800c\u89c6\u9891\u5e27\u7684\u5e27\u95f4\u9694\u65f6\u95f4\u8f83\u5927\u91c7\u96c6\u7cbe\u5ea6\uff0c\u6bcf\u79d2 25 \u5e27\u7684\u8bdd\uff0c\u5c31\u662f 40ms \u4e00\u5e27\u3002\u5982\u679c\u8fd8\u91c7\u7528\u97f3\u9891\u7684\u6309\u7167\u91c7\u6837\u7387\u6765\u9012\u589e\u7684\u8bdd\uff0c\u53ef\u80fd\u4f1a\u51fa\u73b0\u8ddf\u5b9e\u9645\u65f6\u949f\u5bf9\u4e0d\u9f50\u7684\u60c5\u51b5\uff0c\u6240\u4ee5\u5c31\u76f4\u63a5\u6bcf\u53d6\u4e00\u5e27\uff0c\u6309\u7167\u53d6\u51fa\u65f6\u523b\u7684\u7cfb\u7edf\u65f6\u949f\u7b97\u51fa\u4e00\u4e2a\u65f6\u95f4\u6233\uff0c\u8fd9\u6837\u53ef\u4ee5\u518d\u73b0\u771f\u5b9e\u89c6\u9891\u5e27\u8ddf\u5b9e\u9645\u65f6\u95f4\u7684\u5bf9\u5e94\u5173\u7cfb\u3002

\n

\u8ddf\u4e0a\u9762\u97f3\u9891\u4e00\u6837\uff0c\u5728\u5c01\u88c5\u5230 RTP \u5305\u7684\u65f6\u5019\uff0c\u4f1a\u5c06\u539f\u59cb\u89c6\u9891\u5e27\u7684\u65f6\u95f4\u6233\u7d2f\u52a0\u4e0a\u4e00\u4e2a\u968f\u673a\u504f\u79fb\u91cf\uff08\u6b64\u504f\u79fb\u91cf\u8ddf\u97f3\u9891\u7684\u5e76\u4e0d\u662f\u540c\u4e00\u4e2a\u503c\uff09\uff0c\u4f5c\u4e3a\u6b64 RTP \u5305\u7684\u65f6\u95f4\u6233\u53d1\u9001\u51fa\u53bb\u3002\u503c\u5f97\u6ce8\u610f\u7684\u662f\uff0c\u8fd9\u91cc\u8ba1\u7b97\u7684 NTP \u65f6\u95f4\u6233\u6839\u672c\u5c31\u4e0d\u4f1a\u968f\u7740 RTP \u6570\u636e\u5305\u4e00\u8d77\u53d1\u9001\u51fa\u53bb\uff0c\u56e0\u4e3a RTP \u5305\u7684\u5305\u5934\u91cc\u9762\u6ca1\u6709 NTP \u5b57\u6bb5\uff0c\u5373\u4f7f\u662f\u6269\u5c55\u5b57\u6bb5\u91cc\uff0c\u6211\u4eec\u4e5f\u6ca1\u6709\u653e\u8fd9\u4e2a\u503c\uff0c\u5982\u4e0b\u9762\u89c6\u9891\u7684\u65f6\u95f4\u76f8\u5173\u7684\u6269\u5c55\u5b57\u6bb5\u3002\n\"\"

\n

\u97f3\u89c6\u9891\u540c\u6b65\u6838\u5fc3\u4f9d\u636e

\n

\u4ece\u4e0a\u9762\u53ef\u4ee5\u770b\u51fa\uff0cRTP \u5305\u91cc\u9762\u53ea\u5305\u542b\u6bcf\u4e2a\u6d41\u7684\u72ec\u7acb\u7684\u3001\u5355\u8c03\u9012\u589e\u7684\u65f6\u95f4\u6233\u4fe1\u606f\uff0c\u4e5f\u5c31\u662f\u8bf4\u97f3\u9891\u548c\u89c6\u9891\u4e24\u4e2a\u65f6\u95f4\u6233\u5b8c\u5168\u662f\u72ec\u7acb\u7684\uff0c\u6ca1\u6709\u5173\u7cfb\u7684\uff0c\u65e0\u6cd5\u53ea\u6839\u636e\u8fd9\u4e2a\u4fe1\u606f\u6765\u8fdb\u884c\u540c\u6b65\uff0c\u56e0\u4e3a\u65e0\u6cd5\u5bf9\u4e24\u4e2a\u6d41\u7684\u65f6\u95f4\u8fdb\u884c\u5173\u8054\uff0c\u6211\u4eec\u9700\u8981\u4e00\u79cd\u6620\u5c04\u5173\u7cfb\uff0c\u5c06\u4e24\u4e2a\u72ec\u7acb\u7684\u65f6\u95f4\u6233\u5173\u8054\u8d77\u6765\u3002

\n

\u8fd9\u4e2a\u65f6\u5019 RTCP \u5305\u91cc\u9762\u7684\u4e00\u79cd\u53d1\u9001\u7aef\u62a5\u544a\u5206\u7ec4 SR (SenderReport) \u5305\u5c31\u4e0a\u573a\u4e86\uff0c\u8be6\u60c5\u8bf7\u53c2\u8003 RFC3550\u3002\n\"\"\nSR \u5305\u7684\u5176\u4e2d\u4e00\u4e2a\u4f5c\u7528\u5c31\u662f\u6765\u544a\u8bc9\u6211\u4eec\u6bcf\u4e2a\u6d41\u7684 RTP \u5305\u7684\u65f6\u95f4\u6233\u548c NTP \u65f6\u95f4\u7684\u5bf9\u5e94\u5173\u7cfb\u7684\u3002\u9760\u7684\u5c31\u662f\u4e0a\u8fb9\u56fe\u7247\u4e2d\u6807\u51fa\u7684 NTP \u65f6\u95f4\u6233\u548c RTP \u65f6\u95f4\u6233\uff0c\u901a\u8fc7 RFC3550 \u7684\u63cf\u8ff0\uff0c\u6211\u4eec\u77e5\u9053\u8fd9\u4e24\u4e2a\u65f6\u95f4\u6233\u5bf9\u5e94\u7684\u662f\u540c\u4e00\u4e2a\u65f6\u523b\uff0c\u8fd9\u4e2a\u65f6\u523b\u8868\u793a\u6b64 SR \u5305\u751f\u6210\u7684\u65f6\u523b\u3002\u8fd9\u5c31\u662f\u6211\u4eec\u5bf9\u97f3\u89c6\u9891\u8fdb\u884c\u540c\u6b65\u7684\u6700\u6838\u5fc3\u7684\u4f9d\u636e\uff0c\u6240\u6709\u7684\u5176\u5b83\u8ba1\u7b97\u90fd\u662f\u56f4\u7ed5\u8fd9\u4e2a\u6838\u5fc3\u4f9d\u636e\u6765\u5c55\u5f00\u7684\u3002

\n

SR \u5305\u7684\u751f\u6210

\n

\u7531\u4e0a\u9762\u8bba\u8ff0\u53ef\u77e5\uff0cNTP \u65f6\u95f4\u548c RTP \u65f6\u95f4\u6233\u662f\u540c\u4e00\u65f6\u523b\u7684\u4e0d\u540c\u8868\u793a\uff0c\u53ea\u662f\u7cbe\u5ea6\u548c\u5355\u4f4d\u4e0d\u4e00\u6837\u3002NTP \u65f6\u95f4\u662f\u7edd\u5bf9\u65f6\u95f4\uff0c\u4ee5\u6beb\u79d2\u4e3a\u5355\u4f4d\uff0c\u800c RTP \u65f6\u95f4\u6233\u5219\u548c\u5a92\u4f53\u7684\u91c7\u6837\u9891\u7387\u6709\u5173\uff0c\u662f\u4e00\u4e2a\u5355\u8c03\u9012\u589e\u6570\u503c\u3002\u751f\u6210 SR \u5305\u7684\u8fc7\u7a0b\u5728 RTCPSender::BuildSR(const RtcpContext& ctx) \u51fd\u6570\u91cc\u9762\uff0c\u8001\u7248\u672c\u91cc\u9762\u6709 bug\uff0c\u5199\u6b7b\u4e86\u91c7\u6837\u7387\u4e3a 8K\uff0c\u65b0\u7248\u672c\u5df2\u7ecf\u4fee\u590d\uff0c\u4e0b\u9762\u622a\u56fe\u662f\u8001\u7248\u672c\u7684\u4ee3\u7801\uff1a\n\"\"

\n

\u8ba1\u7b97\u7684\u601d\u8def\u5982\u4e0b

\n

\u9996\u5148\uff0c\u6211\u4eec\u8981\u83b7\u53d6\u5f53\u524d\u65f6\u523b\uff08\u5373 SR \u5305\u751f\u6210\u65f6\u523b\uff09\u7684 NTP \u65f6\u95f4\u3002\u8fd9\u4e2a\u76f4\u63a5\u4ece\u4f20\u8fc7\u6765\u7684\u53c2\u6570 ctx \u4e2d\u5c31\u53ef\u4ee5\u83b7\u5f97\uff1a\n\"\"\n\u5176\u6b21\uff0c\u6211\u4eec\u8981\u8ba1\u7b97\u5f53\u524d\u65f6\u523b\uff0c\u5e94\u8be5\u5bf9\u5e94\u7684 RTP \u7684\u65f6\u95f4\u6233\u662f\u591a\u5c11\u3002\u6839\u636e\u6700\u540e\u4e00\u4e2a\u53d1\u9001\u7684 RTP \u5305\u7684\u65f6\u95f4\u6233 last_rtp_timestamp_ \u548c\u5b83\u7684\u91c7\u96c6\u65f6\u523b\u7684\u7cfb\u7edf\u65f6\u95f4 last_frame_capture_time_ms_\uff0c\u548c\u5f53\u524d\u5a92\u4f53\u6d41\u7684\u65f6\u95f4\u6233\u7684\u6bcf ms \u589e\u957f\u901f\u7387 rtp_rate \uff0c\u4ee5\u53ca\u4ece last_frame_capture_time_ms_ \u5230\u5f53\u524d\u65f6\u523b\u7684\u65f6\u95f4\u6d41\u901d\uff0c\u5c31\u53ef\u4ee5\u7b97\u51fa\u6765\u3002\u6ce8\u610f\uff0clast_rtp_timestamp_ \u662f\u5a92\u4f53\u6d41\u7684\u539f\u59cb\u65f6\u95f4\u6233\uff0c\u4e0d\u662f\u7ecf\u8fc7\u968f\u673a\u504f\u79fb\u7684 RTP \u5305\u65f6\u95f4\u6233\uff0c\u6240\u4ee5\u6700\u540e\u53c8\u7d2f\u52a0\u4e86\u504f\u79fb\u91cf timestamp_offset_ \u3002\u5176\u4e2d\u6700\u540e\u4e00\u4e2a\u53d1\u9001\u7684 RTP \u5305\u7684\u65f6\u95f4\u4fe1\u606f\u662f\u901a\u8fc7\u4e0b\u9762\u7684\u51fd\u6570\u8fdb\u884c\u66f4\u65b0\u7684\uff1a\n\"\"

\n

\u97f3\u89c6\u9891\u540c\u6b65\u7684\u8ba1\u7b97

\n

\u56e0\u4e3a\u540c\u4e00\u53f0\u673a\u5668\u4e0a\u97f3\u9891\u6d41\u548c\u89c6\u9891\u6d41\u7684\u672c\u5730\u7cfb\u7edf\u65f6\u95f4\u662f\u4e00\u6837\u7684\uff0c\u4e5f\u5c31\u662f\u7cfb\u7edf\u65f6\u95f4\u5bf9\u5e94\u7684 NTP \u683c\u5f0f\u7684\u65f6\u95f4\u4e5f\u662f\u4e00\u6837\u7684\uff0c\u662f\u5728\u540c\u4e00\u4e2a\u5750\u6807\u7cfb\u4e0a\u7684\uff0c\u6240\u4ee5\u53ef\u4ee5\u628a NTP \u65f6\u95f4\u4f5c\u4e3a\u6a2a\u8f74 X\uff0c\u5355\u4f4d\u662f ms\uff0c\u800c\u628a RTP \u65f6\u95f4\u6233\u7684\u503c\u4f5c\u4e3a\u7eb5\u8f74 Y\uff0c\u753b\u5728\u4e00\u8d77\u3002\u4e0b\u56fe\u5c55\u793a\u4e86\u8ba1\u7b97\u97f3\u89c6\u9891\u540c\u6b65\u7684\u539f\u7406\u548c\u65b9\u6cd5\uff0c\u5176\u5b9e\u5f88\u7b80\u5355\uff0c\u5c31\u662f\u4f7f\u7528\u6700\u8fd1\u7684\u4e24\u4e2a SR \u70b9\uff0c\u4e24\u70b9\u786e\u5b9a\u4e00\u6761\u76f4\u7ebf\uff0c\u4e4b\u540e\u7ed9\u4efb\u610f\u4e00\u4e2a RTP \u65f6\u95f4\u6233\uff0c\u90fd\u53ef\u4ee5\u6c42\u51fa\u5bf9\u5e94\u7684 NTP \u65f6\u95f4\uff0c\u53c8\u56e0\u4e3a\u89c6\u9891\u548c\u97f3\u9891\u7684 NTP \u65f6\u95f4\u662f\u5728\u540c\u4e00\u57fa\u51c6\u4e0a\u7684\uff0c\u6240\u4ee5\u5c31\u53ef\u4ee5\u7b97\u51fa\u4e24\u8005\u7684\u5dee\u503c\u3002\n\"\"\n\u4e0a\u56fe\u4ee5\u97f3\u9891\u7684\u4e24\u4e2a SR \u5305\u4e3a\u4f8b\uff0c\u786e\u5b9a\u51fa\u4e86 RTP \u548c NTP \u5bf9\u5e94\u5173\u7cfb\u7684\u76f4\u7ebf\uff0c\u7136\u540e\u7ed9\u4efb\u610f\u4e00\u4e2a rtp_a\uff0c\u5c31\u7b97\u51fa\u4e86\u5176\u5bf9\u5e94\u7684 NTP_a\uff0c\u540c\u7406\u4e5f\u53ef\u4ee5\u6c42\u4efb\u610f\u89c6\u9891\u5305 rtp_v \u5bf9\u5e94\u7684 NTP_v \u7684\u65f6\u95f4\u70b9\uff0c\u4e24\u4e2a\u7684\u5dee\u503c\u5c31\u662f\u65f6\u95f4\u5dee\u3002

\n

\u4e0b\u9762\u662f WebRTC \u91cc\u9762\u8ba1\u7b97\u76f4\u7ebf\u5bf9\u5e94\u7684\u7cfb\u6570 rate \u548c\u504f\u79fb offset \u7684\u4ee3\u7801\uff1a\n\"\"\n\u5728 WebRTC \u4e2d\u8ba1\u7b97\u7684\u662f\u6700\u65b0\u6536\u5230\u7684\u97f3\u9891 RTP \u5305\u548c\u6700\u65b0\u6536\u5230\u7684\u89c6\u9891 RTP \u5305\u7684\u5bf9\u5e94\u7684 NTP \u65f6\u95f4\uff0c\u4f5c\u4e3a\u7f51\u7edc\u4f20\u8f93\u5f15\u5165\u7684\u4e0d\u540c\u6b65\u65f6\u957f\uff0c\u7136\u540e\u53c8\u6839\u636e\u5f53\u524d\u97f3\u9891\u548c\u89c6\u9891\u7684 JitterBuffer \u548c\u64ad\u653e\u7f13\u51b2\u533a\u7684\u5927\u5c0f\uff0c\u5f97\u5230\u4e86\u64ad\u653e\u5f15\u5165\u7684\u4e0d\u540c\u6b65\u65f6\u957f\uff0c\u6839\u636e\u4e24\u4e2a\u4e0d\u540c\u6b65\u65f6\u957f\uff0c\u5f97\u5230\u4e86\u6700\u7ec8\u7684\u97f3\u89c6\u9891\u4e0d\u540c\u6b65\u65f6\u957f\uff0c\u8ba1\u7b97\u8fc7\u7a0b\u5728 StreamSynchronization::ComputeRelativeDelay() \u51fd\u6570\u4e2d\uff0c\u4e4b\u540e\u53c8\u7ecf\u8fc7\u4e86 StreamSynchronization::ComputeDelays() \u51fd\u6570\u5bf9\u5176\u8fdb\u884c\u4e86\u6307\u6570\u5e73\u6ed1\u7b49\u4e00\u7cfb\u5217\u7684\u5904\u7406\u548c\u5224\u65ad\uff0c\u5f97\u51fa\u6700\u7ec8\u63a7\u5236\u97f3\u9891\u548c\u89c6\u9891\u7684\u6700\u5c0f\u5ef6\u65f6\u65f6\u95f4\uff0c\u5206\u522b\u901a\u8fc7 syncable_audio_->SetMinimumPlayoutDelay(target_audio_delay_ms) \u548c syncable_video_->SetMinimumPlayoutDelay(target_video_delay_ms) \u5e94\u7528\u5230\u4e86\u97f3\u89c6\u9891\u7684\u64ad\u653e\u7f13\u51b2\u533a\u3002

\n

\u8fd9\u4e00\u7cfb\u5217\u64cd\u4f5c\u90fd\u662f\u7531\u5b9a\u65f6\u5668\u8c03\u7528 RtpStreamsSynchronizer::Process() \u51fd\u6570\u6765\u5904\u7406\u7684\u3002

\n

\u53e6\u5916\u9700\u8981\u6ce8\u610f\u4e00\u4e0b\uff0c\u5728\u77e5\u9053\u91c7\u6837\u7387\u7684\u60c5\u51b5\u4e0b\uff0c\u662f\u53ef\u4ee5\u901a\u8fc7\u4e00\u4e2a SR \u5305\u6765\u8ba1\u7b97\u7684\uff0c\u5982\u679c\u6ca1\u6709 SR \u5305\uff0c\u662f\u65e0\u6cd5\u8fdb\u884c\u51c6\u786e\u7684\u97f3\u89c6\u9891\u540c\u6b65\u7684\u3002\n\"\"\nWebRTC \u4e2d\u5b9e\u73b0\u97f3\u89c6\u9891\u540c\u6b65\u7684\u624b\u6bb5\u5c31\u662f SR \u5305\uff0c\u6838\u5fc3\u7684\u4f9d\u636e\u5c31\u662f SR \u5305\u4e2d\u7684 NTP \u65f6\u95f4\u548c RTP \u65f6\u95f4\u6233\u3002\u6700\u540e\u7684\u4e24\u5f20 NTP \u65f6\u95f4-RTP \u65f6\u95f4\u6233 \u5750\u6807\u56fe\u5982\u679c\u4f60\u80fd\u770b\u660e\u767d\uff08\u5176\u5b9e\u5f88\u7b80\u5355\uff0c\u5c31\u662f\u6c42\u89e3\u51fa\u76f4\u7ebf\u65b9\u7a0b\u6765\u8ba1\u7b97 NTP \uff09\uff0c\u90a3\u4e48\u4e5f\u5c31\u771f\u6b63\u7684\u7406\u89e3\u4e86 WebRTC \u4e2d\u97f3\u89c6\u9891\u540c\u6b65\u7684\u539f\u7406\u3002\u5982\u679c\u6709\u4ec0\u4e48\u9057\u6f0f\u6216\u8005\u9519\u8bef\uff0c\u6b22\u8fce\u5927\u5bb6\u4e00\u8d77\u4ea4\u6d41\uff01

\n" }, { "author": { "url": "member/VideoCloudTech", "name": "VideoCloudTech", "avatar": "https://cdn.v2ex.com/avatar/9612/8e04/513669_large.png?m=1610098421" }, "url": "t/757184", "title": "light-rtc: \u7406\u5ff5\u4e0e\u5b9e\u8df5", "id": "t/757184", "date_published": "2021-03-01T03:23:02+00:00", "content_html": "

\u5728\u4e0e\u540c\u884c\u4ea4\u6d41\u8fc7\u7a0b\u4e2d\uff0c\u53d1\u73b0\u5f88\u591a\u540c\u884c\u5bf9 WebRTC \u6539\u52a8\u592a\u591a\uff0c\u5bfc\u81f4\u65e0\u6cd5\u5347\u7ea7 WebRTC \u7248\u672c\u3002\u800c WebRTC \u5f00\u6e90\u793e\u533a\u7684\u5feb\u901f\u8fed\u4ee3\uff0c\u8ba9\u4ed6\u4eec\u611f\u5230\u6b23\u559c\u53c8\u7126\u8651\uff1a\u5f00\u6e90\u793e\u533a\u7684\u8fed\u4ee3\u6548\u679c\uff0c\u662f\u4e0d\u662f\u8d85\u8fc7\u4e86\u4ed6\u4eec\u5bf9 WebRTC \u7684\u4f18\u5316\u6548\u679c\uff1f\u6211\u4eec\u9488\u5bf9\u7279\u5b9a\u573a\u666f\u4f18\u5316 WebRTC \u65f6\uff0c\u600e\u4e48\u7d27\u8ddf WebRTC \u5f00\u6e90\u793e\u533a\u901a\u7528\u7684\u4f18\u5316\uff1f

\n

\u7406\u5ff5

\n

\u7b80\u8a00\u4e4b\uff0c\u628a WebRTC \u4f5c\u4e3a Framework \u4f7f\u7528\uff0c\u800c\u4e0d\u662f Library\uff0c\u5373\uff1aWebRTC \u4ed3\u5e93\u8f7b\u91cf\u5316\uff0c\u6838\u5fc3\u6a21\u5757\u63d2\u4ef6\u5316\u3002

\n

\u8be6\u7ec6\u7684\uff0cWebRTC \u4f5c\u4e3a Framework \u4e32\u8054\u6838\u5fc3\u6a21\u5757\uff1b\u6838\u5fc3\u6a21\u5757\u65e2\u53ef\u4ee5\u4ee5\u63d2\u4ef6\u5f62\u5f0f\u4f7f\u7528\u6211\u4eec\u7684\u5b9e\u73b0\uff0c\u4e5f\u53ef\u4ee5 Fallback \u5230 WebRTC \u7684\u9ed8\u8ba4\u5b9e\u73b0\u3002\u76ee\u7684\u662f\u51cf\u5c11 WebRTC \u51b2\u7a81\u7684\u53ef\u80fd\u6027\uff0c\u63d0\u9ad8\u5347\u7ea7 WebRTC \u7684\u654f\u6377\u6027\u3002

\n

\u76ee\u6807\uff1a\u4e00\u5e74\u5347\u7ea7\u4e00\u6b21 WebRTC\uff0c\u4e00\u6b21\u82b1\u8d39\u4e00\u4e2a\u4eba\u6708\u3002

\n

\u67b6\u6784

\n

\u6a21\u5757\u62c6\u89e3

\n

\"file\"\nWebRTC \u7684\u6838\u5fc3\u6a21\u5757\uff0c\u5305\u62ec\uff1a

\n

\u97f3\u9891

\n\n

\u89c6\u9891

\n\n

\u901a\u7528

\n\n

WebRTC \u5728\u957f\u671f\u7684\u6f14\u8fdb\u4e2d\uff0cAPI \u5df2\u7ecf\u5177\u5907\u4e86\u4f5c\u4e3a Framework \u7684\u5927\u90e8\u5206\u80fd\u529b\u3002\u7ea2\u8272\u7684\u6838\u5fc3\u6a21\u5757\uff0c\u5df2\u7ecf\u57fa\u672c\u53ef\u4ee5\u63d2\u4ef6\u5316\uff0c\u5982\u4e0b\u9762\u7684 API\uff1a\n\"file\"

\n

\u4ed3\u5e93\u7ba1\u7406

\n

\"file\"\nlight-rtc \u4f5c\u4e3a WebRTC \u4ed3\u5e93\uff0c\u6211\u4eec\u9700\u8981\u4fdd\u7559\u4e24\u4e2a Remote\uff0c\u4e00\u4e2a\u662f Alibaba\uff0c\u4e00\u4e2a\u662f Google \u3002\u5347\u7ea7 WebRTC \u65f6\uff0c\u6211\u4eec\u4ece Google \u4e0a Pull \u6700\u65b0\u4ee3\u7801\uff0c \u89e3\u51b3\u51b2\u7a81\uff0c\u7136\u540e Push \u5230 Alibaba \u3002

\n

\u5bf9\u63d2\u4ef6\u5316\u7684\u6a21\u5757\uff0c\u6211\u4eec\u9700\u8981\u653e\u5230\u5355\u72ec\u7684\u4ed3\u5e93 lrtc-plugin \u91cc\uff0c\u8fd9\u6837\u6709\u4e24\u4e2a\u597d\u5904\uff1a

\n
    \n
  1. \u5bf9 light-rtc \u4ed3\u5e93\u6539\u52a8\u5c11\uff0c\u51cf\u5c11\u4e0e Google \u51b2\u7a81\u7684\u53ef\u80fd\u6027\uff1b
  2. \n
  3. \u66f4\u91cd\u8981\u7684\uff0c\u8ba9\u6bcf\u4e2a\u5f00\u53d1\u540c\u5b66\uff0c\u5728\u6bcf\u6b21\u6539\u52a8\u524d\uff0c\u66f4\u4e3b\u52a8\u3001\u66f4\u6709\u610f\u8bc6\u7684\u601d\u8003\uff0c\u653e\u5230\u54ea\u4e2a\u4ed3\u5e93\u66f4\u5408\u9002\uff0c\u5426\u5219\u5bb9\u6613\u60ef\u6027\u601d\u7ef4\uff0c\u76f4\u63a5\u6539\u52a8 light-rtc \u3002
  4. \n
\n

\u5bf9 lrtc-plugin \u4f9d\u8d56\u7684\u7b2c\u4e09\u65b9\u5e93\uff0c\u4e5f\u5e94\u8be5\u4ee5\u5355\u72ec\u7684\u4ed3\u5e93\u5b58\u5728\uff0c\u5e76\u4fdd\u7559\u4e24\u4e2a Remote\uff0c\u6bd4\u5982 Opus\uff0c\u8fd9\u6837\uff0c\u5373\u4f7f\u4fee\u6539\u4e86 Opus \u6e90\u7801\uff0c\u4ecd\u7136\u53ef\u4ee5\u50cf\u5347\u7ea7 light-rtc \u4e00\u6837\uff0c\u65b9\u4fbf\u7684\u5355\u72ec\u5347\u7ea7 Opus \u7248\u672c\u3002

\n

\u6a21\u5757

\n

Codec

\n

\u97f3\u9891\u7f16\u89e3\u7801\u5668\u3001\u89c6\u9891\u7f16\u89e3\u7801\u5668\uff0c\u662f\u6211\u4eec\u6700\u5e38\u4f18\u5316\u7684\u90e8\u5206\u4e4b\u4e00\uff1a

\n\n

\u8fd9\u90e8\u5206\u63d2\u4ef6\u5316\u662f\u76f8\u5bf9\u7b80\u5355\u7684\uff0c\u53ea\u9700\u8981\u5b9e\u73b0\u81ea\u5df1\u7684 [Video|Audio][Encoder|Decoder]Factory \u5373\u53ef\u3002\u4ee5 Simulcast \u4e3a\u4f8b\uff0c\u5728\u81ea\u5df1\u5b9e\u73b0\u7684 VideoEncoderFactory \u91cc\uff0c\u5148\u7528 WebRTC \u539f\u59cb\u7684 VideoEncoderFactory\uff0c\u521b\u5efa\u591a\u4e2a Encoder \u5bf9\u8c61\uff0c\u7136\u540e\u5c01\u88c5\u5230\u4e00\u4e2a Simulcast Encoder \u91cc\u3002

\n

ADM

\n

\u5f88\u53ef\u60dc\uff0cADM(Audio Device Module)\u6ca1\u6709\u63d0\u4f9b\u68c0\u6d4b\u8bbe\u5907\u63d2\u62d4\u7684\u529f\u80fd\uff0c\u9700\u8981\u589e\u52a0 Callback \u63a5\u53e3\u3002

\n

\u53e6\u5916\uff0c\u867d\u7136 WebRTC \u652f\u6301\u6837\u672c\u6570\u91cf\u7684\u76d1\u63a7\uff0c\u4f46\u662f\u5f53\u524d\u53ea\u7528\u4e8e\u6253\u5370\u65e5\u5fd7\uff0c\u5982\u679c\u60f3\u5728\u6b64\u57fa\u7840\u4e0a\u505a\u66f4\u591a\u4e8b\u60c5\uff08\u5982\uff1a\u53d1\u73b0\u91c7\u96c6\u6837\u672c\u4e3a 0 \u65f6\uff0c\u91cd\u542f\u91c7\u96c6\uff09\uff0c\u5219\u5355\u72ec\u505a\u4e00\u4e2a AudioSampleMoniter \u7684\u7c7b\uff0c\u6bd4\u8f83\u6709\u5229\u4e8e\u6269\u5c55\u3002\n\"file\"\nADM \u662f\u4e00\u4e2a\u9002\u914d\u96be\u70b9\uff0c\u76f8\u4fe1\u662f\u56f0\u6270 RTC \u540c\u884c\u7684\u5171\u540c\u96be\u9898\u3002\u4e0d\u540c\u64cd\u4f5c\u7cfb\u7edf\u3001\u4e0d\u540c\u673a\u578b\uff0c\u90fd\u53ef\u80fd\u6709\u4e0d\u4e00\u6837\u7684\u95ee\u9898\u3002\u4f8b\u5982\uff1a

\n\n

\u8fd9\u4e9b\u4fee\u6539\u5927\u90e8\u5206\u5c5e\u4e8e Bugfix\uff0c\u53c2\u8003\u201cBugfix\u201d\u7ae0\u8282\u3002

\n

APM

\n

APM(Audio Processing Module)\u53ef\u80fd\u662f light-rtc \u76f8\u5bf9\u96be\u5904\u7406\u7684\u90e8\u5206\u3002

\n

APM \u4e0e NetEQ \u4e00\u8d77\uff0c\u53ef\u80fd\u662f WebRTC \u6838\u5fc3\u6a21\u5757\u4e2d\uff0c\u5f00\u6e90\u4ef7\u503c\u6700\u5927\u7684\u90e8\u5206\u3002\u5728\u6211\u5bf9 APM \u6709\u9650\u7684\u8ba4\u77e5\u91cc\uff0c\u5bf9 APM \u5e38\u89c1\u7684\u4f18\u5316\u53ef\u80fd\u6709\uff1a

\n\n

\u4e0b\u56fe\u662f WebRTC APM \u5185\u90e8\u6a21\u5757\u7684\u6570\u636e\u6d41\u7a0b\u56fe\uff1a\n\"file\"\n\u4ece\u56fe\u4e2d\u53ef\u4ee5\u770b\u51fa\uff0cAPM \u5176\u5b9e\u4e5f\u4e3a\u63d2\u4ef6\u5316\u505a\u4e86\u51c6\u5907\uff0c\u4f46\u662f\u53ea\u5728\u8fd1\u7aef\u4fe1\u53f7\u7684\u5c3e\u90e8\u3001\u8fdc\u7aef\u4fe1\u53f7\u7684\u5934\u90e8\u3002\u4ece APM \u6784\u9020\u51fd\u6570\u4e0a\u4e5f\u53ef\u4ee5\u770b\u51fa\u6765\uff1a\n\"file\"\n\u6ee4\u6ce2 /\u5747\u8861\uff0c\u53ef\u4ee5\u65b9\u4fbf\u7684\u5b9e\u73b0\u4e00\u4e2a CustomProcessing \u7684 render_pre_processor \u3002

\n

\u5176\u4ed6\u7684\u4f18\u5316\uff0c\u9075\u5faa\u8f7b\u91cf\u5316 /\u63d2\u4ef6\u5316\u7684\u7406\u5ff5\uff0c\u6ca1\u6709\u73b0\u6210\u7684\u63d2\u4ef6\u63a5\u53e3\uff0c\u6211\u4eec\u53ef\u4ee5\u521b\u9020\u65b0\u7684\u63d2\u4ef6\u63a5\u53e3\uff0c\u5982\u5578\u53eb\u6291\u5236\uff0c\u4ee5\u53ca AECM \u4f18\u5316\u7684\u90e8\u5206\u7b97\u6cd5\u3002

\n

\u4f46 APM \u4ecd\u7136\u4f1a\u6709\u5f88\u591a\u6ca1\u529e\u6cd5\u63d2\u4ef6\u5316\u7684\uff0c\u53ea\u80fd\u4fee\u6539 light-rtc \u4ed3\u5e93\uff0c\u5982 AECM Double Talk \u4f18\u5316\u7b49\u3002

\n

AM

\n

AM(Audio Mixer)\u7684\u63d2\u4ef6\u5316\uff0c\u53ef\u4ee5\u5728\u4e0d\u4fee\u6539 light-rtc \u7684\u57fa\u7840\u4e0a\uff0c\u73a9\u51fa\u5f88\u591a\u82b1\u6837\uff1a

\n\n

FEC

\n

FEC(Forward Error Correction)\uff0c\u5e38\u89c1\u7684\u4fee\u6539\uff1a

\n\n

CC

\n

CC(Congestion Control)\uff0c\u5305\u542b\u4e24\u4e2a\u65b9\u9762\uff0c\u4e00\u4e2a\u662f CC \u7b97\u6cd5\u672c\u8eab\uff0c\u4e00\u4e2a\u662f CC \u5173\u8054\u6a21\u5757\u3002

\n

\u7b97\u6cd5\u672c\u8eab\uff0c\u53ef\u4ee5\u7528\u4e0d\u540c\u7684\u7b97\u6cd5\u5b9e\u73b0\uff0c\u5982 WebRTC \u9ed8\u8ba4\u7684 goog_cc\uff0c\u4e5f\u53ef\u4ee5\u662f BBR\uff0c\u751a\u81f3\u662f\u6ee1\u8db3 WebRTC::NetworkControllerFactoryInterface \u63a5\u53e3\u7684\u5916\u90e8\u63d2\u4ef6\u3002

\n

\u5173\u8054\u6a21\u5757\uff1a

\n\n

\"file\"

\n\n

VideoRender

\n

Android \u3001iOS \u3001Mac\uff0cWebRTC \u90fd\u63d0\u4f9b\u4e86\u9ed8\u8ba4\u7684\u5b9e\u73b0\uff0c\u867d\u7136\u6709\u5c11\u91cf Bug\uff0c\u4f46\u662f\u57fa\u672c\u6ee1\u8db3\u9700\u6c42\u3002

\n

Windows \u5e73\u53f0\uff0c\u65e9\u671f WebRTC \u63d0\u4f9b\u4e86 D3D \u7684\u5b9e\u73b0\uff0c\u6700\u65b0\u7248\u5df2\u7ecf\u5254\u9664\uff0c\u6211\u4eec\u53ef\u4ee5\u5728 lrtc-plugin \u4ed3\u5e93\u5b9e\u73b0\u81ea\u5df1\u7684 D3D\uff0c\u6216\u8005\u5176\u4ed6\u7684\u6e32\u67d3\uff0c\u5982 QT OpenGL \u3002

\n

VideoProcess

\n

WebRTC \u5e76\u6ca1\u6709\u63d0\u4f9b\u89c6\u9891\u524d\u5904\u7406\uff08\u5982\uff1a\u7f8e\u989c\uff09\u3001\u540e\u5904\u7406\uff08\u5982\uff1a\u8d85\u5206\u8fa8\u7387\uff09\u7684\u63a5\u53e3\uff0c\u4f46\u662f\u6211\u4eec\u5b8c\u5168\u53ef\u4ee5\u50cf rtc::BitrateAllocationStrategy \u4e00\u6837\uff0c\u521b\u9020 VideoProcessInterface \u63a5\u53e3, \u5e76\u5728 lrtc-plugin \u4ed3\u5e93\u91cc\u5b9e\u73b0\u3002\n\"file\"\n\u8ba9 VideoProcessInterface \u540c\u65f6\u7ee7\u627f Sink \u548c Source \u63a5\u53e3\uff0c\u53ef\u4ee5\u65b9\u4fbf\u7684\u628a\u591a\u4e2a\u5bf9\u8c61\u4e32\u8054\u8d77\u6765\u3002

\n

\u5176\u4ed6 & Bugfix

\n

\u5176\u4ed6\u6838\u5fc3\u6a21\u5757\uff0c\u5982 JitterBuffer \u3001ICE \u7b49\uff0c\u76ee\u524d\u63a5\u89e6\u7684\u4e3b\u8981\u662f Bugfix\uff0c\u8fd8\u6ca1\u6709\u53d1\u73b0\u81ea\u5df1\u5b9a\u5236\u91cd\u5199\u7684\u5fc5\u8981\u3002

\n

Bugfix\uff0c\u5f80\u5f80\u53ea\u80fd\u4fee\u6539 light-rtc \u4ed3\u5e93\u3002\u4e00\u65b9\u9762\uff0c\u662f\u5c3d\u91cf\u628a Bugfix \u5185\u805a\u6210\u51fd\u6570\uff0c\u51cf\u5c11\u5bf9\u5df2\u6709\u4ee3\u7801\u7684\u4fee\u6539\uff1b\u53e6\u4e00\u65b9\u9762\uff0c\u5c3d\u91cf\u628a Bugfix \u8d21\u732e\u5230\u5f00\u6e90\u793e\u533a(Issue Tracker)\uff0c\u65e2\u4e3a\u5f00\u6e90\u793e\u533a\u505a\u4e86\u8d21\u732e\uff0c\u4e5f\u5f7b\u5e95\u907f\u514d\u4e86\u5347\u7ea7\u7684\u51b2\u7a81\u3002

\n

\u8d21\u732e\u5230\u5f00\u6e90\u793e\u533a\uff0c\u5f80\u5f80\u6bd4\u60f3\u8c61\u7684\u8981\u590d\u6742\uff0c\u4f46\u4e5f\u66f4\u80fd\u953b\u70bc\u4eba\u3002\u5728\u7279\u5b9a\u573a\u666f\uff0c\u5f80\u5f80\u53ea\u7528\u4e86 WebRTC \u4e00\u90e8\u5206\u80fd\u529b\uff0c\u5982\u89c6\u9891 JitterBuffer\uff0c\u4e00\u4e2a Bugfix \u53ef\u80fd\u53ea\u8003\u8651\u5230\u4e86 H264\uff0c\u8d21\u732e\u5230\u5f00\u6e90\u793e\u533a\u65f6\uff0c\u5219\u9700\u8981\u540c\u65f6\u517c\u987e VP8/VP9\uff0c\u751a\u81f3\u662f\u5c06\u6765\u7684 AV1 \u3002\u5728\u8fd9\u4e2a\u8fc7\u7a0b\u4e2d\uff0cGoogle \u5de5\u7a0b\u5e08\u4f1a\u5728 Code Review \u4e2d\u4e0e\u4f60\u4eb2\u5bc6\u5207\u78cb\uff0c\u5176\u5b9e\u662f\u975e\u5e38\u597d\u7684\u953b\u70bc\u673a\u4f1a\uff0c\u8fdb\u4e00\u6b65\u63d0\u9ad8\u5bf9 WebRTC \u7684\u8ba4\u8bc6\u3002

\n

\u53c2\u8003

\n

WebRTC m74 \u6e90\u7801

\n

RSFEC\uff1a

\n\n

CC

\n\n" }, { "author": { "url": "member/wwjvtwoex", "name": "wwjvtwoex", "avatar": "https://cdn.v2ex.com/avatar/f222/0563/145193_large.png?m=1459950174" }, "url": "t/723156", "date_modified": "2020-11-09T04:41:15+00:00", "content_html": "\u8fd9\u91cc\u662f\u6f14\u793a\u94fe\u63a5 https://owebio.github.io/serverless-webrtc-chat/

\u7cfb\u7edf: Manjaro Linux \u6700\u540e\u66f4\u65b0

Firefox 82 \u5728\u7b2c 3 \u6b65 \u201cCREATE Participant'S SDP\u201d \u540e\u7b49\u5f85\u51e0\u79d2\u949f\uff0c\u7a0b\u5e8f\u5931\u8d25
\u9519\u8bef\u4fe1\u606f\u662f \"WebRTC: ICE failed, add a STUN server and see about:webrtc for more details\"

Firefix 83 \u5f00\u53d1\u7248 \u80fd\u591f\u6b63\u5e38\u8fd0\u884c\u4e0a\u9762\u7684\u6f14\u793a

Chrome 81 \u80fd\u591f\u6b63\u5e38\u8fd0\u884c\u4e0a\u9762\u7684\u6f14\u793a", "date_published": "2020-11-09T04:38:50+00:00", "title": "\u6c42\u52a9: serverless-webrtc-chat \u5728 Firefox \u4e0b\u5931\u8d25", "id": "t/723156" }, { "author": { "url": "member/kekxv", "name": "kekxv", "avatar": "https://cdn.v2ex.com/gravatar/2c5e4e866a976b0a86e710350f44e18b?s=73&d=retro" }, "url": "t/695756", "title": "\u6c42\u52a9\u5173\u4e8e WebRTC \u53ea\u80fd\u5728\u5c40\u57df\u7f51\u5efa\u7acb\u6210\u529f\u95ee\u9898", "id": "t/695756", "date_published": "2020-08-05T02:52:48+00:00", "content_html": "

\u6211\u6574\u4e86\u4e2a golang + websocket + WebRTC \u7684\uff0c\u539f\u672c\u662f\u4e3a\u4e86\u5c41 2 \u5c41\u4f20\u6587\u4ef6\uff0c

\n

\u4f46\u662f\u73b0\u5728WebRTC\u53ea\u5728\u5c40\u57df\u7f51\u5185\u5efa\u7acb\u6210\u529f\uff0c\n\u8fd9\u6837\u7684\u8bdd\uff0c\u5c31\u53ea\u80fd\u4f7f\u7528 websocket \u901a\u8fc7\u670d\u52a1\u7aef\u8fdb\u884c\u8f6c\u53d1\uff0c

\n

\u4f46\u662f\u8fd9\u6837\u8dd1\u670d\u52a1\u5668\u5e26\u5bbd\uff0c\u6709\u70b9\u8d35\u554a\uff0c\u80fd\u7ed9\u70b9\u5565\u5b50\u5efa\u8bae\u6216\u8005\u5e2e\u5fd9\u770b\u770b\u662f\u56e0\u4e3a\u4ec0\u4e48\u53ea\u80fd\u5728\u5c40\u57df\u7f51\u5efa\u7acb\u6210\u529f\uff1f

\n

\u9879\u76ee\u5728 https://github.com/kGoChat

\n

\u7528\u7684\u662f golang \u548c vue

\n" }, { "author": { "url": "member/zombiecong", "name": "zombiecong", "avatar": "https://cdn.v2ex.com/avatar/1823/72a1/103701_large.png?m=1775028960" }, "url": "t/673033", "title": "\u6b63\u5728\u505a\u4e00\u4e2a\u5f00\u6e90 WebRTC \u9879\u76ee\uff0c\u6709\u611f\u5174\u8da3\u7684\u5c0f\u4f19\u4f34\u5417\u3002", "id": "t/673033", "date_published": "2020-05-18T14:27:10+00:00", "content_html": "

\u6700\u8fd1\u4e00\u4e2a\u6708\u6bd4\u8f83\u95f2\uff0c\u641e\u4e86\u4e00\u4e2a\u9879\u76ee\u3002https://github.com/0-u-0

\n

\u4f46\u662f\u8981\u505a\u4e1c\u897f\u5b9e\u5728\u592a\u591a\uff0c\u641e\u4e86\u4e00\u4e2a\u534a\u6708\u611f\u89c9\u5feb\u4e0d\u884c\u4e86\u3002\u611f\u5174\u8da3\u7684\u5144\u5f1f\u53ef\u4ee5\u5e2e\u5e2e\u6211\ud83d\ude2d

\n

\u57fa\u672c\u4ecb\u7ecd

\n

\u60f3\u8981\u505a\u4e00\u4e2a\u57fa\u4e8e WebRTC \u7684\u6613\u7528\u7684\u97f3\u89c6\u9891\u67b6\u6784\uff0c\u5305\u62ec \u6d41\u5a92\u4f53\u670d\u52a1(media server)\uff0c\u4fe1\u4ee4\u670d\u52a1\u5668(signal server)\uff0cWeb\uff0ciOS \u548c Android \u7aef SDK \u3002\u4f7f\u7528 SDK\uff0c\u53ef\u4ee5\u8f7b\u677e\u5bb9\u6613\u6784\u5efa videoChat app \u3002\n\u57fa\u672c\u67b6\u5b50\uff1a\n\"\"

\n

\u76ee\u6807\uff1a

\n\n

\u672a\u6765

\n\n

\u8bbe\u8ba1

\n\n
\n

\u6709\u51e0\u4e2a\u95ee\u9898\uff0c\u5e0c\u671b\u80fd\u6709\u5927\u795e\u80fd\u5e2e\u6211\u89e3\u7b54\u4e00\u4e0b

\n
    \n
  1. 4\uff0c5 \u5e74\u6ca1\u641eAndroid \uff0ckotlin\u7684\u751f\u6001\u600e\u4e48\u6837\uff0cSDK \u7528 kotlin \u505a\uff0c\u6709\u6ca1\u6709\u4ec0\u4e48\u5927\u5751\uff1f
  2. \n
  3. Web SDK \u662f\u7528Typescript\u5199\u7684\uff0cSDK\u7684API\u6587\u6863\u662f\u76f4\u63a5\u7528Typescript\u4ee3\u7801\u751f\u6210\uff0c\u6bd4\u5982\u7528 typedoc\uff0c\u8fd8\u662f\u751f\u6210 Javascript\u4e4b\u540e\uff0c\u518d\u7528jsdoc\u751f\u6210\uff1f
  4. \n
\n
\n

\u603b\u4e4b\uff0c\u6b22\u8fce pull request

\n" }, { "author": { "url": "member/wazon", "name": "wazon", "avatar": "https://cdn.v2ex.com/gravatar/e3bbd81c66d55fca4aaf65d929342bce?s=73&d=retro" }, "url": "t/654273", "title": "sharedrop P2P \u6587\u4ef6\u5206\u4eab", "id": "t/654273", "date_published": "2020-03-19T07:38:11+00:00", "content_html": "HTML5 clone of Apple's AirDrop - easy P2P file transfer powered by WebRTC
https://www.sharedrop.io
https://github.com/cowbell/sharedrop
\u8bd5\u4e86\u4e0b\u633a\u597d\u7528\u7684\uff0c\u597d\u50cf\u6ca1\u770b\u89c1\u6709\u4eba\u63a8\u8350\u8fc7" }, { "author": { "url": "member/abc1310054026", "name": "abc1310054026", "avatar": "https://cdn.v2ex.com/gravatar/7c6b57e7cf36d3fb2a2b92eb40f02546?s=73&d=retro" }, "url": "t/626455", "title": "webrtc \u4e0d\u662f\u624d\u6709\u7684\u6280\u672f\uff0c\u5e94\u7528\u9886\u609f\u4e3b\u8981\u662f\u7f51\u9875\u7aef\uff0c\u73b0\u5728\u5b89\u5353\u7248\u672c\u66f4\u65b0\u5f88\u5feb\uff0c\u4e3a\u4ec0\u4e48\u5185\u7f6e\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u8fd9\u79cd\u51e0\u5e74\u524d\u5c31\u6709\u7684\u65b0\u6280\u672f\uff0c\u8fd9\u4e2a\u4e0d\u5408\u7406", "id": "t/626455", "date_published": "2019-12-06T03:24:27+00:00", "content_html": "
\n

\u5ba2\u6237\u63d0\u95ee\uff1awebrtc \u4e0d\u662f\u624d\u6709\u7684\u6280\u672f\uff0c\u5e94\u7528\u9886\u609f\u4e3b\u8981\u662f\u7f51\u9875\u7aef\uff0c\u73b0\u5728\u5b89\u5353\u7248\u672c\u66f4\u65b0\u5f88\u5feb\uff0c\u4e3a\u4ec0\u4e48\u5185\u7f6e\u6d4f\u89c8\u5668\u4e0d\u652f\u6301\u8fd9> \u79cd\u51e0\u5e74\u524d\u5c31\u6709\u7684\u65b0\u6280\u672f\uff0c\u8fd9\u4e2a\u4e0d\u5408\u7406

\n
\n

\u5404\u4f4d\u6709\u4ec0\u4e48\u770b\u6cd5\ud83d\ude43

\n" }, { "author": { "url": "member/asd4324193", "name": "asd4324193", "avatar": "https://cdn.v2ex.com/gravatar/be53d6a729a1c27bbd10ac8877888e4e?s=73&d=retro" }, "url": "t/544292", "title": "Webtorrent \u5728\u5185\u7f51\u73af\u5883\u8fdb\u884c\u64ad\u79cd\u7684\u60f3\u6cd5", "id": "t/544292", "date_published": "2019-03-13T12:14:25+00:00", "content_html": "

Webtorrent \u5728\u5185\u7f51\u73af\u5883\u8fdb\u884c\u64ad\u79cd~\n\u76ee\u524d\u6709\u4e00\u4e2a\u60f3\u6cd5\uff0c\u672c\u5730\u670d\u52a1\u5668\u642d\u5efa\u73af\u5883\u7528 webtorrent \u8fdb\u884c\u64ad\u79cd\uff0c\u4f46\u662f\u64ad\u79cd\u540e\u3002\n\u7535\u4fe1\uff0c\u8054\u901a\u548c\u79fb\u52a8\u662f\u4e0d\u80fd\u4e92\u8054\u7684\uff0c\u53ea\u80fd\u5355\u4e2a\u65b9\u9762\u3002\n\u6211\u8fd9\u4e00\u770b\uff0c\u5c31\u8bd5\u8bd5 frp \u8fdb\u884c\u6253\u6d1e\uff0c\u6b63\u597d\u770b\u5230 P2P \u70b9\u5bf9\u70b9\u53ef\u4ee5\u4e0d\u7528\u8d70\u670d\u52a1\u7aef\u7684\u6d41\u91cf\u3002\n\u8ddf\u516c\u7f51\u670d\u52a1\u5668\u90a3\u5757\u8fdb\u884c\u4e92\u901a\u540e\uff0c\u53d1\u73b0\u672c\u5730\u670d\u52a1\u5668\u64ad\u79cd\u4f9d\u65e7\u4e0d\u80fd\u4e92\u901a.\n\u7136\u540e\u60f3\u5230\u4e86 Websocket \u548c WebRTC\nWebRTC \u8fd9\u5757\u662f\u4e0d\u662f\u4e5f\u5f97\u6253\u6d1e\uff1f\u4f7f\u7528 Coturn \uff1f

\n" }, { "author": { "url": "member/allanzyne", "name": "allanzyne", "avatar": "https://cdn.v2ex.com/avatar/6e80/d726/187290_large.png?m=1472223073" }, "url": "t/533118", "title": "\u80fd\u5426\u7528 WebRTC \u505a\u4e00\u4e2a\u5c40\u57df\u7f51\u7684\u89c6\u9891\u64ad\u653e\u670d\u52a1\uff1f", "id": "t/533118", "date_published": "2019-02-05T11:28:07+00:00", "content_html": "

\u4e0d\u662f\u5f88\u4e86\u89e3\u8fd9\u4e2a\u6280\u672f\uff0c\u60f3\u6cd5\u662f\u7528 ffmpeg + WebRTC\uff0c\u4e0d\u77e5\u9053\u6709\u4eba\u63a2\u7d22\u8fc7\u6ca1\uff1f

\n" }, { "author": { "url": "member/liuhy1991", "name": "liuhy1991", "avatar": "https://cdn.v2ex.com/avatar/f58d/478e/57185_large.png?m=1394144458" }, "url": "t/524256", "title": "\u6c42\u52a9\u5404\u4f4d\u5927\u795e\uff0c\u56fd\u5185\u76ee\u524d\u4e3b\u6d41\u6d4f\u89c8\u5668\u652f\u6301 MediaRecorder \u5417\uff1f", "id": "t/524256", "date_published": "2019-01-05T14:07:08+00:00", "content_html": "

\u9879\u76ee\u8981\u7528 Web API MediaRecorder \u5b9e\u73b0\u4e2a\u529f\u80fd\uff0cChrome for Android \u76ee\u524d\u5df2\u7ecf\u652f\u6301\u4e86\uff0c\u4e0d\u77e5\u9053\u56fd\u5185\u7684\u4f8b\u5982 QQ \u6d4f\u89c8\u5668\uff0cUC \u6d4f\u89c8\u5668\uff0c360 \u6d4f\u89c8\u5668\uff0c\u767e\u5ea6\u6d4f\u89c8\u5668\u652f\u6301\u5982\u4f55\u3002\n\u70e6\u8bf7\u4e86\u89e3\u7684\u5927\u795e\u89e3\u7b54\u4e00\u4e0b\uff5e\uff5e

\n" }, { "author": { "url": "member/gggxxxx", "name": "gggxxxx", "avatar": "https://cdn.v2ex.com/gravatar/3cea951d0888d8348538ec00c46153d6?s=73&d=retro" }, "url": "t/520460", "title": "\u516c\u53f8\u8981\u6d4b\u8bd5 webrtc \u662f\u4e0d\u662f\u4e70\u4e2a\u56fd\u5185\u963f\u91cc\u4e91\u4ec0\u4e48\u7684\uff1f", "id": "t/520460", "date_published": "2018-12-24T06:27:15+00:00", "content_html": "

\u5982\u9898\u3002\n\u8fd9\u4e2a\u8d39\u7528\u4e0d\u8d35\u5427\uff1f\u4e0d\u8d35\u7684\u8bdd\uff0c\u5148\u81ea\u5df1\u638f\u8170\u5305\u7b97\u4e86\u3002\n\u53e6\u5916\uff0c\u56fd\u5185\u963f\u91cc\u4e91\u4ec0\u4e48\u7684\uff0c\u8d2d\u4e70\u540e\u5f00\u4e2a hls \u76f4\u64ad\u4ec0\u4e48\u7684\u4e5f\u4e0d\u53d7\u9650\u5236\u5427\uff1f\n\u521a\u8f6c\u5230\u8fd9\u4e2a\u9886\u57df\uff0c\u6709\u4e9b\u6280\u672f\u7ec6\u8282\u4e0d\u719f\u8bf7\u5927\u4f6c\u4e9b\u6307\u70b9\u4e0b

\n" }, { "author": { "url": "member/xunyu", "name": "xunyu", "avatar": "https://cdn.v2ex.com/avatar/8ab1/b76c/36639_large.png?m=1405500854" }, "url": "t/386852", "title": "kurento room \u670d\u52a1\u7aef Python \u9002\u914d\u65f6 iceCandidate \u5185\u5bb9\u600e\u4e48\u8bbe\u7f6e", "id": "t/386852", "date_published": "2017-08-30T05:02:47+00:00", "content_html": "

\u6211\u73b0\u5728\u5728\u505a kurento room \u7684 python \u670d\u52a1\u7aef\u7f16\u5199,\u73b0\u5728\u804a\u5929\u5ba4\u5185\u65e0\u6cd5\u5f97\u5230\u5176\u4ed6\u4eba\u7684\u56fe\u50cf,\u81ea\u5df1\u662f\u53ef\u4ee5\u7684,console \u62a5\u9519\u662f stun \u914d\u7f6e\u9519\u8bef,\u4f46 Java \u7aef\u662f\u53ef\u4ee5\u6b63\u5e38\u4f7f\u7528\u7684,\u521d\u6b65\u6000\u7591\u662f\u53d1\u9001 iceCandidate \u5185\u5bb9\u9519\u8bef,\u4e0d\u77e5\u9053\u7f51\u9875\u7aef\u53d1\u9001\u8fc7\u6765\u7684 OnIceCandidate \u600e\u4e48\u8f6c\u6362\u4e3a iceCandidate \u7684\u5185\u5bb9\u53d1\u8fc7\u53bb,\u8c22\u8c22

\n" }, { "author": { "url": "member/xunyu", "name": "xunyu", "avatar": "https://cdn.v2ex.com/avatar/8ab1/b76c/36639_large.png?m=1405500854" }, "url": "t/386834", "title": "kurento \u7684 Python \u6539\u9020\u95ee\u9898", "id": "t/386834", "date_published": "2017-08-30T03:59:08+00:00", "content_html": "\u6211\u5728\u505a kurento room python \u7248\u7684\u8fc7\u7a0b\u4e2d\u78b0\u5230\u4e86 iceCandidate \u7684\u95ee\u9898\uff0c\u5728\u4e0d\u8bbe\u7f6e stun \u670d\u52a1\u5668\u7684\u60c5\u51b5\u4e0b java \u7248\u672c\u53ef\u4ee5\u770b\u5230\u5bf9\u65b9\u753b\u9762\uff0c\u6211\u6539\u9020\u7684 python \u7248\u672c\u53ea\u80fd\u770b\u5230\u672c\u5730\u7684\uff0c\u521d\u6b65\u6000\u7591\u662f iceCandidate \u8fd9\u4e2a\u6d88\u606f\u4e0d\u5bf9\uff0c\u6709\u4eba\u77e5\u9053\u670d\u52a1\u7aef\u63a5\u53d7\u4e86 onIceCandidate\uff0c\u5e94\u8be5\u600e\u4e48\u7ed9\u6d4f\u89c8\u5668\u53d1\u9001 iceCandidate \u6d88\u606f\u5185\u5bb9\u4e0d\uff0c\u8c22\u8c22" }, { "author": { "url": "member/hain", "name": "hain", "avatar": "https://cdn.v2ex.com/avatar/eb0e/901a/176218_large.png?m=1470880349" }, "url": "t/330867", "title": "\uff3b \u5317\u4eac\uff3d WebRTC Meetup, 1 \u6708 8 \u65e5 node-party @ \u5fae\u8f6f\u5927\u53a6\uff0c\u62a5\u540d\u4ece\u901f !", "id": "t/330867", "date_published": "2016-12-28T14:26:11+00:00", "content_html": "

What is Node Party?

\n

\u6bcf\u6708\u7ec4\u7ec7 Javascript/Node \u5f00\u53d1\u8005\u805a\u4f1a\uff0c\u5173\u6ce8\u70ed\u95e8\u7684\u524d\u7aef\u3001\u540e\u7aef\u6846\u67b6\uff0c\u5f00\u53d1\u5de5\u5177\u548c\u65b9\u6cd5\u3002

\n

\uff0a \u5b66\u4e60\u65b0\u4e1c\u897f\n\uff0a \u8ba4\u8bc6\u65b0\u670b\u53cb\n\uff0a \u805a\u9910

\n

\u6211\u4eec\u4f1a\u4e3a\u4f60\u51c6\u5907\uff1a\n\u5496\u5561\uff0c\u751c\u70b9\uff0c\u7206\u7c73\u82b1\u548c\u52a8\u542c\u7684\u97f3\u4e50\uff0c\u4e00\u8d77\u5ea6\u8fc7\u4e00\u4e2a\u6109\u5feb\u7684\u4e0b\u5348\u3002

\n

\u65f6\u95f4

\n

2017 \u5e74 1 \u6708 8 \u65e5 \u661f\u671f\u65e5 \u4e0b\u5348 13:00 \uff5e 17:00

\n

\u5730\u70b9

\n

\u5fae\u8f6f\u5927\u53a6 2 \u53f7\u697c 2 \u697c\u9890\u548c\u56ed\u4f1a\u8bae\u5ba4

\n

\u5730\u5740: \u5317\u4eac\u6d77\u6dc0\u533a\u6d77\u6dc0\u533a\u4e39\u68f1\u8857 5 \u53f7\u5fae\u8f6f\u5927\u53a6 Tower 2, 2F \u9890\u548c\u56ed\u4f1a\u8bae\u5ba4 \u767e\u5ea6\u5730\u56fe

\n

\u62a5\u540d\u5730\u5740

\n

\u4e3a\u4e86\u63d0\u5347\u6d3b\u52a8\u8d28\u91cf\uff0c\u9f13\u52b1\u5206\u4eab\uff0c\u672c\u671f node-party \u8fdb\u884c\u552e\u7968\uff0c\u65e9\u9e1f\u7968\u548c\u6807\u51c6\u7968\u53ea\u662f\u4ef7\u683c\u4e0a\u4e0d\u540c\uff0c\u5206\u522b\u662f 29 \u5143\u548c 49 \u5143\u3002

\n

http://www.bagevent.com/event/331797

\n

\u5185\u5bb9

\n

13:00 ~ 13:30 \u5165\u573a

\n

13:20 - 13:30 \u5fae\u8f6f\u65b0\u89c6\u754c\u5f00\u53d1\u8005\u6c99\u9f99\u7b80\u4ecb - \u738b\u6dfb @\u5fae\u8f6f

\n\n

\u738b\u6dfb\uff0c\u5fae\u8f6f\u65b0\u89c6\u754c\u9879\u76ee\u8d1f\u8d23\u4eba

\n

13:30 - 14:30 WebRTC \u5feb\u901f\u5165\u95e8 - \u5218\u8fde\u54cd @dotEngine

\n\n

\u5218\u8fde\u54cd, Founder@dotEngine, https://dot.cc/.\n\u97f3\u89c6\u9891\u901a\u8bdd\u4e91, github/notedit

\n\n

WebRTC \u7684\u524d\u4e16\u4eca\u751f\nWebRTC \u7684\u57fa\u7840\u67b6\u6784\n\u57fa\u7840\u67b6\u6784\u8be6\u89e3

\n

14:50 - 15:50 WebRTC \u5f00\u53d1\u5b9e\u8df5

\n\n

James Pan, \u91ce\u72d7\u79d1\u6280\u97f3\u89c6\u9891\u9879\u76ee\u8d1f\u8d23\u4eba\u3002

\n\n

WebRTC \u7b80\u4ecb\n\u56db\u5927\u6838\u5fc3\uff1a\u8fde\u63a5\uff0c\u901a\u4fe1\uff0c\u97f3\u89c6\u9891\u5904\u7406\u548c\u5b89\u5168\n\u4f7f\u7528 WebRTC \u5f00\u53d1\u89c6\u9891\u901a\u8bdd - 3.1 WebRTC \u901a\u4fe1\u6d41\u7a0b - 3.2 \u4f7f\u7528\u6b65\u9aa4\uff0c\u6838\u5fc3\u65b9\u6cd5\u548c\u6ce8\u610f\u70b9

\n

16:10 - 17:00 \u76f4\u64ad\u670d\u52a1\u5b9e\u8df5

\n\n

\u674e\u667a\u7ef4, Founder@\u8da3\u76f4\u64ad, http://m.quzhiboapp.com/\n\u524d LeanCloud \u5de5\u7a0b\u5e08\uff0c\u5fae\u535a @lzwjava

\n\n

\u76f4\u64ad\u7684\u57fa\u7840\n\u81ea\u5efa\u76f4\u64ad\u670d\u52a1\u5668\u96c6\u7fa4\n\u661f\u57df\u3001\u963f\u91cc\u4e91\u7b49\u76f4\u64ad CDN\n\u624b\u673a H5 \u3001\u684c\u9762\u7f51\u9875\u4f18\u5316\n\u8d39\u7528\u6210\u672c\u3001\u76f4\u64ad\u884c\u4e1a\u611f\u609f

\n

\u5f80\u671f\u56de\u987e

\n

\u7167\u7247\uff0c PPT \uff0c Slides https://github.com/rockq-org/node-party

\n" }, { "author": { "url": "member/veggie", "name": "veggie", "avatar": "https://cdn.v2ex.com/avatar/b3b0/b34e/32137_large.png?m=1357885428" }, "url": "t/312567", "title": "\u6709\u6ca1\u6709\u597d\u7528\u7684\u8bed\u97f3\u76f4\u64ad\u670d\u52a1\u63a8\u8350\uff1f", "id": "t/312567", "date_published": "2016-10-13T09:47:17+00:00", "content_html": "

\u6c42\u4e00\u6b3e html5 \u5b9e\u73b0\u7684\u8bed\u97f3\u76f4\u64ad\u6846\u67b6\uff0c\u8c03\u67e5\u4e86\u4e00\u6bb5\u65f6\u95f4\uff0c\u53d1\u73b0\u5ef6\u8fdf\u4f4e\u7684\u57fa\u672c\u53ea\u6709 rtmp flash \u90a3\u5957\uff0c\u516c\u53f8\u81ea\u5df1\u7528\u7684 red5 \uff0c\u4f46\u662f\u4e5f\u662f flash \u7684\uff0c webrtc \u4e0d\u9002\u5408\u5e7f\u64ad\u6a21\u5f0f\uff0c webRTC \u7f51\u5173\u6a21\u5f0f\u627e\u5230 Janus WebRTC Gateway \uff0c\u4f46\u662f\u597d\u50cf\u5f88\u590d\u6742\uff0c\u6682\u65f6\u6ca1\u6709\u5c1d\u8bd5\uff0c\u4e0d\u77e5\u9053\u6709\u6ca1\u6709\u5176\u4ed6\u65b9\u6848\uff1f

\n" }, { "author": { "url": "member/Akagi201", "name": "Akagi201", "avatar": "https://cdn.v2ex.com/avatar/5792/a227/20979_large.png?m=1583813501" }, "url": "t/304915", "title": "\u7f16\u8bd1\u4e86 WebRTC \u548c Janus Gateway \u7684 API \u6587\u6863", "id": "t/304915", "date_published": "2016-09-08T12:03:37+00:00", "content_html": "\n" }, { "author": { "url": "member/notedit", "name": "notedit", "avatar": "https://cdn.v2ex.com/avatar/f6d1/ecd1/11788_large.png?m=1381820822" }, "url": "t/297733", "title": "\u7f16\u8bd1\u4e86 iOS \u548c Android \u5e73\u53f0\u4e0a\u6700\u65b0\u7684 webrtc \u9700\u8981\u7684\u53ef\u4ee5\u6765\u7528", "id": "t/297733", "date_published": "2016-08-07T12:26:09+00:00", "content_html": "\u81ea\u5df1\u7684\u4ea7\u54c1\u4e5f\u5728\u7528\u8fd9\u4e2a \u4f1a\u4fdd\u6301\u66f4\u65b0\r
\r
\r
Android\r
\r
https://github.com/notedit/libWebRTC-Android\r
\r
\r
iOS\r
\r
https://github.com/notedit/libWebRTC" }, { "author": { "url": "member/doulmi", "name": "doulmi", "avatar": "https://cdn.v2ex.com/gravatar/ff57290f807702145d74c6bf855e1fff?s=73&d=retro" }, "url": "t/255128", "title": "\u5173\u4e8e WEB \u5728\u7ebf\u8bed\u97f3\u804a\u5929\u7cfb\u7edf", "id": "t/255128", "date_published": "2016-02-03T00:57:13+00:00", "content_html": "

\u5927\u5bb6\u6709\u5f00\u53d1\u5173\u4e8e WEB \u5728\u7ebf\u8bed\u97f3\u804a\u5929\u7cfb\u7edf\u7684\u7ecf\u9a8c\u5417\uff1f
\n\u6709\u4ec0\u4e48\u76f8\u5173\u7684\u5f00\u6e90\u8f6f\u4ef6\u6bd4\u8f83\u597d\u7528\uff1f Google WebRTC \u6709\u4eba\u7528\u8fc7\u5417\uff1f

\n" }, { "author": { "url": "member/Akagi201", "name": "Akagi201", "avatar": "https://cdn.v2ex.com/avatar/5792/a227/20979_large.png?m=1583813501" }, "url": "t/243247", "title": "awesome-webrtc: http://openrtc.io/", "id": "t/243247", "date_published": "2015-12-13T11:13:45+00:00", "content_html": "

http://openrtc.io/

\n\n

\u6b22\u8fce Star \u8ddf Fork. \u4f1a\u4e0d\u65ad\u66f4\u65b0.

\n" }, { "author": { "url": "member/kkcheng", "name": "kkcheng", "avatar": "https://cdn.v2ex.com/avatar/9f8e/bf98/106920_large.png?m=1431678457" }, "url": "t/186847", "date_modified": "2015-04-27T16:24:54+00:00", "content_html": "

\u7f51\u4e0a\u627e\u4e0d\u5230\u51e0\u4e2a\u5b9e\u7528\u4f8b\u5b50

\n", "date_published": "2015-04-27T16:18:42+00:00", "title": "\u6709\u7528\u8fc7 WebRTC \u7684\u5417\uff1f\u60f3\u4e86\u89e3\u4e00\u4e0b\u5f00\u53d1\u96be\u5ea6", "id": "t/186847" }, { "author": { "url": "member/Kai", "name": "Kai", "avatar": "https://cdn.v2ex.com/avatar/021b/bc7e/1024_large.png?m=1657391813" }, "url": "t/170627", "title": "WebRTC 1.0", "id": "t/170627", "date_published": "2015-02-12T17:09:34+00:00", "content_html": "http://www.w3.org/TR/2015/WD-webrtc-20150210/" }, { "author": { "url": "member/pebutuoy", "name": "pebutuoy", "avatar": "https://cdn.v2ex.com/avatar/ab69/eb58/55226_large.png?m=1391401846" }, "url": "t/100379", "title": "WebRTC \u6280\u672f\u4ecb\u7ecd", "id": "t/100379", "date_published": "2014-02-15T12:55:34+00:00", "content_html": "\u6f14\u8bb2\u89c6\u9891\u62cd\u6444\u4e8eFluent 2013 \u5927\u4f1a
http://geekcantalk.com/post/76714511113/a-practical-introduction-to-webrtc-fluent-2013

WebRTC is an exciting new web technology that will enable web developers to harness real-time audio and video capabilities using a set of Javascript APIs. WebRTC allows web pages to access local multimedia devices like a webcam and microphone, and transmit these media streams to another WebRTC capable browser via a peer-to-peer network channel. These media streams can also be accompanied by a powerful data channel that lets developer exchange arbitrary data between two peers!
In this session, we\u2019ll be diving deep into the various Javascript APIs (primarily getUserMedia and PeerConnection) that make all of this possible. We\u2019ll also go through the process of building a real WebRTC powered web app and discuss some ways in which these apps can be deployed in the real world.
Participants can expect to walk away with enough knowledge to get them started with writing a WebRTC application. There are no prerequisites other than an intermediate knowledge of Javascript and HTML." }, { "author": { "url": "member/the13matrix", "name": "the13matrix", "avatar": "https://cdn.v2ex.com/avatar/ff65/4eac/50839_large.png?m=1389559137" }, "url": "t/98147", "date_modified": "2014-01-23T22:35:12+00:00", "content_html": "\u53ef\u4ee5\u76f4\u63a5\u4ece\u672c\u5730\u8bfb\u53d6IP\u3002\u548cipconfig /all\u770b\u5230\u7684IP\u4e00\u6837\u3002
\u5982\u679c\u7535\u8111\u76f4\u63a5\u64ad\u53f7\u4e0a\u7f51\uff0c\u5219\u83b7\u53d6\u5230\u7684\u5c31\u662f\u516c\u7f51IP\u3002\u5982\u679c\u662f\u5bb6\u5ead\u3001\u5b66\u6821\u3001\u516c\u53f8\u7684\u5185\u7f51\uff0c\u83b7\u53d6\u5230\u7684\u5c31\u662f\u5185\u7f51IP\u3002\u5982\u679c\u7cfb\u7edf\u91cc\u6709\u865a\u62df\u7f51\u5361\uff0c\u865a\u62df\u7f51\u5361IP\u4e5f\u52a0\u5165\u5217\u8868\u3002
\u6d4b\u8bd5\u4ee3\u7801\uff1a\uff08\u5bf9Chrome\u548cFirefox\u6709\u6548\uff09
<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
<html xmlns=\"http://www.w3.org/1999/xhtml\">
<head>
<meta http-equiv=\"Content-Type\" cOntent=\"text/html; charset=utf-8\" />
<title>\u83b7\u53d6\u5185\u7f51IP</title>
</head>
<body>
\u60a8\u7684\u5185\u7f51IP\uff1a
<span id=\"list\"></span>
<script>
// NOTE: window.RTCPeerConnection is \"not a constructor\" in FF22/23
var RTCPeerCOnnection= /*window.RTCPeerConnection ||*/ window.webkitRTCPeerConnection || window.mozRTCPeerConnection;
if (RTCPeerConnection) (function () {
var rtc = new RTCPeerConnection({iceServers:[]});
if (window.mozRTCPeerConnection) { // FF needs a channel/stream to proceed
rtc.createDataChannel('', {reliable:false});
};
rtc.Onicecandidate= function (evt) {
if (evt.candidate) grepSDP(evt.candidate.candidate);
};
rtc.createOffer(function (offerDesc) {
grepSDP(offerDesc.sdp);
rtc.setLocalDescription(offerDesc);
}, function (e) { console.warn(\"offer failed\", e); });
var addrs = Object.create(null);
addrs[\"0.0.0.0\"] = false;
function updateDisplay(newAddr) {
if (newAddr in addrs) return;
else addrs[newAddr] = true;
var displayAddrs = Object.keys(addrs).filter(function (k) { return addrs[k]; });
document.getElementById('list').innerHTML = displayAddrs.join(\" or perhaps \") || \"n/a\";
}
function grepSDP(sdp) {
var hosts = [];
sdp.split('\\r\\n').forEach(function (line) { // c.f.http://tools.ietf.org/html/rfc4566#page-39
if (~line.indexOf(\"a=candidate\")) { //http://tools.ietf.org/html/rfc4566#section-5.13
var parts = line.split(' '), //http://tools.ietf.org/html/rfc5245#section-15.1
addr = parts[4],
type = parts[7];
if (type === 'host') updateDisplay(addr);
} else if (~line.indexOf(\"c=\")) { //http://tools.ietf.org/html/rfc4566#section-5.7
var parts = line.split(' '),
addr = parts[2];
updateDisplay(addr);
}
});
}
})(); else {
document.getElementById('list').innerHTML = \"<code>ifconfig | grep inet | grep -v inet6 | cut -d\\\" \\\" -f2 | tail -n1</code>\";
document.getElementById('list').nextSibling.textCOntent= \"In Chrome and Firefox your IP should display automatically, by the power of WebRTCskull.\";
}
</script>
</body>
</html>
\u5efa\u7f51\u7ad9\u7684\u670b\u53cb\uff0c\u53ef\u4ee5\u7528\u8fd9\u4e2a\u5224\u65ad\u8bbf\u5ba2\u662f\u5185\u7f51\u7528\u6237\u8fd8\u662f\u516c\u7f51\u3002\u5e76\u4e14\u83b7\u53d6\u8bbf\u5ba2\u5185\u7f51IP\u3002
\u4e0d\u7ba1\u4f60\u7528\u4e86\u591a\u5c11\u5c42\u533f\u540d\u4ee3\u7406/VPN\uff0c\u8fd9\u6bb5\u4ee3\u7801\u90fd\u80fd\u76f4\u63a5\u63d0\u53d6\u672c\u5730IP\u3002\u7136\u540e\u4e00\u4e2a\u5f02\u6b65\u8bf7\u6c42\uff0c\u5c31\u53ef\u4ee5\u88ab\u670d\u52a1\u7aef\u63d0\u53d6\u3002\u6d4f\u89c8\u5668\u65e0\u4efb\u4f55\u5b89\u5168\u63d0\u793a\u3002", "date_published": "2014-01-23T12:54:21+00:00", "title": "\u600e\u6837\u7981\u7528\u6d4f\u89c8\u5668\u7684WebRTC\uff1f\u8fd9\u4e1c\u897f\u5c45\u7136\u80fd\u8bfb\u53d6\u672c\u5730IP\uff01\uff01", "id": "t/98147" }, { "author": { "url": "member/ihacku", "name": "ihacku", "avatar": "https://cdn.v2ex.com/avatar/c8cd/63e1/3073_large.png?m=1675398764" }, "url": "t/88384", "title": "webtorrent - BitTorrent over WebRTC", "id": "t/88384", "date_published": "2013-11-07T04:37:45+00:00", "content_html": "https://github.com/feross/webtorrent" }, { "author": { "url": "member/xiaojay", "name": "xiaojay", "avatar": "https://cdn.v2ex.com/avatar/d9d4/f495/46_large.png?m=1335074561" }, "url": "t/81948", "title": "\u7528 webrtc \u5199\u4e2a\u7c7b\u4f3c btsync \u7684\u5de5\u5177\u53ef\u884c\u4e0d\uff1f", "id": "t/81948", "date_published": "2013-09-10T08:54:03+00:00", "content_html": "btsync \u5f88\u597d\u7528\uff0c\u4f46\u662f\u4e0d\u662fopen source\u7684\u3002" }, { "author": { "url": "member/notedit", "name": "notedit", "avatar": "https://cdn.v2ex.com/avatar/f6d1/ecd1/11788_large.png?m=1381820822" }, "url": "t/80883", "title": "http://lynckia.com/licode/ \u4e00\u5957webrtc\u5f00\u6e90\u7684\u7c7b\u5e93", "id": "t/80883", "date_published": "2013-08-31T13:06:07+00:00", "content_html": "\u5728\u505a workor(http://workor.com) \u7684\u65f6\u5019 \u53c2\u8003\u8fc7\u4ed6\u4eec\u7684\u4ee3\u7801. \u5e0c\u671b\u5bf9\u7814\u7a76webrtc\u7684\u540c\u5b66\u6709\u5e2e\u52a9" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1778546420" }, "url": "t/79383", "title": "\u4e00\u4e2a\u57fa\u4e8e WebRTC \u6280\u672f\u7684\u7f51\u7edc\u7535\u8bdd\u670d\u52a1", "id": "t/79383", "date_published": "2013-08-17T07:00:25+00:00", "content_html": "https://www.10086china.com/

\u57df\u540d\u6709\u70b9\u5c71\u5be8\u3002" }, { "author": { "url": "member/aveline", "name": "aveline", "avatar": "https://cdn.v2ex.com/avatar/5caf/41d6/1304_large.png?m=1432238732" }, "url": "t/70183", "title": "WebRTC World", "id": "t/70183", "date_published": "2013-05-26T03:52:39+00:00", "content_html": "http://joyent.com/blog/join-us-at-webrtc-world-in-june" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1778546420" }, "url": "t/69796", "date_modified": "2013-05-22T07:54:07+00:00", "content_html": "\u4e00\u4e2a\u57fa\u4e8e WebRTC \u6280\u672f\u7684 P2P CDN\uff1a

https://peercdn.com/

", "date_published": "2013-05-22T07:48:56+00:00", "title": "PeerCDN", "id": "t/69796" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1778546420" }, "url": "t/69795", "title": "WebRTC \u7684\u4e00\u7cfb\u5217\u6280\u672f\u771f\u7684\u662f\u4e00\u4e2a\u7279\u522b\u597d\u7684\u521b\u4e1a\u65b9\u5411", "id": "t/69795", "date_published": "2013-05-22T07:48:03+00:00", "content_html": "\u76ee\u524d\u652f\u6301 WebRTC \u7684\u8bbe\u5907\u5df2\u7ecf\u8d85\u8fc7 10 \u4ebf\u53f0\uff0c\u7528\u6237\u4e5f\u6709\u597d\u51e0\u4ebf\u4e86\uff0c\u6211\u5728\u60f3\uff0c\u8fd9\u4e2a\u6280\u672f\u5c06\u6709\u53ef\u80fd\u4f1a\u521b\u9020\u4e00\u5806\u65b0\u7684\u4e0a\u5e02\u516c\u53f8\uff0c\u5c31\u50cf\u5f53\u5e74 Flash \u5f00\u59cb\u652f\u6301\u89c6\u9891\u64ad\u653e\u540e\u90a3\u6837\u3002" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1778546420" }, "url": "t/69629", "title": "\u642d\u5efa\u81ea\u5df1\u7684 TURN Server", "id": "t/69629", "date_published": "2013-05-21T06:18:18+00:00", "content_html": "http://www.dialogic.com/den/forums/t/10238.aspx" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1778546420" }, "url": "t/69460", "title": "WebRTC Book", "id": "t/69460", "date_published": "2013-05-19T20:06:51+00:00", "content_html": "http://www.webrtcbook.com/" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1778546420" }, "url": "t/69459", "title": "SimpleWebRTC", "id": "t/69459", "date_published": "2013-05-19T20:04:34+00:00", "content_html": "https://github.com/henrikjoreteg/SimpleWebRTC" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1778546420" }, "url": "t/69458", "title": "Sharefest", "id": "t/69458", "date_published": "2013-05-19T20:03:46+00:00", "content_html": "http://www.sharefest.me/" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1778546420" }, "url": "t/69457", "title": "PeerJS P2P Chat Demo", "id": "t/69457", "date_published": "2013-05-19T20:01:59+00:00", "content_html": "http://cdn.peerjs.com/demo/chat-old.html" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1778546420" }, "url": "t/69456", "title": "PeerJS", "id": "t/69456", "date_published": "2013-05-19T19:59:51+00:00", "content_html": "http://peerjs.com/" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1778546420" }, "url": "t/69455", "title": "WebRTC.io", "id": "t/69455", "date_published": "2013-05-19T19:59:22+00:00", "content_html": "https://github.com/webRTC/webRTC.io" }, { "author": { "url": "member/Livid", "name": "Livid", "avatar": "https://cdn.v2ex.com/avatar/c4ca/4238/1_large.png?m=1778546420" }, "url": "t/69454", "title": "WebRTCStats", "id": "t/69454", "date_published": "2013-05-19T19:54:47+00:00", "content_html": "http://webrtcstats.com/" } ] } ubao msn snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86