不需要SFU而实现WebRTC联播,appear.in的WebRTC工程师Philipp Hancke实现了在Chrome和Firefox之间的联播。LiveVideoStack对原文进行了摘译。

文 / Philipp Hancke

译 / 元宝

审校 / Ant

原文:

https://webrtchacks.com/a-playground-for-simulcast-without-an-sfu/

同步联播是WebRTC用于多方会议的一个很有趣的方面。简而言之,它意味着可以同时发送三种不同的分辨率(空间可伸缩性)和不同的帧速率(时间可伸缩性)。

通常,需要一个SFU才能利用联播。但是有一个方法可以使在两个浏览器之间或在单个页面内效果可见。这对于做单页测试或使用联播功能是非常有用的,特别是能够只启用某些空间层或控制特定流的目标比特率。

Playground

Playground有两种变体,一种用于Chrome,另一种用于Firefox。Chrome版本使用了我们在2014年夏天的谷歌环聊中首次看到的旧的SDP munging hack 。Firefox 使用‘RTCRtpSender.setParameters’来启用同步联播。两者都没有遵守最新的规范,但这并不会影响任何人对它的使用。

两种变体都可以显示视频图像,首先是发送者图像和总体比特率/帧速率图,其后是三个不同的空间流,每个空间流具有用于比特率和帧率的对应图。

由于我们不想涉及到服务器的内容,所以我们需要破解一些东西。幸运的是,有一个Chrome的测试验证了这个想法。Chrome和Firefox都使用一个数据包的RTP SSRC将其路由到某一个特定的媒体流。这些SSRC可以在SDP提供中找到:

原始的Chrome SDP

1type: offer, sdp: v=0
2o=- 7356021969196541917 2 IN ImP4 127.0.0.1
3s=-
4t=0 0
5a=group:BUNDLE video
6a=msid-semantic: WMS 0AQNo1bnpzlGvB7aE2InJRz85M9lmId7Es9J
7m=video 9 UDP/TLS/RTP/SAVPF 96 97 98 99 100 101 102 124 127 123 125
8c=IN IP4 0.0.0.0
9a=rtcp:9 IN IP4 0.0.0.0
10a=ice-ufrag:cTTs
11a=ice-pwd:W9/g2uTwfb6UCRxfIoMkd5nV
12a=ice-options:trickle
13a=fingerprint:sha-256 01:09:17:BA:CD:91:FE:E0:24:24:86:5C:17:71:CC:37:61:CF:BA:D1:31:49:80:F1:BC:B8:B2:6F:8C:D5:39:F2
14a=setup:actpass
15a=mid:video
16a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
17a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
18a=extmap:4 urn:3gpp:video-orientation
19a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
20a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
21a=extmap:7 http://www.webrtc.org/experiments/rtp-hdrext/video-content-type
22a=extmap:8 http://www.webrtc.org/experiments/rtp-hdrext/video-timing
23a=sendrecv
24a=rtcp-mux
25a=rtcp-rsize
26a=rtpmap:96 VP8/90000
27a=rtcp-fb:96 goog-remb
28a=rtcp-fb:96 transport-cc
29a=rtcp-fb:96 ccm fir
30a=rtcp-fb:96 nack
31a=rtcp-fb:96 nack pli
32a=rtpmap:97 rtx/90000
33a=fmtp:97 apt=96
34a=rtpmap:98 VP9/90000
35a=rtcp-fb:98 goog-remb
36a=rtcp-fb:98 transport-cc
37a=rtcp-fb:98 ccm fir
38a=rtcp-fb:98 nack
39a=rtcp-fb:98 nack pli
40a=rtpmap:99 rtx/90000
41a=fmtp:99 apt=98
42a=rtpmap:100 H264/90000
43a=rtcp-fb:100 goog-remb
44a=rtcp-fb:100 transport-cc
45a=rtcp-fb:100 ccm fir
46a=rtcp-fb:100 nack
47a=rtcp-fb:100 nack pli
48a=fmtp:100 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42001f
49a=rtpmap:101 rtx/90000
50a=fmtp:101 apt=100
51a=rtpmap:102 H264/90000
52a=rtcp-fb:102 goog-remb
53a=rtcp-fb:102 transport-cc
54a=rtcp-fb:102 ccm fir
55a=rtcp-fb:102 nack
56a=rtcp-fb:102 nack pli
57a=fmtp:102 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
58a=rtpmap:124 rtx/90000
59a=fmtp:124 apt=102
60a=rtpmap:127 red/90000
61a=rtpmap:123 rtx/90000
62a=fmtp:123 apt=127
63a=rtpmap:125 ulpfec/90000
64a=ssrc-group:FID 3818935445 664019814
65a=ssrc:3818935445 cname:/9xLVG5y0PJqxacG
66a=ssrc:3818935445 msid:0AQNo1bnpzlGvB7aE2InJRz85M9lmId7Es9J d1c9f46b-0328-4ef1-9c31-c1b279ac554a
67a=ssrc:3818935445 mslabel:0AQNo1bnpzlGvB7aE2InJRz85M9lmId7Es9J
68a=ssrc:3818935445 label:d1c9f46b-0328-4ef1-9c31-c1b279ac554a
69a=ssrc:664019814 cname:/9xLVG5y0PJqxacG
70a=ssrc:664019814 msid:0AQNo1bnpzlGvB7aE2InJRz85M9lmId7Es9J d1c9f46b-0328-4ef1-9c31-c1b279ac554a
71a=ssrc:3818935446 cname:/9xLVG5y0PJqxacG
72a=ssrc:3818935446 msid:0AQNo1bnpzlGvB7aE2InJRz85M9lmId7Es9J d1c9f46b-0328-4ef1-9c31-c1b279ac554a
73a=ssrc:3818935447 cname:/9xLVG5y0PJqxacG
74a=ssrc:3818935447 msid:0AQNo1bnpzlGvB7aE2InJRz85M9lmId7Es9J d1c9f46b-0328-4ef1-9c31-c1b279ac554a
75a=ssrc:3818935448 cname:/9xLVG5y0PJqxacG
76a=ssrc:3818935448 msid:0AQNo1bnpzlGvB7aE2InJRz85M9lmId7Es9J d1c9f46b-0328-4ef1-9c31-c1b279ac554a
77a=ssrc:3818935449 cname:/9xLVG5y0PJqxacG
78a=ssrc:3818935449 msid:0AQNo1bnpzlGvB7aE2InJRz85M9lmId7Es9J d1c9f46b-0328-4ef1-9c31-c1b279ac554a
79a=ssrc-group:FID 3818935446 3818935447
80a=ssrc-group:FID 3818935448 3818935449
81a=ssrc-group:SIM 3818935445 3818935446 3818935448

和2014年一样,重要的是多个‘a=ssrc:’的行以及‘a=ssrc-group:SIM’的行。

原始的Firefox SDP

1v=0
2o=mozilla...THIS_IS_SDPARTA-61.0.1 2246157997147315987 0 IN IP4 0.0.0.0
3s=-
4t=0 0
5a=sendrecv
6a=fingerprint:sha-256 00:3E:DC:02:92:60:97:0D:D8:F7:7F:E9:AD:41:46:CD:B5:FC:33:35:3F:5C:C4:BC:CD:85:17:96:F8:D6:14:57
7a=group:BUNDLE sdparta_0
8a=ice-options:trickle
9a=msid-semantic:WMS *
10m=video 40601 UDP/TLS/RTP/SAVPF 120 121 126 97
11c=IN IP4 192.168.1.230
12a=sendrecv
13a=end-of-candidates
14a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
15a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
16a=extmap:5 urn:ietf:params:rtp-hdrext:toffset
17a=extmap:6/sendonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
18a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
19a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
20a=fmtp:120 max-fs=12288;max-fr=60
21a=fmtp:121 max-fs=12288;max-fr=60
22a=ice-pwd:f317cfe0aaa529381815e208a6cdec19
23a=ice-ufrag:07366c17
24a=mid:sdparta_0
25a=msid:{8de6968c-0ea9-4a19-aaa6-51355d4a5f4e} {9bdb3a96-19f3-4730-8459-e56db515b5da}
26a=rid:hi send
27a=rid:mid send
28a=rid:lo send
29a=rtcp-fb:120 nack
30a=rtcp-fb:120 nack pli
31a=rtcp-fb:120 ccm fir
32a=rtcp-fb:120 goog-remb
33a=rtcp-fb:121 nack
34a=rtcp-fb:121 nack pli
35a=rtcp-fb:121 ccm fir
36a=rtcp-fb:121 goog-remb
37a=rtcp-fb:126 nack
38a=rtcp-fb:126 nack pli
39a=rtcp-fb:126 ccm fir
40a=rtcp-fb:126 goog-remb
41a=rtcp-fb:97 nack
42a=rtcp-fb:97 nack pli
43a=rtcp-fb:97 ccm fir
44a=rtcp-fb:97 goog-remb
45a=rtcp-mux
46a=rtpmap:120 VP8/90000
47a=rtpmap:121 VP9/90000
48a=rtpmap:126 H264/90000
49a=rtpmap:97 H264/90000
50a=setup:actpass
51a=simulcast: send rid=hi;mid;lo
52a=ssrc:252082699 cname:{004db4a6-943d-496b-9e8d-1689f7be7355}
53a=ssrc:2611961929 cname:{004db4a6-943d-496b-9e8d-1689f7be7355}
54a=ssrc:1452646660 cname:{004db4a6-943d-496b-9e8d-1689f7be7355}

在Firefox中,重要的联播比特数是‘a = rid’的行和‘a = simulcast’的行(从底部开始的第4行)。注意:这是来自规范的旧版本,可能会有所变化。

WebRTC hack

我们需要让我们的同行相信,它实际上正在接收三种不同的视频流——低、中、高的比特率——而不仅仅是其中一种。为实现这一目标,我们需要创建自己的SDP,其中包含从SSRC到跟踪的不同映射。这是有点苛刻的,但这个网站被称为webrtchacks是有原因的!

我们最终将Firefox产品转换为:

1v=0
 2o=mozilla...THIS_IS_SDPARTA-61.0 8324701712193024513 0 IN IP4 0.0.0.0
 3s=-
 4t=0 0
 5a=sendrecv
 6a=fingerprint:sha-256 00:3E:DC:02:92:60:97:0D:D8:F7:7F:E9:AD:41:46:CD:B5:FC:33:35:3F:5C:C4:BC:CD:85:17:96:F8:D6:14:57
 7a=group:BUNDLE sdparta_0 sdparta_1 sdparta_2
 8a=msid-semantic:WMS *
 9m=video 9 UDP/TLS/RTP/SAVPF 120 121 126 97
10c=IN IP4 0.0.0.0
11a=sendrecv
12a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
13a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
14a=extmap:5 urn:ietf:params:rtp-hdrext:toffset
15a=extmap:6/sendonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
16a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
17a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
18a=fmtp:120 max-fs=12288;max-fr=60
19a=fmtp:121 max-fs=12288;max-fr=60
20a=ice-pwd:f317cfe0aaa529381815e208a6cdec19
21a=ice-ufrag:07366c17
22a=mid:sdparta_0
23a=msid:low low
24a=rtcp-fb:120 nack
25a=rtcp-fb:120 nack pli
26a=rtcp-fb:120 ccm fir
27a=rtcp-fb:120 goog-remb
28a=rtcp-fb:121 nack
29a=rtcp-fb:121 nack pli
30a=rtcp-fb:121 ccm fir
31a=rtcp-fb:121 goog-remb
32a=rtcp-fb:126 nack
33a=rtcp-fb:126 nack pli
34a=rtcp-fb:126 ccm fir
35a=rtcp-fb:126 goog-remb
36a=rtcp-fb:97 nack
37a=rtcp-fb:97 nack pli
38a=rtcp-fb:97 ccm fir
39a=rtcp-fb:97 goog-remb
40a=rtcp-mux
41a=rtpmap:120 VP8/90000
42a=rtpmap:121 VP9/90000
43a=rtpmap:126 H264/90000
44a=rtpmap:97 H264/90000
45a=setup:actpass
46a=ssrc:252082699 cname:{004db4a6-943d-496b-9e8d-1689f7be7355}
47m=video 9 UDP/TLS/RTP/SAVPF 120 121 126 97
48c=IN IP4 0.0.0.0
49a=sendrecv
50a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
51a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
52a=extmap:5 urn:ietf:params:rtp-hdrext:toffset
53a=extmap:6/sendonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
54a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
55a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
56a=fmtp:120 max-fs=12288;max-fr=60
57a=fmtp:121 max-fs=12288;max-fr=60
58a=ice-pwd:f317cfe0aaa529381815e208a6cdec19
59a=ice-ufrag:07366c17
60a=mid:sdparta_1
61a=msid:mid mid
62a=rtcp-fb:120 nack
63a=rtcp-fb:120 nack pli
64a=rtcp-fb:120 ccm fir
65a=rtcp-fb:120 goog-remb
66a=rtcp-fb:121 nack
67a=rtcp-fb:121 nack pli
68a=rtcp-fb:121 ccm fir
69a=rtcp-fb:121 goog-remb
70a=rtcp-fb:126 nack
71a=rtcp-fb:126 nack pli
72a=rtcp-fb:126 ccm fir
73a=rtcp-fb:126 goog-remb
74a=rtcp-fb:97 nack
75a=rtcp-fb:97 nack pli
76a=rtcp-fb:97 ccm fir
77a=rtcp-fb:97 goog-remb
78a=rtcp-mux
79a=rtpmap:120 VP8/90000
80a=rtpmap:121 VP9/90000
81a=rtpmap:126 H264/90000
82a=rtpmap:97 H264/90000
83a=setup:actpass
84a=ssrc:2611961929 cname:{004db4a6-943d-496b-9e8d-1689f7be7355}
85m=video 9 UDP/TLS/RTP/SAVPF 120 121 126 97
86c=IN IP4 0.0.0.0
87a=sendrecv
88a=extmap:3 urn:ietf:params:rtp-hdrext:sdes:mid
89a=extmap:4 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
90a=extmap:5 urn:ietf:params:rtp-hdrext:toffset
91a=extmap:6/sendonly urn:ietf:params:rtp-hdrext:sdes:rtp-stream-id
92a=fmtp:126 profile-level-id=42e01f;level-asymmetry-allowed=1;packetization-mode=1
93a=fmtp:97 profile-level-id=42e01f;level-asymmetry-allowed=1
94a=fmtp:120 max-fs=12288;max-fr=60
95a=fmtp:121 max-fs=12288;max-fr=60
96a=ice-pwd:f317cfe0aaa529381815e208a6cdec19
97a=ice-ufrag:07366c17
98a=mid:sdparta_2
99a=msid:hi hi
100a=rtcp-fb:120 nack
101a=rtcp-fb:120 nack pli
102a=rtcp-fb:120 ccm fir
103a=rtcp-fb:120 goog-remb
104a=rtcp-fb:121 nack
105a=rtcp-fb:121 nack pli
106a=rtcp-fb:121 ccm fir
107a=rtcp-fb:121 goog-remb
108a=rtcp-fb:126 nack
109a=rtcp-fb:126 nack pli
110a=rtcp-fb:126 ccm fir
111a=rtcp-fb:126 goog-remb
112a=rtcp-fb:97 nack
113a=rtcp-fb:97 nack pli
114a=rtcp-fb:97 ccm fir
115a=rtcp-fb:97 goog-remb
116a=rtcp-mux
117a=rtpmap:120 VP8/90000
118a=rtpmap:121 VP9/90000
119a=rtpmap:126 H264/90000
120a=rtpmap:97 H264/90000
121a=setup:actpass
122a=ssrc:1452646660 cname:{004db4a6-943d-496b-9e8d-1689f7be7355}

这显示了三个不同的媒体部分(按照统一计划的规定),它将在接收器处触发“跟踪”事件三次,为我们提供三个不同的 MediaStream对象以附加到视频元素,并且还允许使用getStats API来为各个比特率制作图表。

请参阅SDP的源代码,了解如何创建它。

调整各个层的比特率

Chrome长期以来一直使用硬编码表来表示各个空间层的同步比特率。

1// These tables describe from which resolution we can use how many
2// simulcast layers at what bitrates (maximum, target, and minimum).
3// Important!! Keep this table from high resolution to low resolution.
4// clang-format off
5const SimulcastFormat kSimulcastFormats[] = {
6  {1920, 1080, 3, 5000, 4000, 800},
7  {1280, 720, 3,  2500, 2500, 600},
8  {960, 540, 3, 900, 900, 450},
9  {640, 360, 2, 700, 500, 150},
10  {480, 270, 2, 450, 350, 150},
11  {320, 180, 1, 200, 150, 30},
12  {0, 0, 1, 200, 150, 30}
13};

该表显示了分辨率(例如1920×1080),空间层数(3)以及最大,最佳和最小比特率。

感谢‘setParameters’让我们现在可以偏离这个表中定义的比特率并获得一些创意。如果你运行该示例而不进行任何修改,你可以看到联播以大约3.2mbps的比特率在发送。它分为三个不同的空间流,大约是150kbps,500kbps和2500kbps,与表中的设置相匹配。

让我们通过将这个JavaScript粘贴到控制台来修改它:

1var p = pc1.getSenders()[0].getParameters();
2p.encodings[1].maxBitrate = 300*1000;
3p.encodings[2].maxBitrate = 400*1000;
4pc1.getSenders()[0].setParameters(p)
5  .catch(e => console.error(e))

这将中分辨率(640×360)空间层的目标比特率设置为300kbps,将720p流的目标比特率设置为400kbps。编码器可以很好地匹配这些比特率,它们的质量非常好,即使将720p流的比特率设置为400kbps也是如此。

如果我们将720p的目标比特率降低到200 kbps,那么我们可以看到由于帧率下降而导致的视觉退化,因为只有基本的时间层被发送。对于720p的流,你可以用像200kbps一样低的比特率来使用...

此图表(以及下面的图表)中均是左侧为比特率,右侧为帧率。

这对于在SFU中成功实现同步联播的任何人来说都不是新闻,但是在没有任何服务器的情况下,在单个页面中展示这个效果还是很惊人的。

到处都是Bug

最初构建页面的主要动机之一是探索Firefox中对联播的支持。它没有预期的那么好,最大的问题是因为Firefox以及我在SFU实现中的错误。在playground的页面上,我可以证明它不在SFU中,但在Firefox中出现了问题。

中分辨率图层的比特率仅以300kbps,而不是Chrome发送的500kbps。尽管请求超过2000kbps,我们只能为高分辨率层获得500kbps的速率。部分原因是SDP munging中的一个非常巧妙的错误,它影响了低分辨率层的设置。这很容易在JavaScript中修复。

接下来,有一个问题是高分辨率层的配置被修改了,这将很快在Firefox中登陆,并将被提升到Beta和ESR。有了修复,比特率就会高得多:

中等分辨率层的目标比特率也根据我的要求更改为500kbps。把我当成一个非常满意的客户!

Jitsi的Brian Baldino发现了另外一个有趣的问题。当禁用高中空间层时,Chrome将以每秒超过一兆比特的比特率继续发送。这是为了保持比特率估计值高而填充数据。

这实际上是对旧版Chrome问题非常好的再现,希望在一个更具体的用例中出现的不良行为,以及在单个页面测试中进行复制,使这更容易修复。

最后但并非最不重要的是,您可能已经注意到Chrome中本地视频的高帧率,接近90帧。Chrome似乎将所有发送流的比特率和帧率都加了起来。这(可能)不太正确,所以这里有另一个bug报告。

同步联播对于构建高级WebRTC应用程序非常重要。希望这个playground让Web开发人员更容易访问它。特别感谢Florent Castelli在Chrome中实现‘setParameters’,并允许更多的修补以及Byron Campen在Firefox问题上的快速支持。

不需要SFU实现WebRTC联播实践相关推荐

  1. 5月19-20日WebRTCon 2018 梳理全球WebRTC技术实践与案例

    4月17日,距离WebRTCon 2018举行还有一个多月的时间,这是由音视频技术社区LiveVideoStack发起的WebRTC生态大会.大会将聚焦WebRTC技术实践与应用案例两大主线,旨在为W ...

  2. WebRTC基础实践 - 5.通过RTCPeerConnection传输流媒体视频

    本节内容 在本节课程中, 我们将学习以下内容: 使用WebRTC兼容库: adapter.js, 来抹平各浏览器间的差异. 通过 RTCPeerConnection API 传输流媒体视频. 控制 m ...

  3. WebRTC基础实践 - 10. 总结

    我们创建了一个视频聊天的APP, 同时支持传输文件以及其他数据! 内容回顾 在本教程中, 我们学习了以下内容: 获取webcam摄像头的视频内容. 通过 RTCPeerConnection 传输视频. ...

  4. WebRTC基础实践 - 7. 配置信令服务

    本节内容 在本节课程中, 我们将学习以下内容: 通过 npm 安装 package.json 文件中指定的项目依赖 运行Node.js服务器, 通过 node-static 提供静态文件服务. 用So ...

  5. WebRTC基础实践 - 9. 拍照并传给对方

    本节内容 在本节课程中, 我们将学习以下内容: 拍照并通过canvas元素获取图像数据. 给对面发送图片. 本节的完整版代码位于 step-06 文件夹中. 工作原理 前面的小节中, 我们使用 RTC ...

  6. WebRTC基础实践 - 1. WebRTC简介

    WebRTC 是一个开源的实时通信项目, 主要目标是对Web/原生App平台上的语音.视频.以及数据传输等实时通讯提供支持. WebRTC 主要包括以下 JavaScript API(点击链接可查看相 ...

  7. 网易工业级WebRTC应用实践深度解析

    本文来自网易云信CTO赵加雨在LiveVideoStackCon2017上的分享,并由 LiveVideoStack整理而成.赵加雨阐述了网易在WebRTC上的探索和改进,以及如何与WebRTC进行互 ...

  8. 基于Licode的WebRTC全球分布式架构

    随着在线教育行业的兴起, 许多人把目光投向了国外市场,而如何搭建全球化的音视频网络就成为了其中的关键问题.百家云研发工程师陈聪详细介绍了如何利用Licode 开源服务器搭建全球分布式架构以解决常见的教 ...

  9. 音视频技术开发周刊 62期

    版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/vn9PLgZvnPs1522s82g/article/details/81660079 『音视频技术 ...

最新文章

  1. 千万级并发!如何设计一个多级缓存系统?
  2. VASP计算HSE06带隙INCAR
  3. 医疗实体链接(标准化)论文解读 (附代码) A Lightweight Neural Model for Biomedical Entity Linking
  4. 听安全专家讲如何黑掉黑客的故事
  5. 学习Docker容器时,错误bash: ping: command not found的解决方法
  6. python io流,Python io流会在列表理解中自动关闭吗?
  7. js 中location 的学习
  8. (转)WEB2.0的单手定则
  9. 项目运行报'vue-cli-service' 不是内部或外部命令,也不是可运行的程序 或批处理文件“
  10. github上的优秀项目和开发环境配置
  11. E-prime问题(安装.net3.5)
  12. 非对称密钥/对称密钥加解密工具
  13. 计算机游戏act指的是什么游戏,忍龙2领衔!5款史上最佳的ACT游戏推荐,值得一玩!...
  14. 2. 数理统计---样本分布
  15. 领域自适应论文(六十八):Implicit Class-Conditioned Domain Alignment for Unsupervised Domain Adaptation论文原理
  16. 图模型在欺诈检测应用一点看法
  17. 【python量化】将Informer用于股价预测
  18. MAC版Sublime Text 解决 Unable to download XXX 问题
  19. Myeclipse 使用经验总结
  20. unity下载并和vs2019关联的步骤

热门文章

  1. 2017年12月英语四级翻译预测
  2. .NET分布式缓存Redis从入门到实战
  3. 中国人工智能学会通讯——最优传输理论在机器学习中的应用 1.1 最优传输理论与 WGAN 模型...
  4. VDP文件级恢复需要在用VDP备份的机器上浏览
  5. Java实现简易的文件的迁移器
  6. 如何Exchange移动数据库文件(一)
  7. CodeForces - 431C k-Tree(dp)
  8. HDU - 6214 Smallest Minimum Cut(最小割最少边数)
  9. UVA - 796 Critical Links(tarjan求割边)
  10. 安卓进阶系列-04自定义原型图片显示(CircleImageView)的使用