<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Webrtc on 编程技术记录</title>
    <link>https://blog.z6z8.cn/tags/webrtc/</link>
    <description>Recent content in Webrtc on 编程技术记录</description>
    <generator>Hugo</generator>
    <language>zh-Hans</language>
    <lastBuildDate>Thu, 18 Nov 2021 09:22:34 +0000</lastBuildDate>
    <atom:link href="https://blog.z6z8.cn/tags/webrtc/feed.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>GoogleWebRTC for iOS 设置SDP和ICE顺序错误导致不互通</title>
      <link>https://blog.z6z8.cn/2021/11/18/googlewebrtc-for-ios-%E8%AE%BE%E7%BD%AEsdp%E5%92%8Cice%E9%A1%BA%E5%BA%8F%E9%94%99%E8%AF%AF%E5%AF%BC%E8%87%B4%E4%B8%8D%E4%BA%92%E9%80%9A/</link>
      <pubDate>Thu, 18 Nov 2021 09:22:34 +0000</pubDate>
       <guid isPermaLink="false">http://blog.z6z8.cn/?p=1149</guid> 
      <description>&lt;p&gt;环境:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;GoogleWebRTC 1.1.31999&lt;/li&gt;
&lt;li&gt;Xcode 13&lt;/li&gt;
&lt;li&gt;iOS 15&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;问题描述：&lt;/p&gt;
&lt;p&gt;1、 学习WebRTC时，先用simple-peer实现了浏览器和浏览器之间的音视频互通。&lt;/p&gt;
&lt;p&gt;2、然后结合浏览器的经验，基于GoogleWebRTC for iOS实现了iOS真机和浏览器直接的互通&lt;/p&gt;
&lt;p&gt;3、 最后在测试iOS真机之间的互通时，基本不互通，测试失败。排查了很长时间，最后定位为API调用顺序错误&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;应先设置远端SDP，再设置远端ICE&lt;/strong&gt;，具体到API就是，先设置
调用 &lt;code&gt;setRemoteDescription&lt;/code&gt;,然后再调用 &lt;code&gt;addIceCandidate&lt;/code&gt;&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-objc&#34; data-lang=&#34;objc&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;// 收到远端SDP和ICE信息后
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#75715e&#34;&gt;&lt;/span&gt;[peerConnection setRemoteDescription:remoteSDP completionHandler:&lt;span style=&#34;color:#f92672&#34;&gt;^&lt;/span&gt;(NSError &lt;span style=&#34;color:#f92672&#34;&gt;*&lt;/span&gt; err){
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        [peerConnection addIceCandidate:remoteICE];
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;];
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;</description>
    </item>
    <item>
      <title>WebRTC初学Demo</title>
      <link>https://blog.z6z8.cn/2021/10/19/webrtc%E5%88%9D%E5%AD%A6demo/</link>
      <pubDate>Tue, 19 Oct 2021 01:52:57 +0000</pubDate>
       <guid isPermaLink="false">http://blog.z6z8.cn/?p=1115</guid> 
      <description>&lt;p&gt;webrtc介绍&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;#%E7%AE%80%E4%BB%8B&#34;&gt;简介&lt;/a&gt;&lt;a href=&#34;#%E5%AE%9E%E7%8E%B0%E5%9F%BA%E6%9C%AC%E7%9A%84%E6%95%B0%E6%8D%AE%E9%80%9A%E9%81%93&#34;&gt;实现基本的数据通道&lt;/a&gt;&lt;a href=&#34;#%E6%96%87%E4%BB%B6%E4%BC%A0%E8%BE%93&#34;&gt;文件传输&lt;/a&gt;&lt;a href=&#34;#%E4%BF%AE%E6%94%B9%E4%BC%A0%E8%BE%93%E9%80%9F%E5%BA%A6%E9%99%90%E5%88%B6&#34;&gt;修改传输速度限制&lt;/a&gt;&lt;a href=&#34;#%E9%80%89%E6%8B%A9%E5%B9%B6%E8%AF%BB%E5%8F%96%E6%96%87%E4%BB%B6%E6%95%B0%E6%8D%AE&#34;&gt;选择并读取文件数据&lt;/a&gt;&lt;a href=&#34;#%E8%87%AA%E5%8A%A8%E4%B8%8B%E8%BD%BD%E6%96%87%E4%BB%B6&#34;&gt;自动下载文件&lt;/a&gt;&lt;a href=&#34;#%E5%AE%8C%E6%95%B4%E4%BB%A3%E7%A0%81-1&#34;&gt;完整代码&lt;/a&gt;&lt;a href=&#34;#%E9%9F%B3%E8%A7%86%E9%A2%91%E9%80%9A%E8%AF%9D&#34;&gt;音视频通话&lt;/a&gt;&lt;a href=&#34;#https&#34;&gt;https&lt;/a&gt;&lt;a href=&#34;#%E8%AE%BF%E9%97%AE%E9%9F%B3%E8%A7%86%E9%A2%91%E6%B5%81&#34;&gt;访问音视频流&lt;/a&gt;&lt;a href=&#34;#%E5%AE%8C%E6%95%B4%E4%BB%A3%E7%A0%81-2&#34;&gt;完整代码&lt;/a&gt;&lt;a href=&#34;#%E5%B1%8F%E5%B9%95%E5%85%B1%E4%BA%AB&#34;&gt;屏幕共享&lt;/a&gt;&lt;a href=&#34;#%E6%8D%95%E6%8D%89%E5%B1%8F%E5%B9%95&#34;&gt;捕捉屏幕&lt;/a&gt;&lt;a href=&#34;#%E5%AE%8C%E6%95%B4%E4%BB%A3%E7%A0%81-3&#34;&gt;完整代码&lt;/a&gt;&lt;a href=&#34;#nat%E7%A9%BF%E9%80%8F%E4%B9%8Bstunturn&#34;&gt;NAT穿透之STUN/TURN&lt;/a&gt;&lt;a href=&#34;#%E4%BF%A1%E4%BB%A4%E6%9C%8D%E5%8A%A1%E5%99%A8&#34;&gt;信令服务器&lt;/a&gt;&lt;a href=&#34;#%E4%BF%A1%E4%BB%A4%E6%9C%8D%E5%8A%A1%E5%AE%9E%E7%8E%B0&#34;&gt;信令服务实现&lt;/a&gt;&lt;a href=&#34;#%E5%AE%8C%E6%95%B4%E4%BB%A3%E7%A0%81-4&#34;&gt;完整代码&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://webrtc.org.cn/webrtc-tutorial-basic/&#34;&gt;详细请访问&lt;/a&gt;&lt;/p&gt;
&lt;h1 id=&#34;简介&#34;&gt;简介&lt;/h1&gt;
&lt;p&gt;WebRTC（网页实时通信技术），是一系列为了建立端到端文本或者随机数据的规范，标准，API和概念的统称。&lt;/p&gt;
&lt;p&gt;任何实现了WebRTC标准的软件之间均可通信，如PC浏览器&amp;ndash;手机浏览器、浏览器&amp;ndash;App、App&amp;ndash;App。通信双方是对等的，但通常还要引入服务端，以便于对等端能够找到对方。&lt;/p&gt;
&lt;p&gt;移动端浏览器对WebRTC的支持&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Android 4.4以上&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;iOS 11以上&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;WebRTC应用不需要非常高性能就能够平稳运行、拥有良好体验。对于WebRTC来说，获取特定硬件的权限也不是必需的。Web应用和原生应用对比：&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;原生应用会比Web应用更快，拥有更高级别的硬件权限；混合应用的运行速度更慢，不能使用移动设备的全部权限。&lt;/li&gt;
&lt;li&gt;原生应用在不同的平台上的代码复用度有待提高；混合应用开发起来会更快，更省钱&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;结论：如果高性能和极致体验不是软件的必不可少的要求，那么，在绝大多数情况下，用户根本注意不到原生和混合WebRTC应用之间的差别。&lt;/p&gt;
&lt;h1 id=&#34;实现基本的数据通道&#34;&gt;实现基本的数据通道&lt;/h1&gt;
&lt;p&gt;对浏览器而言，WebRTC API处于底层且十分复杂。不过我们可以使用封装好的高级别的API&amp;mdash;- &lt;a href=&#34;https://github.com/feross/simple-peer&#34;&gt;simple-peer&lt;/a&gt; 是一个基础的，非常洁净的低层P2P连接封装器.下面的示例是 &lt;code&gt;simple-peer&lt;/code&gt; 的一个标准例子。&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;&#34;&gt;&lt;code class=&#34;language-gdscript3&#34; data-lang=&#34;gdscript3&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;html&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;body&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;      &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;&lt;/span&gt;style&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;        &lt;span style=&#34;color:#75715e&#34;&gt;#outgoing {          width: 100%;          word-wrap: break-word;          white-space: normal;        }      &amp;lt;/style&amp;gt;    &amp;lt;form&amp;gt;      &amp;lt;textarea id=&amp;#34;incoming&amp;#34;&amp;gt;&amp;lt;/textarea&amp;gt;      &amp;lt;button type=&amp;#34;submit&amp;#34;&amp;gt;submit&amp;lt;/button&amp;gt;    &amp;lt;/form&amp;gt;    &amp;lt;pre id=&amp;#34;outgoing&amp;#34;&amp;gt;&amp;lt;/pre&amp;gt;    &amp;lt;script src=&amp;#34;simplepeer.min.js&amp;#34;&amp;gt;&amp;lt;/script&amp;gt;    &amp;lt;script&amp;gt;      const p = new SimplePeer({        initiator: location.hash === &amp;#39;#1&amp;#39;,        trickle: false      })&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      p&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;on(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;error&amp;#39;&lt;/span&gt;, err &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; console&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;log(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;error&amp;#39;&lt;/span&gt;, err))
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      p&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;on(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;signal&amp;#39;&lt;/span&gt;, data &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {        console&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;log(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;SIGNAL&amp;#39;&lt;/span&gt;, JSON&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;stringify(data))        document&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;querySelector(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#outgoing&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;textContent &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; JSON&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;stringify(data)      })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      document&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;querySelector(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;form&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;addEventListener(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;submit&amp;#39;&lt;/span&gt;, ev &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {        ev&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;preventDefault()        p&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;signal&lt;/span&gt;(JSON&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;parse(document&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;querySelector(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;#incoming&amp;#39;&lt;/span&gt;)&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;value))      })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      p&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;on(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;connect&amp;#39;&lt;/span&gt;, () &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {        console&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;log(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;CONNECT&amp;#39;&lt;/span&gt;)        p&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;send(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;whatever&amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; Math&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;random())      })
&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      p&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;on(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;data&amp;#39;&lt;/span&gt;, data &lt;span style=&#34;color:#f92672&#34;&gt;=&amp;gt;&lt;/span&gt; {        console&lt;span style=&#34;color:#f92672&#34;&gt;.&lt;/span&gt;log(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;data: &amp;#39;&lt;/span&gt; &lt;span style=&#34;color:#f92672&#34;&gt;+&lt;/span&gt; data)      })    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/&lt;/span&gt;script&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;lt;/&lt;/span&gt;body&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&amp;lt;/&lt;/span&gt;html&lt;span style=&#34;color:#f92672&#34;&gt;&amp;gt;&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;演示步骤:&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
