PageSourceSearch

https://webrtc.org/getting-started/firebase-rtc-codelab

html webrtc.org collected 2026-09-24 07:14:29 UTC 75,927 bytes, 1,746 lines download raw bytes

1
2
3
4
5
6
7
8
9
10<!doctype html>
11<html 
12      lang="en"
13      dir="ltr">
14  <head>
15    <meta name="google-signin-client-id" content="157101835696-ooapojlodmuabs2do2vuhhnf90bccmoi.apps.googleusercontent.com"><meta name="google-signin-scope"
16          content="profile email"><meta property="og:site_name" content="WebRTC">
17    <meta property="og:type" content="website"><meta name="theme-color" content="#4285f4"><meta charset="utf-8">
18    <meta content="IE=Edge" http-equiv="X-UA-Compatible">
19    <meta name="viewport" content="width=device-width, initial-scale=1">
20    
21
22    <link rel="manifest" href="/_pwa/webrtc/manifest.json"
23          crossorigin="use-credentials">
24    <link rel="preconnect" href="//www.gstatic.com" crossorigin>
25    <link rel="preconnect" href="//fonts.googleapis.com" crossorigin>
26    <link rel="preconnect" href="//www.google-analytics.com" crossorigin><link rel="stylesheet" href="//fonts.googleapis.com/css?family=Roboto:300,400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap">
27      <link rel="stylesheet"
28            href="//fonts.googleapis.com/css2?family=Material+Icons&family=Material+Symbols+Outlined&display=block"><link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc/css/app.css">
29      
30        <link rel="stylesheet" href="https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc/css/dark-theme.css" disabled>
31      <link rel="shortcut icon" href="https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc/images/favicon.png">
32    <link rel="apple-touch-icon" href="https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc/images/touchicon-180.png"><link rel="canonical" href="https://webrtc.org/getting-started/firebase-rtc-codelab"><link rel="search" type="application/opensearchdescription+xml"
33            title="WebRTC" href="https://webrtc.org/s/opensearch.xml">
34      <link rel="alternate" hreflang="en"
35          href="https://webrtc.org/getting-started/firebase-rtc-codelab" /><link rel="alternate" hreflang="x-default" href="https://webrtc.org/getting-started/firebase-rtc-codelab" /><link rel="alternate" hreflang="ar"
36          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=ar" /><link rel="alternate" hreflang="bn"
37          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=bn" /><link rel="alternate" hreflang="zh-Hans"
38          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=zh-cn" /><link rel="alternate" hreflang="zh-Hant"
39          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=zh-tw" /><link rel="alternate" hreflang="fa"
40          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=fa" /><link rel="alternate" hreflang="fr"
41          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=fr" /><link rel="alternate" hreflang="de"
42          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=de" /><link rel="alternate" hreflang="he"
43          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=he" /><link rel="alternate" hreflang="hi"
44          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=hi" /><link rel="alternate" hreflang="id"
45          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=id" /><link rel="alternate" hreflang="it"
46          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=it" /><link rel="alternate" hreflang="ja"
47          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=ja" /><link rel="alternate" hreflang="ko"
48          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=ko" /><link rel="alternate" hreflang="pl"
49          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=pl" /><link rel="alternate" hreflang="pt-BR"
50          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=pt-br" /><link rel="alternate" hreflang="ru"
51          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=ru" /><link rel="alternate" hreflang="es-419"
52          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=es-419" /><link rel="alternate" hreflang="th"
53          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=th" /><link rel="alternate" hreflang="tr"
54          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=tr" /><link rel="alternate" hreflang="vi"
55          href="https://webrtc.org/getting-started/firebase-rtc-codelab?hl=vi" /><title>Firebase + WebRTC Codelab</title>
56
57<meta property="og:title" content="Firebase + WebRTC Codelab"><meta property="og:url" content="https://webrtc.org/getting-started/firebase-rtc-codelab"><meta property="og:locale" content="en">
57<script type="application/ld+json">
58  {
59    "@context": "https://schema.org",
60    "@type": "Article",
61    
62    "headline": "Firebase + WebRTC Codelab"
63  }
64</script>
64
65  
66
67  
68
69  
70
71
72    </head>
73  <body class="color-scheme--light"
74        template="page"
75        theme="webrtc-theme"
76        type="article"
77        
78        appearance
79        
80        layout="docs"
81        
82        
83        
84        
85        
86        display-toc
87        pending>
88  
89    <devsite-progress type="indeterminate" id="app-progress"></devsite-progress>
90  
91  
92    <a href="#main-content" class="skip-link button">
93      
94      Skip to main content
95    </a>
96    <section class="devsite-wrapper">
97      <devsite-cookie-notification-bar></devsite-cookie-notification-bar>
98        <devsite-header role="banner" keep-tabs-visible>
99  
100    
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122<div class="devsite-header--inner" data-nosnippet>
123  <div class="devsite-top-logo-row-wrapper-wrapper">
124    <div class="devsite-top-logo-row-wrapper">
125      <div class="devsite-top-logo-row">
126        <button type="button" id="devsite-hamburger-menu"
127          class="devsite-header-icon-button button-flat material-icons gc-analytics-event"
128          data-category="Site-Wide Custom Events"
129          data-label="Navigation menu button"
130          visually-hidden
131          aria-label="Open menu">
132        </button>
133        
134<div class="devsite-product-name-wrapper">
135
136  <a href="/" class="devsite-site-logo-link gc-analytics-event"
137   data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav"
138   track-name="webRTC" track-metadata-position="nav"
139   track-metadata-eventDetail="nav">
140  
141  <picture>
142    
143    <source srcset="https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc/images/lockup-dark-theme.svg"
144            media="(prefers-color-scheme: dark)"
145            class="devsite-dark-theme">
146    
147    <img src="https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc/images/lockup.svg" class="devsite-site-logo" alt="WebRTC">
148  </picture>
149  
150</a>
151
152
153
154</div>
155        <div class="devsite-top-logo-row-middle">
156          <div class="devsite-header-upper-tabs">
157            
158           </div>
159          
160<devsite-search
161    enable-signin
162    enable-search
163    enable-suggestions
164      enable-query-completion
165    
166    enable-search-summaries
167    project-name="WebRTC"
168    tenant-name="WebRTC"
169    
170    
171    
172    
173    
174    >
175  <form class="devsite-search-form" action="https://webrtc.org/s/results" method="GET">
176    <div class="devsite-search-container">
177      <button type="button"
178              search-open
179              class="devsite-search-button devsite-header-icon-button button-flat material-icons"
180              
181              aria-label="Open search"></button>
182      <div class="devsite-searchbox">
183        <input
184          aria-activedescendant=""
185          aria-autocomplete="list"
186          
187          aria-label="Search"
188          aria-expanded="false"
189          aria-haspopup="listbox"
190          autocomplete="off"
191          class="devsite-search-field devsite-search-query"
192          name="q"
193          
194          placeholder="Search"
195          role="combobox"
196          type="text"
197          value=""
198          >
199          <div class="devsite-search-image material-icons" aria-hidden="true">
200            
201              <svg class="devsite-search-ai-image" width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
202                  <g clip-path="url(#clip0_6641_386)">
203                    <path d="M19.6 21L13.3 14.7C12.8 15.1 12.225 15.4167 11.575 15.65C10.925 15.8833 10.2333 16 9.5 16C7.68333 16 6.14167 15.375 4.875 14.125C3.625 12.8583 3 11.3167 3 9.5C3 7.68333 3.625 6.15 4.875 4.9C6.14167 3.63333 7.68333 3 9.5 3C10.0167 3 10.5167 3.05833 11 3.175C11.4833 3.275 11.9417 3.43333 12.375 3.65L10.825 5.2C10.6083 5.13333 10.3917 5.08333 10.175 5.05C9.95833 5.01667 9.73333 5 9.5 5C8.25 5 7.18333 5.44167 6.3 6.325C5.43333 7.19167 5 8.25 5 9.5C5 10.75 5.43333 11.8167 6.3 12.7C7.18333 13.5667 8.25 14 9.5 14C10.6667 14 11.6667 13.625 12.5 12.875C13.35 12.1083 13.8417 11.15 13.975 10H15.975C15.925 10.6333 15.7833 11.2333 15.55 11.8C15.3333 12.3667 15.05 12.8667 14.7 13.3L21 19.6L19.6 21ZM17.5 12C17.5 10.4667 16.9667 9.16667 15.9 8.1C14.8333 7.03333 13.5333 6.5 12 6.5C13.5333 6.5 14.8333 5.96667 15.9 4.9C16.9667 3.83333 17.5 2.53333 17.5 0.999999C17.5 2.53333 18.0333 3.83333 19.1 4.9C20.1667 5.96667 21.4667 6.5 23 6.5C21.4667 6.5 20.1667 7.03333 19.1 8.1C18.0333 9.16667 17.5 10.4667 17.5 12Z" fill="#5F6368"/>
204                  </g>
205                <defs>
206                <clipPath id="clip0_6641_386">
207                <rect width="24" height="24" fill="white"/>
208                </clipPath>
209                </defs>
210              </svg>
211            
212          </div>
213          <div class="devsite-search-shortcut-icon-container" aria-hidden="true">
214            <kbd class="devsite-search-shortcut-icon">/</kbd>
215          </div>
216      </div>
217    </div>
218  </form>
219  <button type="button"
220          search-close
221          class="devsite-search-button devsite-header-icon-button button-flat material-icons"
222          
223          aria-label="Close search"></button>
224</devsite-search>
225
226        </div>
227
228        
229
230          
231
232          
233
234          
235
236          <devsite-appearance-selector></devsite-appearance-selector>
237
238          
239<devsite-language-selector>
240  <ul role="presentation">
241    
242    
243    <li role="presentation">
244      <a role="menuitem" lang="en"
245        >English</a>
246    </li>
247    
248    <li role="presentation">
249      <a role="menuitem" lang="de"
250        >Deutsch</a>
251    </li>
252    
253    <li role="presentation">
254      <a role="menuitem" lang="es"
255        >Español</a>
256    </li>
257    
258    <li role="presentation">
259      <a role="menuitem" lang="es_419"
260        >Español – América Latina</a>
261    </li>
262    
263    <li role="presentation">
264      <a role="menuitem" lang="fr"
265        >Français</a>
266    </li>
267    
268    <li role="presentation">
269      <a role="menuitem" lang="id"
270        >Indonesia</a>
271    </li>
272    
273    <li role="presentation">
274      <a role="menuitem" lang="it"
275        >Italiano</a>
276    </li>
277    
278    <li role="presentation">
279      <a role="menuitem" lang="pl"
280        >Polski</a>
281    </li>
282    
283    <li role="presentation">
284      <a role="menuitem" lang="pt"
285        >Português</a>
286    </li>
287    
288    <li role="presentation">
289      <a role="menuitem" lang="pt_br"
290        >Português – Brasil</a>
291    </li>
292    
293    <li role="presentation">
294      <a role="menuitem" lang="vi"
295        >Tiếng Việt</a>
296    </li>
297    
298    <li role="presentation">
299      <a role="menuitem" lang="tr"
300        >Türkçe</a>
301    </li>
302    
303    <li role="presentation">
304      <a role="menuitem" lang="ru"
305        >Русский</a>
306    </li>
307    
308    <li role="presentation">
309      <a role="menuitem" lang="he"
310        >עברית</a>
311    </li>
312    
313    <li role="presentation">
314      <a role="menuitem" lang="ar"
315        >العربيّة</a>
316    </li>
317    
318    <li role="presentation">
319      <a role="menuitem" lang="fa"
320        >فارسی</a>
321    </li>
322    
323    <li role="presentation">
324      <a role="menuitem" lang="hi"
325        >हिंदी</a>
326    </li>
327    
328    <li role="presentation">
329      <a role="menuitem" lang="bn"
330        >বাংলা</a>
331    </li>
332    
333    <li role="presentation">
334      <a role="menuitem" lang="th"
335        >ภาษาไทย</a>
336    </li>
337    
338    <li role="presentation">
339      <a role="menuitem" lang="zh_cn"
340        >中文 – 简体</a>
341    </li>
342    
343    <li role="presentation">
344      <a role="menuitem" lang="zh_tw"
345        >中文 – 繁體</a>
346    </li>
347    
348    <li role="presentation">
349      <a role="menuitem" lang="ja"
350        >日本語</a>
351    </li>
352    
353    <li role="presentation">
354      <a role="menuitem" lang="ko"
355        >한국어</a>
356    </li>
357    
358  </ul>
359</devsite-language-selector>
360
361
362          
363
364        
365
366        
367          <devsite-user 
368                        
369                        
370                        
371                        id="devsite-user">
372            
373              
374              <span class="button devsite-top-button" aria-hidden="true" visually-hidden>Sign in</span>
375            
376          </devsite-user>
377        
378        
379        
380      </div>
381    </div>
382  </div>
383
384
385
386  <div class="devsite-collapsible-section
387    ">
388    <div class="devsite-header-background">
389      
390        
391      
392      
393        <div class="devsite-doc-set-nav-row">
394          
395          
396            
397            
398  <devsite-tabs class="lower-tabs">
399
400    <nav class="devsite-tabs-wrapper" aria-label="Lower tabs">
401      
402        
403          <tab  >
404            
405    <a href="https://webrtc.org/"
406    class="devsite-tabs-content gc-analytics-event "
407      track-metadata-eventdetail="https://webrtc.org/"
408    
409       track-type="nav"
410       track-metadata-position="nav - home"
411       track-metadata-module="primary nav"
412       
413       
414         
415           data-category="Site-Wide Custom Events"
416         
417           data-label="Tab: Home"
418         
419           track-name="home"
420         
421       >
422    Home
423  
424    </a>
425    
426  
427          </tab>
428        
429      
430        
431          <tab  class="devsite-active">
432            
433    <a href="https://webrtc.org/getting-started/overview"
434    class="devsite-tabs-content gc-analytics-event "
435      track-metadata-eventdetail="https://webrtc.org/getting-started/overview"
436    
437       track-type="nav"
438       track-metadata-position="nav - guides"
439       track-metadata-module="primary nav"
440       aria-label="Guides, selected" 
441       
442         
443           data-category="Site-Wide Custom Events"
444         
445           data-label="Tab: Guides"
446         
447           track-name="guides"
448         
449       >
450    Guides
451  
452    </a>
453    
454  
455          </tab>
456        
457      
458        
459          <tab  >
460            
461    <a href="https://webrtc.org/support/overview"
462    class="devsite-tabs-content gc-analytics-event "
463      track-metadata-eventdetail="https://webrtc.org/support/overview"
464    
465       track-type="nav"
466       track-metadata-position="nav - support"
467       track-metadata-module="primary nav"
468       
469       
470         
471           data-category="Site-Wide Custom Events"
472         
473           data-label="Tab: Support"
474         
475           track-name="support"
476         
477       >
478    Support
479  
480    </a>
481    
482  
483          </tab>
484        
485      
486    </nav>
487
488  </devsite-tabs>
489
490          
491          
492        </div>
493      
494    </div>
495  </div>
496
497</div>
498
499
500
501  
502</devsite-header>
503        <devsite-book-nav scrollbars >
504          
505            
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527<div class="devsite-book-nav-filter"
528     >
529  <span class="filter-list-icon material-icons" aria-hidden="true"></span>
530  <input type="text"
531         placeholder="Filter"
532         
533         aria-label="Type to filter"
534         role="searchbox">
535  
536  <span class="filter-clear-button hidden"
537        data-title="Clear filter"
538        aria-label="Clear filter"
539        role="button"
540        tabindex="0"></span>
541</div>
542
543<nav class="devsite-book-nav devsite-nav nocontent" data-nosnippet
544     aria-label="Side menu">
545  <div class="devsite-mobile-header">
546    <button type="button"
547            id="devsite-close-nav"
548            class="devsite-header-icon-button button-flat material-icons gc-analytics-event"
549            data-category="Site-Wide Custom Events"
550            data-label="Close navigation"
551            aria-label="Close navigation">
552    </button>
553    <div class="devsite-product-name-wrapper">
554
555  <a href="/" class="devsite-site-logo-link gc-analytics-event"
556   data-category="Site-Wide Custom Events" data-label="Site logo" track-type="globalNav"
557   track-name="webRTC" track-metadata-position="nav"
558   track-metadata-eventDetail="nav">
559  
560  <picture>
561    
562    <source srcset="https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc/images/lockup-dark-theme.svg"
563            media="(prefers-color-scheme: dark)"
564            class="devsite-dark-theme">
565    
566    <img src="https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc/images/lockup.svg" class="devsite-site-logo" alt="WebRTC">
567  </picture>
568  
569</a>
570
571
572</div>
573  </div>
574
575  <div class="devsite-book-nav-wrapper">
576    <div class="devsite-mobile-nav-top">
577      
578        <ul class="devsite-nav-list">
579          
580            
581<li class="devsite-nav-item">
582
583  
584  <a href="/"
585    
586       class="devsite-nav-title gc-analytics-event
587              
588              "
589    
590
591    
592      
593        data-category="Site-Wide Custom Events"
594      
595        data-label="Tab: Home"
596      
597        track-name="home"
598      
599    
600     data-category="Site-Wide Custom Events"
601     data-label="Responsive Tab: Home"
602     track-type="navMenu"
603     track-metadata-eventDetail="globalMenu"
604     track-metadata-position="nav">
605  
606    <span class="devsite-nav-text" tooltip >
607      Home
608   </span>
609    
610  
611  </a>
612  
613
614</li>
615
616          
617            
618<li class="devsite-nav-item">
619
620  
621  <a href="/getting-started/overview"
622    
623       class="devsite-nav-title gc-analytics-event
624              devsite-nav-has-children
625              devsite-nav-active"
626    
627
628    
629      
630        data-category="Site-Wide Custom Events"
631      
632        data-label="Tab: Guides"
633      
634        track-name="guides"
635      
636    
637     data-category="Site-Wide Custom Events"
638     data-label="Responsive Tab: Guides"
639     track-type="navMenu"
640     track-metadata-eventDetail="globalMenu"
641     track-metadata-position="nav">
642  
643    <span class="devsite-nav-text" tooltip >
644      Guides
645   </span>
646    
647    <span class="devsite-nav-icon material-icons" data-icon="forward"
648          >
649    </span>
650    
651  
652  </a>
653  
654
655</li>
656
657          
658            
659<li class="devsite-nav-item">
660
661  
662  <a href="/support/overview"
663    
664       class="devsite-nav-title gc-analytics-event
665              devsite-nav-has-children
666              "
667    
668
669    
670      
671        data-category="Site-Wide Custom Events"
672      
673        data-label="Tab: Support"
674      
675        track-name="support"
676      
677    
678     data-category="Site-Wide Custom Events"
679     data-label="Responsive Tab: Support"
680     track-type="navMenu"
681     track-metadata-eventDetail="globalMenu"
682     track-metadata-position="nav">
683  
684    <span class="devsite-nav-text" tooltip >
685      Support
686   </span>
687    
688    <span class="devsite-nav-icon material-icons" data-icon="forward"
689          >
690    </span>
691    
692  
693  </a>
694  
695
696</li>
697
698          
699          
700          
701        </ul>
702      
703    </div>
704    
705      <div class="devsite-mobile-nav-bottom">
706        
707          
708          <ul class="devsite-nav-list" menu="_book">
709            <li class="devsite-nav-item"><a href="/getting-started/overview"
710        class="devsite-nav-title"
711      ><span class="devsite-nav-text" tooltip>Overview</span></a></li>
712
713  <li class="devsite-nav-item
714           devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path">
715        <span class="devsite-nav-text" tooltip>Get started</span>
716      </div></li>
717
718  <li class="devsite-nav-item"><a href="/getting-started/media-devices"
719        class="devsite-nav-title"
720      ><span class="devsite-nav-text" tooltip>Media devices</span></a></li>
721
722  <li class="devsite-nav-item"><a href="/getting-started/media-capture-and-constraints"
723        class="devsite-nav-title"
724      ><span class="devsite-nav-text" tooltip>Media capture and constraints</span></a></li>
725
726  <li class="devsite-nav-item"><a href="/getting-started/peer-connections"
727        class="devsite-nav-title"
728      ><span class="devsite-nav-text" tooltip>Peer connections</span></a></li>
729
730  <li class="devsite-nav-item"><a href="/getting-started/remote-streams"
731        class="devsite-nav-title"
732      ><span class="devsite-nav-text" tooltip>Remote streams</span></a></li>
733
734  <li class="devsite-nav-item"><a href="/getting-started/data-channels"
735        class="devsite-nav-title"
736      ><span class="devsite-nav-text" tooltip>Data channels</span></a></li>
737
738  <li class="devsite-nav-item"><a href="/getting-started/turn-server"
739        class="devsite-nav-title"
740      ><span class="devsite-nav-text" tooltip>TURN server</span></a></li>
741
742  <li class="devsite-nav-item"><a href="/getting-started/testing"
743        class="devsite-nav-title"
744      ><span class="devsite-nav-text" tooltip>Testing</span></a></li>
745
746  <li class="devsite-nav-item"><a href="/getting-started/unified-plan-transition-guide"
747        class="devsite-nav-title"
748      ><span class="devsite-nav-text" tooltip>Unified Plan transition guide</span></a></li>
749
750  <li class="devsite-nav-item
751           devsite-nav-heading"><div class="devsite-nav-title devsite-nav-title-no-path">
752        <span class="devsite-nav-text" tooltip>Codelabs</span>
753      </div></li>
754
755  <li class="devsite-nav-item"><a href="/getting-started/firebase-rtc-codelab"
756        class="devsite-nav-title"
757      ><span class="devsite-nav-text" tooltip>FirebaseRTC Code lab</span></a></li>
758          </ul>
759        
760        
761        
762          
763    
764  
765    
766  
767    
768  
769        
770      </div>
771    
772  </div>
773</nav>
774          
775        </devsite-book-nav>
776      
777      <section id="gc-wrapper">
778        <main role="main" id="main-content" class="devsite-main-content"
779            
780              has-book-nav
781              has-sidebar
782            >
783          <div class="devsite-sidebar">
784            <div class="devsite-sidebar-content">
785                
786                <devsite-toc class="devsite-nav"
787                            role="navigation"
788                            aria-label="On this page"
789                            depth="2"
790                            scrollbars
791                            data-nosnippet
792                  ></devsite-toc>
793                <devsite-recommendations-sidebar class="nocontent devsite-nav" data-nosnippet>
794                </devsite-recommendations-sidebar>
795            </div>
796          </div>
797          <devsite-content>
798            
799              
800
801
802
803
804
805
806
807
808
809
810<article class="devsite-article">
811  
812  
813  
814    <div class="devsite-banner devsite-banner-announcement nocontent" data-nosnippet
815      
816        
817      >
818      <div class="devsite-banner-message">
819        <div class="devsite-banner-message-text">
820          <style>
821  .devsite-banner-announcement:not(.devsite-banner-tenant) {
822    background: #202124;
823    color: white;
824    font-weight: 500;
825  }
826  .devsite-banner-announcement a {
827    color: white;
828    font-weight: 700;
829  }
830  .devsite-banner-announcement a:link:not(.button),
831  .devsite-banner-announcement a:visited:not(.button) {
832    background: 0;
833  }
834  .devsite-banner-announcement a:hover,
835  .devsite-banner-announcement a:focus {
836    text-decoration: none;
837  }
838  .devsite-banner-announcement .devsite-banner-message-text {
839    margin: 0 auto;
840  }
841</style> <span class="nocontent">
842  Google is committed to advancing racial equity for Black communities.
843</span> <a href="https://google.com/racialequity"
844   class="gc-analytics-event nocontent"
845   data-category="Announcement"
846   data-label="Racial Equity">See how.</a>
847        </div>
848      </div>
849    </div>
850  
851  
852  
853
854  <div class="devsite-article-meta nocontent" role="navigation" data-nosnippet>
855    
856    
857    <ul class="devsite-breadcrumb-list"
858  
859    aria-label="Breadcrumb">
860  
861  <li class="devsite-breadcrumb-item
862             ">
863    
864    
865    
866      
867        
868  <a href="https://webrtc.org/"
869      
870        class="devsite-breadcrumb-link gc-analytics-event"
871      
872        data-category="Site-Wide Custom Events"
873      
874        data-label="Breadcrumbs"
875      
876        data-value="1"
877      
878        track-type="globalNav"
879      
880        track-name="breadcrumb"
881      
882        track-metadata-position="1"
883      
884        track-metadata-eventdetail="WebRTC"
885      
886    >
887    
888          WebRTC
889        
890  </a>
891  
892      
893    
894  </li>
895  
896  <li class="devsite-breadcrumb-item
897             ">
898    
899      
900      <div class="devsite-breadcrumb-guillemet material-icons" aria-hidden="true"></div>
901    
902    
903    
904      
905        
906  <a href="https://webrtc.org/getting-started/overview"
907      
908        class="devsite-breadcrumb-link gc-analytics-event"
909      
910        data-category="Site-Wide Custom Events"
911      
912        data-label="Breadcrumbs"
913      
914        data-value="2"
915      
916        track-type="globalNav"
917      
918        track-name="breadcrumb"
919      
920        track-metadata-position="2"
921      
922        track-metadata-eventdetail=""
923      
924    >
925    
926          Guides
927        
928  </a>
929  
930      
931    
932  </li>
933  
934</ul>
935    
936      
937    <devsite-thumb-rating position="header">
938    </devsite-thumb-rating>
939  
940    
941  </div>
942  
943    <h1 class="devsite-page-title" tabindex="-1">
944      Firebase + WebRTC Codelab<devsite-actions hidden data-nosnippet></devsite-actions>
945  
946      
947    </h1>
948  <div class="devsite-page-title-meta"><devsite-view-release-notes></devsite-view-release-notes></div>
949  
950
951  <devsite-toc class="devsite-nav"
952    depth="2"
953    devsite-toc-embedded
954    >
955  </devsite-toc>
956  
957    
958  <div class="devsite-article-body clearfix
959  ">
960
961  
962    
963    
964
965
966<h2 id="1_introduction" data-text="1. Introduction" tabindex="-1">1. Introduction</h2>
967
968<p>In this codelab, you&#39;ll learn how to build a simple video chat application using
969the WebRTC API in your browser and Cloud Firestore for signaling. The
970application is called FirebaseRTC and works as a simple example that will teach
971you the basics of building WebRTC enabled applications.</p>
972
973<blockquote>
974<aside class="note"><strong>Note:</strong><span> Another option for signaling could be Firebase Cloud Messaging. However,
975that is currently only supported in Chrome and in this codelab we will focus
976on a solution that works across all browsers supporting WebRTC.</span></aside></blockquote>
977
978<h3 id="what_youll_learn" data-text="What you'll learn" tabindex="-1">What you'll learn</h3>
979
980<ul>
981<li>Initiating a video call in a web application using WebRTC</li>
982<li>Signaling to the remote party using Cloud Firestore</li>
983</ul>
984
985<h3 id="what_youll_need" data-text="What you'll need" tabindex="-1">What you'll need</h3>
986
987<p>Before starting this codelab, make sure that you&#39;ve installed:</p>
988
989<ul>
990<li>npm which typically comes with Node.js - Node LTS is recommended</li>
991</ul>
992
993<h2 id="2_create_and_set_up_a_firebase_project" data-text="2. Create and set up a Firebase project" tabindex="-1">2. Create and set up a Firebase project</h2>
994
995<h3 id="create_a_firebase_project" data-text="Create a Firebase project" tabindex="-1">Create a Firebase project</h3>
996
997<ol>
998<li><a href="https://console.firebase.google.com">In the Firebase console</a>, click Add
999project, then name the Firebase project FirebaseRTC.</li>
1000</ol>
1001
1002<p>Remember the Project ID for your Firebase project.</p>
1003
1004<blockquote>
1005<aside class="note"><strong>Note:</strong><span> If you go to the home page of your project, you can see it in Settings &gt;
1006Project Settings (or look at the URL!)</span></aside></blockquote>
1007
1008<ol>
1009<li>Click Create project.</li>
1010</ol>
1011
1012<p>The application that you&#39;re going to build uses two Firebase services available
1013on the web:</p>
1014
1015<ul>
1016<li>Cloud Firestore to save structured data on the Cloud and get instant
1017notification when the data is updated</li>
1018<li>Firebase Hosting to host and serve your static assets</li>
1019</ul>
1020
1021<p>For this specific codelab, you&#39;ve already configured Firebase Hosting in the
1022project you&#39;ll be cloning. However, for Cloud Firestore, we&#39;ll walk you through
1023the configuration and enabling of the services using the Firebase console.</p>
1024
1025<h3 id="enable_cloud_firestore" data-text="Enable Cloud Firestore" tabindex="-1">Enable Cloud Firestore</h3>
1026
1027<p>The app uses Cloud Firestore to save the chat messages and receive new chat
1028messages.</p>
1029
1030<p>You&#39;ll need to enable Cloud Firestore:</p>
1031
1032<ol>
1033<li>In the Firebase console menu&#39;s Develop section, click Database.</li>
1034<li>Click <strong>Create database</strong> in the Cloud Firestore pane.</li>
1035<li>Select the <strong>Start in test mode</strong> option, then click Enable after reading the
1036disclaimer about the security rules.</li>
1037</ol>
1038
1039<p>Test mode ensures that you can freely write to the database during development.
1040We&#39;ll make our database more secure later on in this codelab.</p>
1041
1042<h2 id="3_get_the_sample_code" data-text="3. Get the sample code" tabindex="-1">3. Get the sample code</h2>
1043
1044<p>Clone the GitHub repository from the command line:</p>
1045<div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr">git<span class="devsite-syntax-w"> </span>clone<span class="devsite-syntax-w"> </span>https://github.com/webrtc/FirebaseRTC
1046</code></pre></devsite-code>
1047<p>The sample code should have been cloned into the <code translate="no" dir="ltr">FirebaseRTC</code> directory.
1048Make sure your command line is run from this directory from now on:</p>
1049<div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="Bash"><code translate="no" dir="ltr"><span class="devsite-syntax-nb">cd</span><span class="devsite-syntax-w"> </span>FirebaseRTC
1050</code></pre></devsite-code>
1051<h3 id="import_the_starter_app" data-text="Import the starter app" tabindex="-1">Import the starter app</h3>
1052
1053<p>Open the files in <code translate="no" dir="ltr">FirebaseRTC</code> in your editor and change them according to
1054the instructions below. This directory contains the starting code for the
1055codelab which consists of a not-yet functional WebRTC app. We&#39;ll make it
1056functional throughout this codelab.</p>
1057
1058<h2 id="4_install_the_firebase_command_line_interface" data-text="4. Install the Firebase Command Line Interface" tabindex="-1">4. Install the Firebase Command Line Interface</h2>
1059
1060<p>The Firebase Command Line Interface (CLI) allows you to serve your web app
1061locally and deploy your web app to Firebase Hosting.</p>
1062
1063<blockquote>
1064<aside class="note"><strong>Note:</strong><span> To install the CLI, you need to install npm which typically comes with
1065Node.js.</span></aside></blockquote>
1066
1067<ol>
1068<li>Install the CLI by running the following npm command:
1069<code translate="no" dir="ltr">sh
1070npm -g install firebase-tools</code></li>
1071</ol>
1072
1073<blockquote>
1074<aside class="note"><strong>Note:</strong><span> Doesn&#39;t work? You may need to run the command using <code translate="no" dir="ltr">sudo</code> instead.</span></aside></blockquote>
1075
1076<ol>
1077<li>Verify that the CLI has been installed correctly by running the following
1078command:
1079<code translate="no" dir="ltr">sh
1080firebase --version</code></li>
1081</ol>
1082
1083<p>Make sure the version of the Firebase CLI is v6.7.1 or later.</p>
1084
1085<ol>
1086<li>Authorize the Firebase CLI by running the following command:
1087<code translate="no" dir="ltr">sh
1088firebase login</code></li>
1089</ol>
1090
1091<p>You&#39;ve set up the web app template to pull your app&#39;s configuration for Firebase
1092Hosting from your app&#39;s local directory and files. But to do this, you need to
1093associate your app with your Firebase project.</p>
1094
1095<ol>
1096<li><p>Associate your app with your Firebase project by running the following
1097command:
1098<code translate="no" dir="ltr">sh
1099firebase use --add</code></p></li>
1100<li><p>When prompted, select your Project ID, then give your Firebase project an
1101alias.</p></li>
1102</ol>
1103
1104<p>An alias is useful if you have multiple environments (production, staging, etc).
1105However, for this codelab, let&#39;s just use the alias of <code translate="no" dir="ltr">default</code>.</p>
1106
1107<ol>
1108<li><p>Follow the remaining instructions in your command line.</p></li>
1109</ol>
1110
1111<h2 id="5_run_the_local_server" data-text="5. Run the local server" tabindex="-1">5. Run the local server</h2>
1112
1113<p>You&#39;re ready to actually start work on our app! Let&#39;s run the app locally!</p>
1114
1115<ol>
1116<li><p>Run the following Firebase CLI command:
1117<code translate="no" dir="ltr">sh
1118firebase serve --only hosting</code></p></li>
1119<li><p>Your command line should display the following response:
1120<code translate="no" dir="ltr">hosting: Local server: http://localhost:5000</code></p></li>
1121</ol>
1122
1123<p>We&#39;re using the Firebase Hosting emulator to serve our app locally. The web app
1124should now be available from http://localhost:5000.</p>
1125
1126<ol>
1127<li>Open your app at http://localhost:5000.</li>
1128</ol>
1129
1130<p>You should see your copy of FirebaseRTC which has been connected to your
1131Firebase project.</p>
1132
1133<p>The app has automatically connected to your Firebase project.</p>
1134
1135<h2 id="6_creating_a_new_room" data-text="6. Creating a new room" tabindex="-1">6. Creating a new room</h2>
1136
1137<p>In this application, each video chat session is called a room. A user can create
1138a new room by clicking a button in their application. This will generate an ID
1139that the remote party can use to join the same room. The ID is used as the key
1140in Cloud Firestore for each room.</p>
1141
1142<p>
1142Each room will contain the <code translate="no" dir="ltr">RTCSessionDescriptions</code> for both the offer and the
1143answer, as well as two separate collections with ICE candidates from each party.</p>
1144
1145<p>Your first task is to implement the missing code for creating a new room with
1146the initial offer from the caller. Open <code translate="no" dir="ltr">public/app.js</code> and find the comment <code translate="no" dir="ltr">//
1147Add code for creating a room here</code> and add the following code:</p>
1148<div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="JavaScript"><code translate="no" dir="ltr"><span class="devsite-syntax-kd">const</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">offer</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">await</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">peerConnection</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">createOffer</span><span class="devsite-syntax-p">();</span>
1149<span class="devsite-syntax-k">await</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">peerConnection</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">setLocalDescription</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">offer</span><span class="devsite-syntax-p">);</span>
1150
1151<span class="devsite-syntax-kd">const</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">roomWithOffer</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span>
1152<span class="devsite-syntax-w">    </span><span class="devsite-syntax-nx">offer</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span>
1153<span class="devsite-syntax-w">        </span><span class="devsite-syntax-nx">type</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">offer</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">type</span><span class="devsite-syntax-p">,</span>
1154<span class="devsite-syntax-w">        </span><span class="devsite-syntax-nx">sdp</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">offer</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">sdp</span>
1155<span class="devsite-syntax-w">    </span><span class="devsite-syntax-p">}</span>
1156<span class="devsite-syntax-p">}</span>
1157<span class="devsite-syntax-kd">const</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">roomRef</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">await</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">db</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">collection</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s1">'rooms'</span><span class="devsite-syntax-p">).</span><span class="devsite-syntax-nx">add</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">roomWithOffer</span><span class="devsite-syntax-p">);</span>
1158<span class="devsite-syntax-kd">const</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">roomId</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">roomRef</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">id</span><span class="devsite-syntax-p">;</span>
1159<span class="devsite-syntax-nb">document</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">querySelector</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s1">'#currentRoom'</span><span class="devsite-syntax-p">).</span><span class="devsite-syntax-nx">innerText</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-sb">`Current room is </span><span class="devsite-syntax-si">${</span><span class="devsite-syntax-nx">roomId</span><span class="devsite-syntax-si">}</span><span class="devsite-syntax-sb"> - You are the caller!`</span>
1160</code></pre></devsite-code>
1161<p>The first line creates an <code translate="no" dir="ltr">RTCSessionDescription</code> that will represent the offer
1162from the caller. This is then set as the local description, and finally written
1163to the new room object in Cloud Firestore.</p>
1164
1165<p>Next, we will listen for changes to the database and detect when an answer from
1166the callee has been added.</p>
1167<div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="JavaScript"><code translate="no" dir="ltr"><span class="devsite-syntax-nx">roomRef</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">onSnapshot</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-k">async</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">snapshot</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">-</span>&gt;<span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span>
1168<span class="devsite-syntax-w">    </span><span class="devsite-syntax-nx">console</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">log</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s1">'Got updated room:'</span><span class="devsite-syntax-p">,</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">snapshot</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">data</span><span class="devsite-syntax-p">());</span>
1169<span class="devsite-syntax-w">    </span><span class="devsite-syntax-kd">const</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">data</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">snapshot</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">data</span><span class="devsite-syntax-p">();</span>
1170<span class="devsite-syntax-w">    </span><span class="devsite-syntax-k">if</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-o">!</span><span class="devsite-syntax-nx">peerConnection</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">currentRemoteDescription</span><span class="devsite-syntax-w"> &amp;&amp; </span><span class="devsite-syntax-nx">data</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">answer</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span>
1171<span class="devsite-syntax-w">        </span><span class="devsite-syntax-nx">console</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">log</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s1">'Set remote description: '</span><span class="devsite-syntax-p">,</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">data</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">answer</span><span class="devsite-syntax-p">);</span>
1172<span class="devsite-syntax-w">        </span><span class="devsite-syntax-kd">const</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">answer</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-ow">new</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">RTCSessionDescription</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">data</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">answer</span><span class="devsite-syntax-p">)</span>
1173<span class="devsite-syntax-w">        </span><span class="devsite-syntax-k">await</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">peerConnection</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">setRemoteDescription</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">answer</span><span class="devsite-syntax-p">);</span>
1174<span class="devsite-syntax-w">    </span><span class="devsite-syntax-p">}</span>
1175<span class="devsite-syntax-p">});
1175</span>
1176</code></pre></devsite-code>
1177<p>This will wait until the callee writes the <code translate="no" dir="ltr">RTCSessionDescription</code> for the
1178answer, and set that as the remote description on the caller
1179<code translate="no" dir="ltr">RTCPeerConnection</code>.</p>
1180
1181<h2 id="7_joining_a_room" data-text="7. Joining a room" tabindex="-1">7. Joining a room</h2>
1182
1183<p>The next step is to implement the logic for joining an existing room. The user
1184does this by clicking the <strong>Join room</strong> button and entering the ID for the room
1185to join. Your task here is to implement the creation of the
1186<code translate="no" dir="ltr">RTCSessionDescription</code> for the answer and update the room in the database
1187accordingly.</p>
1188<div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="JavaScript"><code translate="no" dir="ltr"><span class="devsite-syntax-kd">const</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">offer</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">roomSnapshot</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">data</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-nx">offer</span><span class="devsite-syntax-p">;</span>
1189<span class="devsite-syntax-k">await</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">peerConnection</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">setRemoteDescription</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">offer</span><span class="devsite-syntax-p">);</span>
1190<span class="devsite-syntax-kd">const</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">answer</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-k">await</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">peerConnection</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">createAnswer</span><span class="devsite-syntax-p">();</span>
1191<span class="devsite-syntax-k">await</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">peerConnection</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">setLocalDescription</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">answer</span><span class="devsite-syntax-p">);</span>
1192
1193<span class="devsite-syntax-kd">const</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">roomWithAnswer</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span>
1194<span class="devsite-syntax-w">    </span><span class="devsite-syntax-nx">answer</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span>
1195<span class="devsite-syntax-w">        </span><span class="devsite-syntax-nx">type</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">answer</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">type</span><span class="devsite-syntax-p">,</span>
1196<span class="devsite-syntax-w">        </span><span class="devsite-syntax-nx">sdp</span><span class="devsite-syntax-o">:</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">answer</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">sdp</span>
1197<span class="devsite-syntax-w">    </span><span class="devsite-syntax-p">}</span>
1198<span class="devsite-syntax-p">}</span>
1199<span class="devsite-syntax-k">await</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">roomRef</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">update</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">roomWithAnswer</span><span class="devsite-syntax-p">);</span>
1200</code></pre></devsite-code>
1201<p>In the code above, we start by extracting the offer from the caller and creating
1202a <code translate="no" dir="ltr">RTCSessionDescription</code> that we set as the remote description. Next, we create
1203the answer, set it as the local description, and update the database. The update
1204of the database will trigger the <code translate="no" dir="ltr">onSnapshot</code> callback on the caller side, which
1205in turn will set the remote description based on the answer from the callee.
1206This completes the exchange of the <code translate="no" dir="ltr">RTCSessionDescription</code> objects between the
1207caller and the callee.</p>
1208
1209<h2 id="8_collect_ice_candidates" data-text="8. Collect ICE candidates" tabindex="-1">8. Collect ICE candidates</h2>
1210
1211<p>Before the caller and callee can connect to each other, they also need to
1212exchange ICE candidates that tell WebRTC how to connect to the remote peer.
1213Your next task is to implement the code that listens for ICE candidates and adds
1214them to a collection in the database. Find the function <code translate="no" dir="ltr">collectIceCandidates</code>
1215and add the following code:</p>
1216<div></div><devsite-code><pre class="devsite-click-to-copy" translate="no" dir="ltr" is-upgraded syntax="JavaScript"><code translate="no" dir="ltr"><span class="devsite-syntax-k">async</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-kd">function</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">collectIceCandidates</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">roomRef</span><span class="devsite-syntax-p">,</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">peerConnection</span><span class="devsite-syntax-p">,</span>
1217<span class="devsite-syntax-w">                                    </span><span class="devsite-syntax-nx">localName</span><span class="devsite-syntax-p">,</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">remoteName</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span>
1218<span class="devsite-syntax-w">    </span><span class="devsite-syntax-kd">const</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">candidatesCollection</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">roomRef</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">collection</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">localName</span><span class="devsite-syntax-p">);</span>
1219
1220<span class="devsite-syntax-w">    </span><span class="devsite-syntax-nx">peerConnection</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">addEventListener</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-s1">
1220'icecandidate'</span><span class="devsite-syntax-p">,</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">event</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">-</span>&gt;<span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span>
1221<span class="devsite-syntax-w">        </span><span class="devsite-syntax-k">if</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">event</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">candidate</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span>
1222<span class="devsite-syntax-w">            </span><span class="devsite-syntax-kd">const</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">json</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">event</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">candidate</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">toJSON</span><span class="devsite-syntax-p">();</span>
1223<span class="devsite-syntax-w">            </span><span class="devsite-syntax-nx">candidatesCollection</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">add</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">json</span><span class="devsite-syntax-p">);</span>
1224<span class="devsite-syntax-w">        </span><span class="devsite-syntax-p">}</span>
1225<span class="devsite-syntax-w">    </span><span class="devsite-syntax-p">});</span>
1226
1227<span class="devsite-syntax-w">    </span><span class="devsite-syntax-nx">roomRef</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">collection</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">remoteName</span><span class="devsite-syntax-p">).</span><span class="devsite-syntax-nx">onSnapshot</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">snapshot</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">-</span>&gt;<span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span>
1228<span class="devsite-syntax-w">        </span><span class="devsite-syntax-nx">snapshot</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">docChanges</span><span class="devsite-syntax-p">().</span><span class="devsite-syntax-nx">forEach</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">change</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">-</span>&gt;<span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span>
1229<span class="devsite-syntax-w">            </span><span class="devsite-syntax-k">if</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">change</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">type</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">===</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-s2">"added"</span><span class="devsite-syntax-p">)</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-p">{</span>
1230<span class="devsite-syntax-w">                </span><span class="devsite-syntax-kd">const</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">candidate</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-o">=</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-ow">new</span><span class="devsite-syntax-w"> </span><span class="devsite-syntax-nx">RTCIceCandidate</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">change</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">doc</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">data</span><span class="devsite-syntax-p">());</span>
1231<span class="devsite-syntax-w">                </span><span class="devsite-syntax-nx">peerConnection</span><span class="devsite-syntax-p">.</span><span class="devsite-syntax-nx">addIceCandidate</span><span class="devsite-syntax-p">(</span><span class="devsite-syntax-nx">candidate</span><span class="devsite-syntax-p">);</span>
1232<span class="devsite-syntax-w">            </span><span class="devsite-syntax-p">}</span>
1233<span class="devsite-syntax-w">        </span><span class="devsite-syntax-p">});
1233</span>
1234<span class="devsite-syntax-w">    </span><span class="devsite-syntax-p">})</span>
1235<span class="devsite-syntax-p">}</span>
1236</code></pre></devsite-code>
1237<p>This function does two things. It collects ICE candidates from the WebRTC API and
1238adds them to the database, and listens for added ICE candidates from the remote
1239peer and adds them to its <code translate="no" dir="ltr">RTCPeerConnection</code> instance. It is important when
1240listening to database changes to filter out anything that isn&#39;t a new addition,
1241since we otherwise would have added the same set of ICE candidates over and over
1242again.</p>
1243
1244<h2 id="9_conclusion" data-text="9. Conclusion" tabindex="-1">9. Conclusion</h2>
1245
1246<p>In this codelab you learned how to implement signaling for WebRTC using Cloud
1247Firestore, as well as how to use that for creating a simple video chat
1248application.</p>
1249
1250<p>To learn more, visit the following resources:</p>
1251
1252<ol>
1253<li><a href="https://github.com/webrtc/FirebaseRTC">FirebaseRTC Source Code</a></li>
1254<li><a href="https://webrtc.github.io/samples">WebRTC samples</a></li>
1255<li><a href="https://firebase.google.com/docs/firestore/">Cloud Firestore</a></li>
1256</ol>
1257
1258  
1259
1260  
1261</div>
1262
1263  
1264    
1265    
1266      
1267    <devsite-thumb-rating position="footer">
1268    </devsite-thumb-rating>
1269  
1270       
1271    
1272    
1273  
1274
1275  <div class="devsite-floating-action-buttons"></div></article>
1276
1277
1278<devsite-content-footer class="nocontent" data-nosnippet>
1279  <p>Except as otherwise noted, the content of this page is licensed under the <a href="https://creativecommons.org/licenses/by/4.0/">Creative Commons Attribution 4.0 License</a>, and code samples are licensed under the <a href="https://www.apache.org/licenses/LICENSE-2.0">Apache 2.0 License</a>. For details, see the <a href="https://developers.google.com/site-policies">Google Developers Site Policies</a>. Java is a registered trademark of Oracle and/or its affiliates.</p>
1280  <p>Last updated 2023-03-29 UTC.</p>
1281</devsite-content-footer>
1282
1283
1284<devsite-notification
1285>
1286</devsite-notification>
1287
1288
1289  
1290<div class="devsite-content-data">
1291  
1292  
1293    <template class="devsite-content-data-template">
1294      [[["Easy to understand","easyToUnderstand","thumb-up"],["Solved my problem","solvedMyProblem","thumb-up"],["Other","otherUp","thumb-up"]],[["Missing the information I need","missingTheInformationINeed","thumb-down"],["Too complicated / too many steps","tooComplicatedTooManySteps","thumb-down"],["Out of date","outOfDate","thumb-down"],["Samples / code issue","samplesCodeIssue","thumb-down"],["Other","otherDown","thumb-down"]],["Last updated 2023-03-29 UTC."],[],[]]
1295    </template>
1296  
1297</div>
1298            
1299          </devsite-content>
1300        </main>
1301        <devsite-footer-promos class="devsite-footer">
1302          
1303            
1304          
1305        </devsite-footer-promos>
1306        <devsite-footer-linkboxes class="devsite-footer">
1307          
1308            
1309<nav class="devsite-footer-linkboxes nocontent"
1310     aria-label="Footer links"
1311     data-nosnippet>
1312  
1313  <ul class="devsite-footer-linkboxes-list">
1314    
1315    <li class="devsite-footer-linkbox ">
1316    <h3 class="devsite-footer-linkbox-heading no-link">Key topics</h3>
1317      <ul class="devsite-footer-linkbox-list">
1318        
1319        <li class="devsite-footer-linkbox-item">
1320          
1321          <a href="//developer.mozilla.org/en-US/docs/Glossary/WebRTC"
1322             class="devsite-footer-linkbox-link gc-analytics-event"
1323             data-category="Site-Wide Custom Events"
1324            
1325             data-label="Footer Link (index 1)"
1326            >
1327            
1328          
1329            WebRTC on MDN
1330          
1331          </a>
1332          
1333          
1334        </li>
1335        
1336        <li class="devsite-footer-linkbox-item">
1337          
1338          <a href="//webrtc.github.io/samples/"
1339             class="devsite-footer-linkbox-link gc-analytics-event"
1340             data-category="Site-Wide Custom Events"
1341            
1342             data-label="Footer Link (index 2)"
1343            >
1344            
1345          
1346            Samples
1347          
1348          </a>
1349          
1350          
1351        </li>
1352        
1353        <li class="devsite-footer-linkbox-item">
1354          
1355          <a href="//webrtc.googlesource.com/src"
1356             class="devsite-footer-linkbox-link gc-analytics-event"
1357             data-category="Site-Wide Custom Events"
1358            
1359             data-label="Footer Link (index 3)"
1360            >
1361            
1362              
1363              
1364            
1365          
1366            Source repository
1367          
1368          </a>
1369          
1370          
1371        </li>
1372        
1373      </ul>
1374    </li>
1375    
1376    <li class="devsite-footer-linkbox ">
1377    <h3 class="devsite-footer-linkbox-heading no-link">Support</h3>
1378      <ul class="devsite-footer-linkbox-list">
1379        
1380        <li class="devsite-footer-linkbox-item">
1381          
1382          <a href="//groups.google.com/forum/#!forum/discuss-webrtc"
1383             class="devsite-footer-linkbox-link gc-analytics-event"
1384             data-category="Site-Wide Custom Events"
1385            
1386             data-label="Footer Link (index 1)"
1387            >
1388            
1389          
1390            Google Groups
1391          
1392          </a>
1393          
1394          
1395        </li>
1396        
1397        <li class="devsite-footer-linkbox-item">
1398          
1399          <a href="//stackoverflow.com/questions/tagged/webrtc"
1400             class="devsite-footer-linkbox-link gc-analytics-event"
1401             data-category="Site-Wide Custom Events"
1402            
1403             data-label="Footer Link (index 2)"
1404            >
1405            
1406          
1407            Stack Overflow
1408          
1409          </a>
1410          
1411          
1412        </li>
1413        
1414        <li class="devsite-footer-linkbox-item">
1415          
1416          <a href="//twitter.com/webrtc"
1417             class="devsite-footer-linkbox-link gc-analytics-event"
1418             data-category="Site-Wide Custom Events"
1419            
1420             data-label="Footer Link (index 3)"
1421            >
1422            
1423              
1424              
1425            
1426          
1427            Twitter
1428          
1429          </a>
1430          
1431          
1432        </li>
1433        
1434      </ul>
1435    </li>
1436    
1437  </ul>
1438  
1439</nav>
1440          
1441        </devsite-footer-linkboxes>
1442        <devsite-footer-utility class="devsite-footer">
1443          
1444            
1445
1446<div class="devsite-footer-utility nocontent" data-nosnippet>
1447  
1448  
1449  <nav class="devsite-footer-sites" aria-label="Other Google Developers websites">
1450    <a href="https://developers.google.com/"
1451       class="devsite-footer-sites-logo-link gc-analytics-event"
1452       data-category="Site-Wide Custom Events"
1453       data-label="Footer Google Developers Link">
1454      <picture>
1455        
1456        <source srcset="https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc/images/lockup-google-for-developers-dark-theme.svg"
1457                media="(prefers-color-scheme: none)"
1458                class="devsite-dark-theme">
1459        
1460        <img class="devsite-footer-sites-logo"
1461             src="https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc/images/lockup-google-for-developers.svg"
1462             loading="lazy"
1463             alt="Google Developers">
1464      </picture>
1465    </a>
1466    <ul class="devsite-footer-sites-list">
1467      
1468      <li class="devsite-footer-sites-item">
1469        <a href="//developer.android.com"
1470           class="devsite-footer-sites-link
1471                  gc-analytics-event"
1472           data-category="Site-Wide Custom Events"
1473         
1474           data-label="Footer Android Link"
1475         
1476         >
1477          Android
1478        </a>
1479      </li>
1480      
1481      <li class="devsite-footer-sites-item">
1482        <a href="//developer.chrome.com/home"
1483           class="devsite-footer-sites-link
1484                  gc-analytics-event"
1485           data-category="Site-Wide Custom Events"
1486         
1487           data-label="Footer Chrome Link"
1488         
1489         >
1490          Chrome
1491        </a>
1492      </li>
1493      
1494      <li class="devsite-footer-sites-item">
1495        <a href="//firebase.google.com"
1496           class="devsite-footer-sites-link
1497                  gc-analytics-event"
1498           data-category="Site-Wide Custom Events"
1499         
1500           data-label="Footer Firebase Link"
1501         
1502         >
1503          Firebase
1504        </a>
1505      </li>
1506      
1507      <li class="devsite-footer-sites-item">
1508        <a href="//cloud.google.com"
1509           class="devsite-footer-sites-link
1510                  gc-analytics-event"
1511           data-category="Site-Wide Custom Events"
1512         
1513           data-label="Footer Google Cloud Platform Link"
1514         
1515         >
1516          Google Cloud Platform
1517        </a>
1518      </li>
1519      
1520      <li class="devsite-footer-sites-item">
1521        <a href="//developers.google.com/products/"
1522           class="devsite-footer-sites-link
1523                  gc-analytics-event"
1524           data-category="Site-Wide Custom Events"
1525         
1526           data-label="Footer All products Link"
1527         
1528         >
1529          All products
1530        </a>
1531      </li>
1532      
1533    </ul>
1534  </nav>
1535  
1536
1537  
1538  <nav class="devsite-footer-utility-links" aria-label="Utility links">
1539    
1540    <ul class="devsite-footer-utility-list">
1541      
1542      <li class="devsite-footer-utility-item
1543                 ">
1544        
1545        
1546        <a class="devsite-footer-utility-link gc-analytics-event"
1547           href="//policies.google.com/terms"
1548           data-category="Site-Wide Custom Events"
1549           data-label="Footer Terms link"
1550         >
1551          Terms
1552        </a>
1553        
1554      </li>
1555      
1556      <li class="devsite-footer-utility-item
1557                 ">
1558        
1559        
1560        <a class="devsite-footer-utility-link gc-analytics-event"
1561           href="//policies.google.com/privacy"
1562           data-category="Site-Wide Custom Events"
1563           data-label="Footer Privacy link"
1564         >
1565          Privacy
1566        </a>
1567        
1568      </li>
1569      
1570      <li class="devsite-footer-utility-item
1571                 glue-cookie-notification-bar-control">
1572        
1573        
1574        <a class="devsite-footer-utility-link gc-analytics-event"
1575           href="#"
1576           data-category="Site-Wide Custom Events"
1577           data-label="Footer Manage cookies link"
1578         
1579           aria-hidden="true"
1580         >
1581          Manage cookies
1582        </a>
1583        
1584      </li>
1585      
1586    </ul>
1587    
1588    
1589<devsite-language-selector>
1590  <ul role="presentation">
1591    
1592    
1593    <li role="presentation">
1594      <a role="menuitem" lang="en"
1595        >English</a>
1596    </li>
1597    
1598    <li role="presentation">
1599      <a role="menuitem" lang="de"
1600        >Deutsch</a>
1601    </li>
1602    
1603    <li role="presentation">
1604      <a role="menuitem" lang="es"
1605        >Español</a>
1606    </li>
1607    
1608    <li role="presentation">
1609      <a role="menuitem" lang="es_419"
1610        >Español – América Latina</a>
1611    </li>
1612    
1613    <li role="presentation">
1614      <a role="menuitem" lang="fr"
1615        >Français</a>
1616    </li>
1617    
1618    <li role="presentation">
1619      <a role="menuitem" lang="id"
1620        >Indonesia</a>
1621    </li>
1622    
1623    <li role="presentation">
1624      <a role="menuitem" lang="it"
1625        >Italiano</a>
1626    </li>
1627    
1628    <li role="presentation">
1629      <a role="menuitem" lang="pl"
1630        >Polski</a>
1631    </li>
1632    
1633    <li role="presentation">
1634      <a role="menuitem" lang="pt"
1635        >Português</a>
1636    </li>
1637    
1638    <li role="presentation">
1639      <a role="menuitem" lang="pt_br"
1640        >Português – Brasil</a>
1641    </li>
1642    
1643    <li role="presentation">
1644      <a role="menuitem" lang="vi"
1645        >Tiếng Việt</a>
1646    </li>
1647    
1648    <li role="presentation">
1649      <a role="menuitem" lang="tr"
1650        >Türkçe</a>
1651    </li>
1652    
1653    <li role="presentation">
1654      <a role="menuitem" lang="ru"
1655        >Русский</a>
1656    </li>
1657    
1658    <li role="presentation">
1659      <a role="menuitem" lang="he"
1660        >עברית</a>
1661    </li>
1662    
1663    <li role="presentation">
1664      <a role="menuitem" lang="ar"
1665        >العربيّة</a>
1666    </li>
1667    
1668    <li role="presentation">
1669      <a role="menuitem" lang="fa"
1670        >فارسی</a>
1671    </li>
1672    
1673    <li role="presentation">
1674      <a role="menuitem" lang="hi"
1675        >हिंदी</a>
1676    </li>
1677    
1678    <li role="presentation">
1679      <a role="menuitem" lang="bn"
1680        >বাংলা</a>
1681    </li>
1682    
1683    <li role="presentation">
1684      <a role="menuitem" lang="th"
1685        >ภาษาไทย</a>
1686    </li>
1687    
1688    <li role="presentation">
1689      <a role="menuitem" lang="zh_cn"
1690        >中文 – 简体</a>
1691    </li>
1692    
1693    <li role="presentation">
1694      <a role="menuitem" lang="zh_tw"
1695        >中文 – 繁體</a>
1696    </li>
1697    
1698    <li role="presentation">
1699      <a role="menuitem" lang="ja"
1700        >日本語</a>
1701    </li>
1702    
1703    <li role="presentation">
1704      <a role="menuitem" lang="ko"
1705        >한국어</a>
1706    </li>
1707    
1708  </ul>
1709</devsite-language-selector>
1710
1711  </nav>
1712</div>
1713          
1714        </devsite-footer-utility>
1715        <devsite-panel>
1716          
1717        </devsite-panel>
1718        
1719      </section>
1720      </section>
1721    <devsite-sitemask></devsite-sitemask>
1722    <devsite-snackbar></devsite-snackbar>
1723    <devsite-tooltip ></devsite-tooltip>
1724    <devsite-heading-link></devsite-heading-link>
1725    <devsite-analytics>
1726      
1727        
1727<script type="application/json" analytics>[{&#34;dimensions&#34;: {&#34;dimension5&#34;: false, &#34;dimension1&#34;: &#34;Signed out&#34;, &#34;dimension2&#34;: false, &#34;dimension4&#34;: &#34;en&#34;, &#34;dimension3&#34;: &#34;en&#34;}, &#34;gaid&#34;: &#34;UA-23466548-1&#34;, &#34;metrics&#34;: {&#34;ratings_count&#34;: &#34;metric2&#34;, &#34;ratings_value&#34;: &#34;metric1&#34;}, &#34;purpose&#34;: 0}]</script>
vendor: 1 bytes, line 1727
1727
1728<script type="application/json" tag-management>{&#34;at&#34;: &#34;True&#34;, &#34;ga4&#34;: [{&#34;id&#34;: &#34;G-KRN165NY0F&#34;, &#34;purpose&#34;: 0}], &#34;ga4p&#34;: [{&#34;id&#34;: &#34;G-KRN165NY0F&#34;, &#34;purpose&#34;: 0}], &#34;gtm&#34;: [], &#34;parameters&#34;: {&#34;internalUser&#34;: &#34;False&#34;, &#34;language&#34;: {&#34;machineTranslated&#34;: &#34;False&#34;, &#34;requested&#34;: &#34;en&#34;, &#34;served&#34;: &#34;en&#34;}, &#34;pageType&#34;: &#34;article&#34;, &#34;projectName&#34;: &#34;WebRTC&#34;, &#34;signedIn&#34;: &#34;False&#34;, &#34;tenant&#34;: &#34;webrtc&#34;, &#34;recommendations&#34;: {&#34;sourcePage&#34;: &#34;&#34;, &#34;sourceType&#34;: 0, &#34;sourceRank&#34;: 0, &#34;sourceIdenticalDescriptions&#34;: 0, &#34;sourceTitleWords&#34;: 0, &#34;sourceDescriptionWords&#34;: 0, &#34;experiment&#34;: &#34;&#34;}, &#34;experiment&#34;: {&#34;ids&#34;: &#34;&#34;}}}</script>
1728
1729      
1730    </devsite-analytics>
1731    
1732    
1733    
1734    
1735<script nonce="sa0r4ivZvbhbg9VIvvvn8iqzddDI1q">
1736  
1737  (function(d,e,v,s,i,t,E){d['GoogleDevelopersObject']=i;
1738    t=e.createElement(v);t.async=1;t.src=s;E=e.getElementsByTagName(v)[0];
1739    E.parentNode.insertBefore(t,E);})(window, document, 'script',
1740    'https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc/js/app_loader.js', '[25,"en",null,"/js/devsite_app_module.js","https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b","https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc","https://webrtc-dot-devsite-v2-prod-3p.appspot.com",null,null,["/_pwa/webrtc/manifest.json","https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/images/video-placeholder.svg","https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc/images/favicon.png","https://www.gstatic.com/devrel-devsite/prod/v5be16d8c9f9402e54c2da2ff24cb75c148f5d2bc84c6f8dfc8b9e16ae456160b/webrtc/images/lockup.svg","https://fonts.googleapis.com/css?family=Roboto:300,400,400italic,500,500italic,700,700italic|Roboto+Mono:400,500,700&display=swap"],1,null,[1,6,8,12,14,17,21,25,50,52,63,70,75,76,80,87,91,92,93,97,98,100,101,102,103,104,105,107,108,109,110,112,113,117,118,120,122,124,125,126,127,129,130,131,132,133,134,135,136,138,140,141,147,148,149,151,152,156,157,158,159,161,163,164,168,169,170,179,180,182,183,186,191,193,196],"AIzaSyCNm9YxQumEXwGJgTDjxoxXK6m1F-9720Q","AIzaSyCc76DZePGtoyUjqKrLdsMGk_ry7sljLbY","webrtc.org","AIzaSyB9bqgQ2t11WJsOX8qNsCQ6U-w91mmqF-I","AIzaSyAdYnStPdzjcJJtQ0mvIaeaMKj7_t6J_Fg",null,null,null,["MiscFeatureFlags__gdp_dashboard_reskin_enabled","MiscFeatureFlags__fix_lower_breadcrumbs","Profiles__enable_profile_collections","MiscFeatureFlags__developers_footer_image","Profiles__enable_auto_apply_credits","CloudShell__cloud_shell_button","Search__enable_ai_search_summaries_for_all","DevPro__enable_embed_profile_creation","MiscFeatureFlags__enable_framebox_badge_methods","Profiles__enable_awarding_url","MiscFeatureFlags__enable_firebase_utm","Concierge__enable_remove_info_panel_tags","MiscFeatureFlags__enable_variable_operator_index_yaml","Profiles__enable_developer_profiles_callout","DevPro__enable_devpro_offers","Cloud__enable_cloud_shell","Profiles__enable_user_type","Profiles__enable_complete_playlist_endpoint","MiscFeatureFlags__enable_explain_this_code","CloudShell__cloud_code_overflow_menu","Cloud__enable_cloud_shell_fte_user_flow","DevPro__enable_free_benefits","Profiles__enable_stripe_subscription_management","Profiles__enable_join_program_group_endpoint","Search__enable_suggestions_from_borg","DevPro__enable_credits_banner","Cloud__enable_cloud_dlp_service","DevPro__enable_g1_ineligible_redirect","Profiles__enable_developer_profile_benefits_ui_redesign","MiscFeatureFlags__enable_explicit_template_dependencies","DevPro__enable_cloud_innovators_plus","MiscFeatureFlags__enable_variable_operator","Search__enable_dynamic_content_confidential_banner","MiscFeatureFlags__enable_appearance_cookies","MiscFeatureFlags__developers_footer_dark_image","DevPro__enable_g1_integration","DevPro__enable_google_payments_buyflow","MiscFeatureFlags__remove_cross_domain_tracking_params","Cloud__enable_cloudx_experiment_ids","DevPro__enable_developer_subscriptions","Analytics__enable_clearcut_logging","Cloud__enable_free_trial_server_call","TpcFeatures__proxy_prod_host","Profiles__enable_developer_profile_pages_as_content","DevPro__enable_devsite_captcha","Cloud__enable_legacy_calculator_redirect","Profiles__enable_public_developer_profiles","DevPro__enable_vertex_credit_card","Profiles__enable_purchase_prompts","Experiments__reqs_query_experiments","Cloud__cache_serialized_dynamic_content","MiscFeatureFlags__enable_dark_theme","Profiles__enable_page_saving","MiscFeatureFlags__enable_project_variables","DevPro__enable_google_payments","EngEduTelemetry__enable_engedu_telemetry","Profiles__enable_recognition_badges","Profiles__enable_release_notes_notifications","Profiles__enable_completecodelab_endpoint","DevPro__enable_firebase_workspaces_card","AIStudioInteractionsToggle__interactions_are_default","Profiles__enable_playlist_community_acl","Profiles__enable_completequiz_endpoint","TpcFeatures__enable_unmirrored_page_left_nav","Profiles__enable_callout_notifications","DevPro__enable_enterprise","DevPro__remove_eu_tax_intake_form","Profiles__enable_targeted_hero","Profiles__require_profile_eligibility_for_signin","SignIn__enable_l1_signup_flow","MiscFeatureFlags__enable_view_transitions","Profiles__enable_dashboard_curated_recommendations","DevPro__enable_nvidia_credits_card","Concierge__enable_actions_menu","DevPro__enable_code_assist","Concierge__enable_pushui","Cloud__fast_free_trial","BookNav__enable_tenant_cache_key","Analytics__enable_devpro_interaction_logging","Search__enable_page_map","DevPro__enable_google_one_card","Search__enable_ai_eligibility_checks"],null,null,"AIzaSyA58TaKli1DculwmAmbpzLVGuWc8eCQgQc","https://developerscontentserving-pa.googleapis.com","AIzaSyDWBU60w0P9hEkr29kkksYs8Z7gvZ8u_wc","https://developerscontentsearch-pa.googleapis.com",2,4,null,"https://developerprofiles-pa.googleapis.com",[25,"webrtc","WebRTC","webrtc.org",null,"webrtc-dot-devsite-v2-prod-3p.appspot.com",null,null,[null,1,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[1],null,null,null,null,null,null,null,null,null,null,null,[1]],null,[35,null,null,null,null,null,"/images/lockup.svg","/images/touchicon-180.png",null,null,null,1,null,1,null,null,null,null,null,null,null,2,null,null,null,"/images/lockup-dark-theme.svg",[]],[],null,
1740null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,[2,4,6,7,1,12,14,15,17,18,20,21,22,23,28,30,32,36,39,40,43],null,[[],[1,1]],[[["UA-23466548-1"],["UA-23466548-2"],null,null,["UA-23466548-3"],null,null,[["G-KRN165NY0F"],null,null,[["G-KRN165NY0F",1]]],[["UA-23466548-1",1]],null,[["UA-23466548-3",1]],null,1],[[4,5],[3,4],[1,1],[5,8],[2,2]],[[1,1],[2,2]]],null,4],null,null,1,1,"https://developerscontentinsights-pa.googleapis.com","AIzaSyC11xEGtFhkmSh_iF6l_itbxnFz2GrIBOg","AIzaSyAXJ10nRF73mmdSDINgkCNX5bbd2KPcWm8","https://developers.googleapis.com",null,null,"AIzaSyCjP0KOnHfv8mwe38sfzZJMOnqE3HvrD4A",null,null,"https://developers.googleapis.com"]')
1741  
1742</script>
1742
1743
1744    <devsite-a11y-announce></devsite-a11y-announce>
1745  </body>
1746</html>

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.