├── .babelrc ├── .eslintrc.js ├── .github ├── ISSUE_TEMPLATE.md └── PULL_REQUEST_TEMPLATE.md ├── .gitignore ├── .stylelintrc ├── .travis.yml ├── AUTHORS ├── CONTRIBUTING.md ├── LICENSE.md ├── README.md ├── google1b7eb21c5b594ba0.html ├── gulpfile.babel.js ├── index.html ├── nightwatch.conf.js ├── nightwatch.json ├── nightwatch ├── customAsserts │ ├── videoHeight.js │ └── videoWidth.js └── customCommands │ ├── waitForMediaPlaybackReady.js │ └── waitForReadyState.js ├── package-lock.json ├── package.json ├── release ├── ChromeWebRTCNetworkLimiterExtension_0.1.zip ├── ChromeWebRTCNetworkLimiterExtension_0.2.1.1.zip └── desktopCaptureExtension.zip └── src ├── content ├── capture │ ├── canvas-pc │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── canvas-record │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── canvas-video │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── video-contenthint │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── video-pc │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ └── video-video │ │ ├── css │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ └── main.js ├── datachannel │ ├── basic │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ ├── datatransfer │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ ├── filetransfer │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ └── messaging │ │ ├── index.html │ │ ├── main.css │ │ └── main.js ├── devices │ ├── input-output │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ └── multi │ │ ├── audio │ │ └── audio.mp3 │ │ ├── css │ │ └── main.css │ │ ├── images │ │ └── poster.jpg │ │ ├── index.html │ │ ├── js │ │ └── main.js │ │ └── video │ │ ├── chrome.mp4 │ │ ├── chrome.ogv │ │ └── chrome.webm ├── extensions │ ├── desktopcapture │ │ ├── README.md │ │ ├── app.js │ │ ├── extension │ │ │ ├── background.js │ │ │ ├── content-script.js │ │ │ ├── icon.png │ │ │ └── manifest.json │ │ └── index.html │ └── multipleroutes │ │ ├── img │ │ └── netli_1280.png │ │ └── src │ │ ├── README.md │ │ ├── _locales │ │ └── en │ │ │ └── messages.json │ │ ├── background.html │ │ ├── eventPage.js │ │ ├── img │ │ ├── icon_128.png │ │ └── icon_16.png │ │ ├── manifest.json │ │ ├── options.html │ │ ├── options.js │ │ └── utils.js ├── getusermedia │ ├── audio │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── canvas │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── filter │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── getdisplaymedia │ │ ├── css │ │ │ └── styles.css │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── gum │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ ├── record │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ ├── resolution │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ ├── source │ │ └── index.html │ └── volume │ │ ├── css │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ ├── main.js │ │ └── soundmeter.js ├── peerconnection │ ├── audio │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ ├── bandwidth │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── constraints │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── create-offer │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── dtmf │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ ├── multiple-relay │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── multiple │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ ├── munge-sdp │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ ├── old-new-stats │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── pc1 │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ ├── pr-answer │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── restart-ice │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ ├── states │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ │ └── main.js │ ├── trickle-ice │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ ├── upgrade │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ ├── js │ │ │ └── main.js │ │ └── test │ │ │ └── test.js │ ├── webaudio-input │ │ ├── audio │ │ │ └── Shamisen-C4.wav │ │ ├── css │ │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ │ ├── main.js │ │ │ └── webaudioextended.js │ └── webaudio-output │ │ ├── css │ │ └── main.css │ │ ├── index.html │ │ └── js │ │ └── main.js └── wasm │ ├── audioctx │ ├── css │ │ └── main.css │ ├── index.html │ └── js │ │ └── main.js │ ├── libvpx │ ├── css │ │ └── main.css │ ├── index.html │ └── js │ │ └── main.js │ ├── webp │ ├── css │ │ └── main.css │ ├── index.html │ └── js │ │ ├── libwebp.js │ │ └── main.js │ └── webrtc │ ├── css │ └── main.css │ ├── index.html │ ├── js │ └── main.js │ └── play.html ├── css └── main.css ├── images └── webrtc-icon-192x192.png ├── js ├── lib │ └── ga.js ├── third_party │ ├── graph.js │ ├── streamvisualizer.js │ └── webgl_teapot │ │ ├── cameracontroller.js │ │ ├── demo.js │ │ ├── images │ │ ├── bump.jpg │ │ ├── skybox-negx.jpg │ │ ├── skybox-negy.jpg │ │ ├── skybox-negz.jpg │ │ ├── skybox-posx.jpg │ │ ├── skybox-posy.jpg │ │ └── skybox-posz.jpg │ │ ├── matrix4x4.js │ │ ├── teapot-streams.js │ │ ├── webgl-debug.js │ │ └── webgl-utils.js └── videopipe.js ├── video ├── chrome.mp4 ├── chrome.webm └── mixed-content.webm └── wasm ├── libvpx ├── libvpx.js ├── libvpx.wasm └── vpx-worker.js ├── libwebp ├── a.out.js └── a.out.wasm └── webrtc ├── beauty.js ├── fetch-worker.js ├── pthread-main.js ├── webrtc.js ├── webrtc.js.mem ├── webrtc.wasm └── webrtc.wasm.map /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "env" 4 | ], 5 | "plugins": [ 6 | "add-module-exports" 7 | ] 8 | } 9 | -------------------------------------------------------------------------------- /.eslintrc.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | 'extends': 'google', 3 | 'parserOptions': { 4 | 'ecmaVersion': 2017, 5 | 'sourceType': 'module', 6 | }, 7 | 'rules': { 8 | 'max-len': 'off', 9 | 'require-jsdoc': 'off', 10 | 'arrow-parens': 'off', 11 | 'comma-dangle': 'off', 12 | 'no-throw-literal': 'off', 13 | 'camelcase': 'off', 14 | 'prefer-rest-params': 'off', 15 | 'no-invalid-this': 'off', 16 | 'eol-last': 'off', 17 | }, 18 | }; 19 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | # Please read first! 2 | Please use [discuss-webrtc](https://groups.google.com/forum/#!forum/discuss-webrtc) for general technical discussions and questions. 3 | 4 | - [ ] I have provided steps to reproduce 5 | - [ ] I have provided browser name and version 6 | - [ ] I have provided a link to the sample here or a modified version thereof 7 | 8 | **Note: If the checkboxes above are not checked (which you do after the issue is posted), the issue will be closed.** 9 | 10 | ## Browser affected 11 | 12 | **Browser name including version (e.g. Chrome 64.0.3282.119)** 13 | 14 | 15 | ## Description 16 | 17 | 18 | ## Steps to reproduce 19 | 20 | 21 | ## Expected results 22 | 23 | 24 | ## Actual results 25 | 26 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | **Description** 2 | 3 | 4 | **Purpose** 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | browsers* 2 | .eslintcache 3 | firefox-*.tar.bz2 4 | node_modules 5 | .DS_Store 6 | validation-report.json 7 | validation-status.json 8 | .idea 9 | firefox_profile/* 10 | tests_output 11 | *.log -------------------------------------------------------------------------------- /.stylelintrc: -------------------------------------------------------------------------------- 1 | { 2 | "extends": "stylelint-config-recommended" 3 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | dist: trusty 2 | sudo: required 3 | language: node_js 4 | cache: 5 | - node_modules 6 | node_js: 7 | - lts/* 8 | jdk: oraclejdk8 9 | 10 | #before_script: 11 | # - sudo safaridriver --enable 12 | # - defaults write com.apple.Safari IncludeDevelopMenu YES 13 | # - defaults write com.apple.Safari AllowRemoteAutomation 1 14 | # - defaults write com.apple.Safari LocalFileRestrictionsEnabled 0 15 | # - defaults write com.apple.Safari WebKit2ICECandidateFilteringEnabled 0 16 | # - defaults write com.apple.Safari WebKit2MockCaptureDevicesEnabled 1 17 | # - defaults write com.apple.Safari WebKit2MediaCaptureRequiresSecureConnection 0 18 | 19 | branches: 20 | only: 21 | - gh-pages 22 | 23 | script: 24 | - npm test 25 | 26 | matrix: 27 | include: 28 | - name: "Chrome Stable" 29 | env: BROWSER=chrome 30 | addons: 31 | chrome: stable 32 | - name: "Firefox Stable" 33 | env: BROWSER=firefox 34 | addons: 35 | firefox: latest 36 | allow_failures: 37 | - name: "Chrome Beta" 38 | env: BROWSER=chrome 39 | addons: 40 | chrome: beta 41 | - name: "Firefox Beta" 42 | env: BROWSER=firefox 43 | addons: 44 | firefox: latest-beta 45 | # - name: "Safari" 46 | # env: BROWSER=safari 47 | # - name: "Firefox ESR" 48 | # env: BROWSER=firefox 49 | # addons: 50 | # firefox: latest-esr 51 | 52 | notifications: 53 | email: 54 | recipients: 55 | forward-webrtc-github@webrtc.org 56 | on_success: change 57 | on_failure: always 58 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | The WebRTC Project Authors 2 | The Chromium Authors 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # WebRTC welcomes patches/pulls for features and bug fixes! 2 | 3 | For contributors external to Google, follow the instructions given in the 4 | [Google Individual Contributor License Agreement](https://cla.developers.google.com/about/google-individual). 5 | In all cases, contributors must sign a contributor license agreement before a contribution can be accepted. 6 | Please complete the agreement for an [individual](https://developers.google.com/open-source/cla/individual) or 7 | a [corporation](https://developers.google.com/open-source/cla/corporate) as appropriate. 8 | 9 | If you plan to add a new sample or make significant changes to an existing sample, we recommend that you start by creating 10 | a [new issue](https://github.com/webrtc/samples/issues/new) where we can discuss the details. 11 | 12 | When creating a new sample or updating an existing one, please make sure you also create, or update any existing, tests. 13 | All tests in this repository are implemented as Nightwatch.JS UI tests, so please follow the same design in your own. 14 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014, The WebRTC project authors. All rights reserved. 2 | 3 | Redistribution and use in source and binary forms, with or without 4 | modification, are permitted provided that the following conditions are 5 | met: 6 | 7 | * Redistributions of source code must retain the above copyright 8 | notice, this list of conditions and the following disclaimer. 9 | 10 | * Redistributions in binary form must reproduce the above copyright 11 | notice, this list of conditions and the following disclaimer in 12 | the documentation and/or other materials provided with the 13 | distribution. 14 | 15 | * Neither the name of Google nor the names of its contributors may 16 | be used to endorse or promote products derived from this software 17 | without specific prior written permission. 18 | 19 | THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20 | "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22 | A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23 | HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24 | SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25 | LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29 | OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | [![Build Status](https://travis-ci.org/webrtc/samples.svg?branch=gh-pages)](https://travis-ci.org/webrtc/samples/) 2 | 3 | # WebRTC code samples 4 | 5 | This is a repository for the WebRTC JavaScript code samples. All of the samples can be tested from [webrtc.github.io/samples](https://webrtc.github.io/samples). 6 | 7 | We welcome contributions and bugfixes. Please see [CONTRIBUTING.md](https://github.com/webrtc/samples/blob/gh-pages/CONTRIBUTING.md) for details. 8 | 9 | ## Testing 10 | 11 | Some of the samples have an associated test. These are currently using [Nightwatch.JS](https://nightwatchjs.org) and 12 | are only testing the UI of the samples. The purpose of these is to provide examples of how you can write UI tests for 13 | your WebRTC web application. 14 | 15 | ## Bugs 16 | 17 | If you encounter a bug or problem with one of the samples, please submit a 18 | [new issue](https://github.com/webrtc/samples/issues/new) so we know about it and can fix it. 19 | 20 | Please avoid submitting issues on this repository for general problems you have with WebRTC. If you have found a bug in 21 | the WebRTC APIs, please see [webrtc.org/bugs](https://webrtc.org/bugs) for how to submit bugs on the affected browsers. 22 | If you need support on how to implement your own WebRTC-based application, please see the 23 | [discuss-webrtc](https://groups.google.com/forum/#!forum/discuss-webrtc) Google Group. 24 | 25 | -------------------------------------------------------------------------------- /google1b7eb21c5b594ba0.html: -------------------------------------------------------------------------------- 1 | google-site-verification: google1b7eb21c5b594ba0.html -------------------------------------------------------------------------------- /gulpfile.babel.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | import gulp from 'gulp'; 4 | import eslint from 'gulp-eslint'; 5 | import zip from 'gulp-zip'; 6 | import gulpStylelint from 'gulp-stylelint'; 7 | import nightwatch from 'gulp-nightwatch'; 8 | 9 | gulp.task('zip', function() { 10 | return gulp.src('src/content/extensions/desktopcapture/extension/**') 11 | .pipe(zip('desktopCaptureExtension.zip')) 12 | .pipe(gulp.dest('release')); 13 | }); 14 | 15 | gulp.task('eslint', function() { 16 | return gulp.src(['src/content/**/*.js', 'test/*.js', '!**/third_party/*.js']) 17 | .pipe(eslint()) 18 | .pipe(eslint.format()) 19 | .pipe(eslint.failAfterError()); 20 | }); 21 | 22 | 23 | gulp.task('stylelint', function() { 24 | return gulp.src('src/**/*.css') 25 | .pipe(gulpStylelint({ 26 | reporters: [ 27 | {formatter: 'string', console: true} 28 | ] 29 | })); 30 | }); 31 | 32 | gulp.task('nightwatch', function() { 33 | const browser = process.env.BROWSER || 'chrome'; 34 | return gulp.src('gulpfile.babel.js') 35 | .pipe(nightwatch({ 36 | configFile: 'nightwatch.conf.js', 37 | cliArgs: [`--env ${browser}`] 38 | })); 39 | }); 40 | 41 | 42 | gulp.task('default', gulp.series('eslint', 'stylelint', 'nightwatch')); -------------------------------------------------------------------------------- /nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-core/register') 2 | 3 | module.exports = require('./nightwatch.json') 4 | -------------------------------------------------------------------------------- /nightwatch.json: -------------------------------------------------------------------------------- 1 | { 2 | "src_folders": [ 3 | "src/content/getusermedia/gum/test", 4 | "src/content/getusermedia/resolution/test", 5 | "src/content/devices/input-output/test", 6 | "src/content/datachannel/filetransfer/test", 7 | "src/content/datachannel/datatransfer/test", 8 | "src/content/datachannel/basic/test", 9 | "src/content/peerconnection/audio/test" 10 | ], 11 | "output_folder": false, 12 | "custom_commands_path": [ 13 | "nightwatch/customCommands" 14 | ], 15 | "custom_assertions_path": [ 16 | "nightwatch/customAsserts" 17 | ], 18 | "page_objects_path": "", 19 | "selenium": { 20 | "start_process": true, 21 | "server_path": "./node_modules/selenium-server/lib/runner/selenium-server-standalone-3.14.0.jar", 22 | "port": 4444, 23 | "log_path": "", 24 | "cli_args": { 25 | "webdriver.firefox.profile": "./node_modules/.bin/geckodriver", 26 | "webdriver.chrome.driver":"./node_modules/.bin/chromedriver" 27 | } 28 | }, 29 | "test_settings": { 30 | "default": { 31 | "screenshots": { 32 | "enabled": false 33 | } 34 | }, 35 | "chrome": { 36 | "selenium_port": 4444, 37 | "selenium_host": "localhost", 38 | "desiredCapabilities": { 39 | "browserName": "chrome", 40 | "javascriptEnabled": true, 41 | "acceptSslCerts": true, 42 | "chromeOptions": { 43 | "args": [ 44 | "--headless", 45 | "--no-sandbox", 46 | "--allow-file-access-from-files", 47 | "--use-fake-device-for-media-stream", 48 | "--use-fake-ui-for-media-stream", 49 | "--disable-translate", 50 | "--no-process-singleton-dialog", 51 | "--mute-audio" 52 | ] 53 | } 54 | } 55 | }, 56 | "firefox": { 57 | "selenium_port": 4444, 58 | "selenium_host": "localhost", 59 | "desiredCapabilities": { 60 | "browserName": "firefox", 61 | "javascriptEnabled": true, 62 | "acceptSslCerts": true, 63 | "marionette": true, 64 | "moz:firefoxOptions": { 65 | "log": { 66 | "level": "trace" 67 | }, 68 | "args": [ 69 | "-headless", 70 | "-no-remote" 71 | ], 72 | "prefs": { 73 | "browser.cache.disk.enable": false, 74 | "browser.cache.disk.capacity": 0, 75 | "browser.cache.disk.smart_size.enabled": false, 76 | "browser.cache.disk.smart_size.first_run": false, 77 | "browser.sessionstore.resume_from_crash": false, 78 | "browser.startup.page": 0, 79 | "media.navigator.streams.fake": true, 80 | "media.navigator.permission.disabled": true, 81 | "device.storage.enabled": false, 82 | "media.gstreamer.enabled": false, 83 | "browser.startup.homepage": "about:blank", 84 | "browser.startup.firstrunSkipsHomepage": false, 85 | "extensions.update.enabled": false, 86 | "app.update.enabled": false, 87 | "network.http.use-cache": false, 88 | "browser.shell.checkDefaultBrowser": false 89 | } 90 | } 91 | } 92 | } 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /nightwatch/customAsserts/videoHeight.js: -------------------------------------------------------------------------------- 1 | exports.assertion = function(selector, videoHeight, msg) { 2 | this.message = msg || `Testing if element <${selector}> has videoHeight ${videoHeight}`; 3 | this.expected = videoHeight; 4 | 5 | this.pass = value => value === videoHeight; 6 | 7 | this.value = result => result.value; 8 | 9 | this.command = function(callback) { 10 | this.api.execute(function(selector) { 11 | const element = document.querySelector(selector); 12 | return element.videoHeight; 13 | }, [selector], callback); 14 | }; 15 | }; 16 | -------------------------------------------------------------------------------- /nightwatch/customAsserts/videoWidth.js: -------------------------------------------------------------------------------- 1 | exports.assertion = function(selector, videoWidth, msg) { 2 | this.message = msg || `Testing if element <${selector}> has videoWidth ${videoWidth}`; 3 | this.expected = videoWidth; 4 | 5 | this.pass = value => value === videoWidth; 6 | 7 | this.value = result => result.value; 8 | 9 | this.command = function(callback) { 10 | this.api.execute(function(selector) { 11 | const element = document.querySelector(selector); 12 | return element.videoWidth; 13 | }, [selector], callback); 14 | }; 15 | }; 16 | -------------------------------------------------------------------------------- /nightwatch/customCommands/waitForMediaPlaybackReady.js: -------------------------------------------------------------------------------- 1 | import EventEmitter from 'events'; 2 | import assert from 'assert'; 3 | 4 | class MediaPlaybackReady extends EventEmitter { 5 | constructor() { 6 | super(); 7 | } 8 | 9 | command(selector, timeout, message) { 10 | this.startTime = new Date().getTime(); 11 | const self = this; 12 | 13 | const executeArgs = [selector]; 14 | const checkFunction = (selector, cb) => { 15 | console.error('checkFunction'); 16 | const element = document.querySelector(selector); 17 | // readyState === 4 means that video/audio is ready to play 18 | cb(element.readyState); 19 | }; 20 | const callback = result => { 21 | const now = new Date().getTime(); 22 | if (result.value === 4) { 23 | const msg = message || `Media element ${selector} started playing in ${now - self.startTime} ms`; 24 | self.emit('done'); 25 | } else if (now - self.startTime < timeout) { 26 | this.api.executeAsync(checkFunction, executeArgs, callback); 27 | } else { 28 | const failMsg = message || `Media element ${selector} failed to start in ${now - self.startTime} ms`; 29 | assert.equal(result.value, 4, failMsg); 30 | self.emit('done'); 31 | } 32 | }; 33 | this.api.executeAsync(checkFunction, executeArgs, callback); 34 | 35 | return this; 36 | } 37 | } 38 | 39 | export default MediaPlaybackReady; 40 | -------------------------------------------------------------------------------- /nightwatch/customCommands/waitForReadyState.js: -------------------------------------------------------------------------------- 1 | import EventEmitter from 'events'; 2 | import assert from 'assert'; 3 | 4 | class WaitForReadyState extends EventEmitter { 5 | constructor() { 6 | super(); 7 | } 8 | 9 | command(selector, readyState, timeout, message) { 10 | this.readyState = readyState; 11 | this.startTime = new Date().getTime(); 12 | const self = this; 13 | 14 | const executeArgs = [selector]; 15 | const checkFunction = (selector, cb) => { 16 | const element = document.querySelector(selector); 17 | cb(element.readyState); 18 | }; 19 | const callback = result => { 20 | const now = new Date().getTime(); 21 | if (result.value === this.readyState) { 22 | const msg = message || `Ready state for ${selector} become ${this.readyState} in ${now - self.startTime} ms`; 23 | self.emit('done'); 24 | } else if (now - self.startTime < timeout) { 25 | this.api.executeAsync(checkFunction, executeArgs, callback); 26 | } else { 27 | const failMsg = message || `Ready state for ${selector} didn't become ${this.readyState} in ${now - self.startTime} ms`; 28 | assert.equal(result.value, this.readyState, failMsg); 29 | self.emit('done'); 30 | } 31 | }; 32 | this.api.executeAsync(checkFunction, executeArgs, callback); 33 | 34 | return this; 35 | } 36 | } 37 | 38 | export default WaitForReadyState; 39 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "webrtc-samples", 3 | "version": "1.0.0", 4 | "description": "Project checking for WebRTC GitHub samples repo", 5 | "keywords": [ 6 | "webrtc", 7 | "demos", 8 | "samples", 9 | "javascript" 10 | ], 11 | "homepage": "https://github.com/webrtc/samples", 12 | "bugs": { 13 | "url": "https://github.com/webrtc/samples/issues" 14 | }, 15 | "license": "BSD-3-Clause", 16 | "author": "The WebRTC project authors", 17 | "repository": { 18 | "type": "git", 19 | "url": "https://github.com/webrtc/samples.git" 20 | }, 21 | "scripts": { 22 | "test": "gulp" 23 | }, 24 | "devDependencies": { 25 | "babel-core": "^6.26.3", 26 | "babel-plugin-add-module-exports": "^0.2.1", 27 | "babel-preset-env": "^1.7.0", 28 | "babel-register": "^6.26.0", 29 | "chromedriver": "^2.41.0", 30 | "eslint-config-google": "^0.9.1", 31 | "express": "^4.14.1", 32 | "fs": "0.0.1-security", 33 | "geckodriver": "^1.12.2", 34 | "gulp": "^4.0.0", 35 | "gulp-babel": "^7.0.1", 36 | "gulp-eslint": "^5.0.0", 37 | "gulp-exec": "^3.0.2", 38 | "gulp-nightwatch": "^1.0.1", 39 | "gulp-stylelint": "^7.0.0", 40 | "gulp-zip": "^4.2.0", 41 | "lodash": "^4.17.10", 42 | "minimatch": "^3.0.4", 43 | "nightwatch": "^1.0.10", 44 | "pem": "^1.9.4", 45 | "selenium-server": "^3.14.0", 46 | "stylelint": "^9.4.0", 47 | "stylelint-config-recommended": "^2.1.0" 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /release/ChromeWebRTCNetworkLimiterExtension_0.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/release/ChromeWebRTCNetworkLimiterExtension_0.1.zip -------------------------------------------------------------------------------- /release/ChromeWebRTCNetworkLimiterExtension_0.2.1.1.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/release/ChromeWebRTCNetworkLimiterExtension_0.2.1.1.zip -------------------------------------------------------------------------------- /release/desktopCaptureExtension.zip: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/release/desktopCaptureExtension.zip -------------------------------------------------------------------------------- /src/content/capture/canvas-pc/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | canvas { 10 | background-color: #ccc; 11 | --width: calc(45%); 12 | width: var(--width); 13 | height: calc(var(--width) * 0.75); 14 | margin: 1em; 15 | vertical-align: top; 16 | } 17 | 18 | video { 19 | --width: calc(45%); 20 | width: var(--width); 21 | height: calc(var(--width) * 0.75); 22 | margin: 1em; 23 | object-fit: cover; 24 | } 25 | -------------------------------------------------------------------------------- /src/content/capture/canvas-pc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Canvas to peer connection 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

37 | WebRTC samples Stream from canvas to peer connection 38 |

39 | 40 | 41 | 42 | 43 |

Click and drag on the canvas element (on the left) to move the teapot.

44 | 45 |

This demo requires Firefox 47 or Chrome 52 (or later).

46 | 47 |

The teapot is drawn on the canvas element using WebGL. A stream is captured from the canvas using its captureStream() 48 | method and streamed via a peer connection to the video element on the right.

49 | 50 |

View the browser console to see logging.

51 | 52 |

Several variables are in global scope, so you can inspect them from the console: canvas, 53 | video, localPeerConnection, remotePeerConnection and stream. 54 |

55 | 56 |

For more demos and information about captureStream(), see Media Capture from Canvas Implementation.

59 | 60 |

For more information about RTCPeerConnection, see Getting 62 | Started With WebRTC.

63 | 64 | View source on GitHub 66 | 67 |
68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | -------------------------------------------------------------------------------- /src/content/capture/canvas-record/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 3px 10px 0; 10 | padding-left: 2px; 11 | padding-right: 2px; 12 | width: 99px; 13 | } 14 | 15 | button:last-of-type { 16 | margin: 0; 17 | } 18 | 19 | p.borderBelow { 20 | margin: 0 0 20px 0; 21 | padding: 0 0 20px 0; 22 | } 23 | 24 | canvas { 25 | background-color: #ccc; 26 | --width: calc(45%); 27 | width: var(--width); 28 | height: calc(var(--width) * 0.75); 29 | margin: 1em; 30 | vertical-align: top; 31 | } 32 | 33 | video { 34 | --width: calc(45%); 35 | width: var(--width); 36 | height: calc(var(--width) * 0.75); 37 | margin: 1em; 38 | object-fit: cover; 39 | } 40 | 41 | -------------------------------------------------------------------------------- /src/content/capture/canvas-video/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | canvas { 10 | background-color: #ccc; 11 | --width: calc(45%); 12 | width: var(--width); 13 | height: calc(var(--width) * 0.75); 14 | margin: 1em; 15 | vertical-align: top; 16 | } 17 | 18 | video { 19 | --width: calc(45%); 20 | width: var(--width); 21 | height: calc(var(--width) * 0.75); 22 | margin: 1em; 23 | object-fit: cover; 24 | } 25 | -------------------------------------------------------------------------------- /src/content/capture/canvas-video/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Canvas to video 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

WebRTC samples Stream from canvas to video element 37 |

38 | 39 | 40 | 41 | 42 | 43 |

Click and drag on the canvas (on the left) to move the teapot.

44 | 45 |

This demo requires Firefox 47 or Chrome 52 (or later).

46 | 47 |

The teapot is drawn on the canvas element using WebGL. A stream is captured from the canvas element using its 48 | captureStream() method and set as the srcObject of the video element.

49 | 50 |

The canvas, video, and stream variables are in global scope, so you can 51 | inspect them from the browser console.

52 | 53 |

For more demos and information about captureStream(), see Media Capture from Canvas Implementation.

56 | 57 | View source on GitHub 59 | 60 |
61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | -------------------------------------------------------------------------------- /src/content/capture/canvas-video/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | /* global main */ 10 | 11 | 'use strict'; 12 | 13 | // Call main() in demo.js 14 | main(); 15 | 16 | const canvas = document.querySelector('canvas'); 17 | const video = document.querySelector('video'); 18 | 19 | const stream = canvas.captureStream(); 20 | video.srcObject = stream; 21 | -------------------------------------------------------------------------------- /src/content/capture/video-contenthint/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | video { 10 | --width: calc(45%); 11 | width: var(--width); 12 | height: calc(var(--width) * 9 / 16); 13 | margin: 1em; 14 | object-fit: cover; 15 | } 16 | 17 | .video-container { 18 | border-bottom: 1px solid grey; 19 | font-style: italic; 20 | margin: 20px; 21 | } 22 | 23 | #videos { 24 | text-align: center; 25 | width: 100%; 26 | } 27 | -------------------------------------------------------------------------------- /src/content/capture/video-pc/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | video { 10 | margin: 0 10px 0 0; 11 | width: calc(50% - 7px); 12 | } 13 | 14 | video:last-of-type { 15 | margin-right: 0; 16 | } 17 | 18 | @media screen and (max-width: 400px) { 19 | video { 20 | margin: 0 5px 20px 0; 21 | width: calc(50% - 5px); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/content/capture/video-pc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Video to peer connection 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

WebRTC samples Stream from a video to a peer connection 37 |

38 | 39 | 45 | 46 | 47 | 48 |

This demo requires Firefox 47, Chrome 53 with Experimental Web Platform features enabled from 49 | chrome://flags.

50 | 51 |

A stream is captured from the video on the left using the captureStream() method, and streamed via a 52 | peer connection to the video element on the right.

53 | 54 |

View the browser console to see logging.

55 | 56 |

Several variables are in global scope, so you can inspect them from the console: localPeerConnection, 57 | remotePeerConnection and stream.

58 | 59 |

For more information about RTCPeerConnection, see Getting 61 | Started With WebRTC.

62 | 63 | View source on GitHub 65 | 66 |
67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/content/capture/video-video/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | video { 10 | margin: 0 10px 0 0; 11 | width: calc(50% - 7px); 12 | } 13 | 14 | video:last-of-type { 15 | margin-right: 0; 16 | } 17 | 18 | @media screen and (max-width: 400px) { 19 | video { 20 | margin: 0 5px 20px 0; 21 | width: calc(50% - 5px); 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/content/capture/video-video/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | captureStream(): video to video 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

WebRTC samples captureStream(): video to video 37 |

38 | 39 | 44 | 45 | 46 | 47 |

Press play on the left video to start the demo.

48 | 49 |

A stream is captured from the video element on the left using its captureStream() method and set as 50 | the srcObject of the video element on the right.

51 | 52 |

The stream variable are in global scope, so you can inspect them from the browser console.

53 | 54 | View source on GitHub 56 | 57 |
58 | 59 | 60 | 61 | 62 | 63 | 64 | -------------------------------------------------------------------------------- /src/content/capture/video-video/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 'use strict'; 9 | 10 | const leftVideo = document.getElementById('leftVideo'); 11 | const rightVideo = document.getElementById('rightVideo'); 12 | 13 | leftVideo.addEventListener('canplay', () => { 14 | const stream = leftVideo.captureStream(); 15 | rightVideo.srcObject = stream; 16 | }); 17 | -------------------------------------------------------------------------------- /src/content/datachannel/basic/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 1em 1em 0; 10 | width: 90px; 11 | } 12 | div#buttons { 13 | margin: 0 0 1em 0; 14 | } 15 | div#send { 16 | margin: 0 20px 1em 0; 17 | } 18 | div#sendReceive { 19 | border-bottom: 1px solid #eee; 20 | margin: 0; 21 | padding: 0 0 10px 0; 22 | } 23 | div#sendReceive > div { 24 | display: inline-block; 25 | width: calc(50% - 20px); 26 | } 27 | form { 28 | margin: 0 0 1em 0; 29 | white-space: nowrap; 30 | } 31 | form span { 32 | font-weight: 300; 33 | margin: 0 1em 0 0; 34 | white-space: normal; 35 | } 36 | textarea { 37 | color: #444; 38 | font-size: 0.9em; 39 | font-weight: 300; 40 | height: 7.0em; 41 | padding: 5px; 42 | width: calc(100% - 10px); 43 | } 44 | -------------------------------------------------------------------------------- /src/content/datachannel/basic/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Transmit text 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

WebRTC samples 37 | Transmit text

38 | 39 |
40 | 41 | 42 | 43 |
44 | 45 |
46 |
47 |

Send

48 | 50 |
51 |
52 |

Receive

53 | 54 |
55 |
56 | 57 |

View the console to see logging.

58 | 59 |

The RTCPeerConnection objects localConnection and remoteConnection are in 60 | global scope, so you can inspect them in the console as well.

61 | 62 |

For more information about RTCDataChannel, see Getting Started With WebRTC.

65 | 66 | View source on GitHub 68 |
69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | -------------------------------------------------------------------------------- /src/content/datachannel/basic/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | export default { 9 | 'It should transfer text over data channel': (browser) => { 10 | const path = '/src/content/datachannel/basic/index.html'; 11 | const url = 'file://' + process.cwd() + path; 12 | 13 | // Disable this until https://github.com/webrtc/samples/pull/1110 is merged 14 | if (browser.options.desiredCapabilities.browserName === 'safari') { 15 | browser.end(); 16 | return; 17 | } 18 | 19 | browser 20 | .url(url) 21 | .click('#startButton') 22 | .expect.element('#sendButton').to.be.enabled.before(50); 23 | browser.expect.element('#dataChannelSend').to.be.enabled.before(50); 24 | 25 | browser.setValue('#dataChannelSend', 'HELLO, WORLD!'); 26 | browser 27 | .click('#sendButton') 28 | .pause(50) 29 | .assert.value('#dataChannelReceive', 'HELLO, WORLD!'); 30 | 31 | browser 32 | .click('#closeButton') 33 | .expect.element('#sendButton').to.not.be.enabled.before(50); 34 | 35 | browser.end(); 36 | } 37 | }; -------------------------------------------------------------------------------- /src/content/datachannel/datatransfer/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | div.progress { 9 | margin: 0 0 1em 0; 10 | } 11 | 12 | div.progress div.label { 13 | display: inline-block; 14 | font-weight: 400; 15 | width: 8.2em; 16 | } 17 | 18 | div.input { 19 | margin: 0 0 1em 0; 20 | } 21 | 22 | progress { 23 | width: calc(100% - 8.5em); 24 | } 25 | -------------------------------------------------------------------------------- /src/content/datachannel/datatransfer/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | export default { 9 | 'It should transfer data over data channel': (browser) => { 10 | const path = '/src/content/datachannel/datatransfer/index.html'; 11 | const url = 'file://' + process.cwd() + path; 12 | 13 | // Disable this until https://github.com/webrtc/samples/pull/1110 is merged 14 | if (browser.options.desiredCapabilities.browserName === 'safari') { 15 | browser.end(); 16 | return; 17 | } 18 | 19 | browser.url(url).waitForElementVisible('#sendTheData'); 20 | browser.click('#sendTheData'); 21 | browser.expect.element('#transferStatus').text.to.equal('Data transfer completed successfully!'); 22 | browser.end(); 23 | } 24 | }; 25 | -------------------------------------------------------------------------------- /src/content/datachannel/filetransfer/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | div.progress, div#bitrate { 9 | margin: 0 0 1em 0; 10 | } 11 | 12 | div.progress div.label { 13 | display: inline-block; 14 | font-weight: 400; 15 | width: 8.2em; 16 | } 17 | 18 | form { 19 | margin: 0 0 1em 0; 20 | white-space: nowrap; 21 | } 22 | 23 | progress { 24 | width: calc(100% - 8.5em); 25 | } 26 | -------------------------------------------------------------------------------- /src/content/datachannel/filetransfer/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | export default { 10 | 'It should transfer a file over a datachannel': (browser) => { 11 | const path = '/src/content/datachannel/filetransfer/index.html'; 12 | const url = 'file://' + process.cwd() + path; 13 | 14 | // Disable this until https://github.com/webrtc/samples/pull/1110 is merged 15 | if (browser.options.desiredCapabilities.browserName === 'safari') { 16 | browser.end(); 17 | return; 18 | } 19 | 20 | browser.url(url).waitForElementVisible('#fileInput', 1000); 21 | browser.waitForElementNotVisible('#download', 100, 'File download link is not visible'); 22 | browser.expect.element('#sendFile').to.not.be.enabled.before(1000); 23 | browser.setValue('#fileInput', process.cwd() + '/src/content/devices/multi/images/poster.jpg'); 24 | browser.expect.element('#sendFile').to.be.enabled.before(1000); 25 | browser.click('#sendFile'); 26 | browser.waitForElementVisible('#download', 10000, 'File download link is visible'); 27 | browser.end(); 28 | } 29 | }; -------------------------------------------------------------------------------- /src/content/datachannel/messaging/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Send messages with datachannel 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 |
39 | 40 |

WebRTC samples Send messages with datachannel 41 |

42 |
43 | 44 |

This page show how to send text messages via WebRTC datachannels.

45 | 46 |

Enter a message in one text box and press send and it will be transferred to the "remote" peer over a 47 | datachannel.

48 | 49 |
50 | 51 | 52 | 53 |
54 |

View the console to see logging.

55 | 56 |

For more information about RTCDataChannel, see Getting Started With WebRTC.

59 |
60 | 61 | View source on GitHub 63 |
64 | 65 | 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /src/content/datachannel/messaging/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | div.messageBox { 9 | width: 100%; 10 | } 11 | 12 | textarea.message { 13 | width: 100%; 14 | height: 5em; 15 | resize: none; 16 | display: block; 17 | box-sizing: border-box; 18 | margin: 1em; 19 | } 20 | 21 | label { 22 | font-weight: 400; 23 | } 24 | 25 | -------------------------------------------------------------------------------- /src/content/devices/input-output/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Select audio and video sources 24 | 25 | 26 | 27 | 28 | 29 | 44 | 45 | 46 | 47 | 48 |
49 | 50 |

WebRTC samplesSelect sources & outputs 51 |

52 | 53 |

Get available audio, video sources and audio output devices from mediaDevices.enumerateDevices() 54 | then set the source for getUserMedia() using a deviceId constraint.

55 | 56 |
57 | 58 |
59 | 60 |
61 | 62 |
63 | 64 |
65 | 66 |
67 | 68 | 69 | 70 |

Note: If you hear a reverb sound your microphone is picking up the output of your 71 | speakers/headset, lower the volume and/or move the microphone further away from your speakers/headset.

72 | 73 | View source on GitHub 75 |
76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | -------------------------------------------------------------------------------- /src/content/devices/input-output/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | export default { 9 | 'It should have select elements for each media device': (browser) => { 10 | const path = '/src/content/devices/input-output/index.html'; 11 | const url = 'file://' + process.cwd() + path; 12 | 13 | // audio output is't supported on Safari or Firefox 14 | const browserName = browser.options.desiredCapabilities.browserName; 15 | if (browserName === 'firefox' || browserName === 'safari') { 16 | browser 17 | .url(url) 18 | .waitForElementVisible('#audioSource option:nth-of-type(1)', 1000, 'Check that there is at least one audio source') 19 | .waitForElementVisible('#videoSource option:nth-of-type(1)', 1000, 'Check that there is at least one video source') 20 | .end(); 21 | return; 22 | } 23 | 24 | browser 25 | .url(url) 26 | .waitForElementVisible('#audioSource option:nth-of-type(1)', 1000, 'Check that there is at least one audio source') 27 | .waitForElementVisible('#audioOutput option:nth-of-type(1)', 1000, 'Check that there is at least one audio output') 28 | .waitForElementVisible('#videoSource option:nth-of-type(1)', 1000, 'Check that there is at least one video source') 29 | .end(); 30 | } 31 | }; -------------------------------------------------------------------------------- /src/content/devices/multi/audio/audio.mp3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/content/devices/multi/audio/audio.mp3 -------------------------------------------------------------------------------- /src/content/devices/multi/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | audio { 10 | margin: 0 0 1.5em 0; 11 | width: 100%; 12 | } 13 | 14 | div#sources > div { 15 | float: left; 16 | margin: 0 1em 0 0; 17 | width: calc(50% - 0.5em); 18 | } 19 | 20 | div#sources > div:last-of-type { 21 | margin: 0; 22 | } 23 | 24 | select { 25 | margin: 0 0 0.5em 0; 26 | } 27 | 28 | video { 29 | background: black; 30 | height: 234px; 31 | } 32 | -------------------------------------------------------------------------------- /src/content/devices/multi/images/poster.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/content/devices/multi/images/poster.jpg -------------------------------------------------------------------------------- /src/content/devices/multi/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | getUserMedia: output device selection 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

WebRTC samples getUserMedia: output device selection 37 |

38 | 39 |
40 | 41 |
42 |

getUserMedia():

43 |
44 | 45 |
46 | 47 | 48 |
49 |
50 |
51 | 52 |
53 | 54 | 55 |
56 |
57 |
58 | 59 |
60 |

Local media files:

61 |
62 | 67 |
68 | 69 | 70 |
71 |
72 |
73 | 77 |
78 | 79 | 80 |
81 |
82 |
83 | 84 |
85 | 86 |

This demo must be run from localhost or over HTTPS Chrome 49 or later, Firefox is not supported yet.

87 |
88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | -------------------------------------------------------------------------------- /src/content/devices/multi/video/chrome.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/content/devices/multi/video/chrome.mp4 -------------------------------------------------------------------------------- /src/content/devices/multi/video/chrome.ogv: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/content/devices/multi/video/chrome.ogv -------------------------------------------------------------------------------- /src/content/devices/multi/video/chrome.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/content/devices/multi/video/chrome.webm -------------------------------------------------------------------------------- /src/content/extensions/desktopcapture/README.md: -------------------------------------------------------------------------------- 1 | ## WebRTC desktop capture 2 | This is a WebRTC desktop capture extension with a demo app. It uses the [chrome.desktopCapture](https://developer.chrome.com/extensions/desktopCapture) and [getUserMedia()](http://dev.w3.org/2011/webrtc/editor/archives/20140619/getusermedia.html) APIs. 3 | 4 | ###In order to try it out locally do following:### 5 | 1. Download the extension to your machine. 6 | 2. Browse to chrome://extensions 7 | 3. Click load unpacked extensions and select the downloaded extension from step 1. 8 | 4. The extension will now appear in the list, click start and select the desktop or a window. 9 | 10 | You are now capturing a window or your desktop. 11 | 12 | You can use this example to integrate with your own web app as well. Just make sure to serve your app over HTTPS and change the `content_scripts` and `permissions` URLs to match your webapp URL. 13 | 14 | ## Development 15 | If you update this extension you should run the `grunt compress` command which will create a zip file with this extension and put it in the release/ folder. This is to make it easier to download. 16 | -------------------------------------------------------------------------------- /src/content/extensions/desktopcapture/app.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const videoElement = document.getElementById('video'); 4 | 5 | let extensionInstalled = false; 6 | 7 | document.getElementById('start').addEventListener('click', function() { 8 | // send screen-sharer request to content-script 9 | if (!extensionInstalled) { 10 | let message = 'Please install the extension:\n' + 11 | '1. Go to chrome://extensions\n' + 12 | '2. Check: "Enable Developer mode"\n' + 13 | '3. Click: "Load the unpacked extension..."\n' + 14 | '4. Choose "extension" folder from the repository\n' + 15 | '5. Reload this page'; 16 | alert(message); 17 | } 18 | window.postMessage({type: 'SS_UI_REQUEST', text: 'start'}, '*'); 19 | }); 20 | 21 | // listen for messages from the content-script 22 | window.addEventListener('message', function(event) { 23 | if (event.origin !== window.location.origin) { 24 | return; 25 | } 26 | 27 | // content-script will send a 'SS_PING' msg if extension is installed 28 | if (event.data.type && (event.data.type === 'SS_PING')) { 29 | extensionInstalled = true; 30 | } 31 | 32 | // user chose a stream 33 | if (event.data.type && (event.data.type === 'SS_DIALOG_SUCCESS')) { 34 | startScreenStreamFrom(event.data.streamId); 35 | } 36 | 37 | // user clicked on 'cancel' in choose media dialog 38 | if (event.data.type && (event.data.type === 'SS_DIALOG_CANCEL')) { 39 | console.log('User cancelled!'); 40 | } 41 | }); 42 | 43 | function handleSuccess(screenStream) { 44 | videoElement.srcObject = screenStream; 45 | videoElement.play(); 46 | } 47 | 48 | function handleError(error) { 49 | console.log('getUserMedia() failed: ', error); 50 | } 51 | 52 | function startScreenStreamFrom(streamId) { 53 | let constraints = { 54 | audio: false, 55 | video: { 56 | mandatory: { 57 | chromeMediaSource: 'desktop', 58 | chromeMediaSourceId: streamId, 59 | maxWidth: window.screen.width, 60 | maxHeight: window.screen.height 61 | } 62 | } 63 | }; 64 | navigator.mediaDevices.getUserMedia(constraints). 65 | then(handleSuccess).catch(handleError); 66 | } 67 | -------------------------------------------------------------------------------- /src/content/extensions/desktopcapture/extension/background.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | const dataSources = ['screen', 'window']; 4 | let desktopMediaRequestId = ''; 5 | 6 | chrome.runtime.onConnect.addListener(function(port) { 7 | port.onMessage.addListener(function(msg) { 8 | if (msg.type === 'SS_UI_REQUEST') { 9 | requestScreenSharing(port, msg); 10 | } 11 | 12 | if (msg.type === 'SS_UI_CANCEL') { 13 | cancelScreenSharing(msg); 14 | } 15 | }); 16 | }); 17 | 18 | function requestScreenSharing(port, msg) { 19 | // https://developer.chrome.com/extensions/desktopCapture 20 | // params: 21 | // - 'dataSources' Set of sources that should be shown to the user. 22 | // - 'targetTab' Tab for which the stream is created. 23 | // - 'streamId' String that can be passed to getUserMedia() API 24 | desktopMediaRequestId = 25 | chrome.desktopCapture.chooseDesktopMedia(dataSources, port.sender.tab, 26 | function(streamId) { 27 | if (streamId) { 28 | msg.type = 'SS_DIALOG_SUCCESS'; 29 | msg.streamId = streamId; 30 | } else { 31 | msg.type = 'SS_DIALOG_CANCEL'; 32 | } 33 | port.postMessage(msg); 34 | }); 35 | } 36 | 37 | function cancelScreenSharing() { 38 | if (desktopMediaRequestId) { 39 | chrome.desktopCapture.cancelChooseDesktopMedia(desktopMediaRequestId); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /src/content/extensions/desktopcapture/extension/content-script.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // https://chromeextensionsdocs.appspot.com/ 4 | // apps/content_scripts#host-page-communication 5 | // - 'content_script' and execution env are isolated from each other 6 | // - In order to communicate we use the DOM (window.postMessage) 7 | // 8 | // app.js | |content-script.js | |background.js 9 | // window.postMessage|------->|port.postMessage |----->| port.onMessage 10 | // | window | | port | 11 | // webkitGetUserMedia|<------ |window.postMessage|<-----| port.postMessage 12 | // 13 | 14 | const port = chrome.runtime.connect(chrome.runtime.id); 15 | 16 | port.onMessage.addListener(function(msg) { 17 | window.postMessage(msg, '*'); 18 | }); 19 | 20 | window.addEventListener('message', function(event) { 21 | // We only accept messages from ourselves 22 | if (event.source !== window) { 23 | return; 24 | } 25 | 26 | if (event.data.type && ((event.data.type === 'SS_UI_REQUEST') || 27 | (event.data.type === 'SS_UI_CANCEL'))) { 28 | port.postMessage(event.data); 29 | } 30 | }, false); 31 | 32 | window.postMessage({ 33 | type: 'SS_PING', 34 | text: 'start' 35 | }, '*'); 36 | -------------------------------------------------------------------------------- /src/content/extensions/desktopcapture/extension/icon.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/content/extensions/desktopcapture/extension/icon.png -------------------------------------------------------------------------------- /src/content/extensions/desktopcapture/extension/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Screensharing Extension", 3 | "description": "Screensharing Extension for my app", 4 | "version": "1.0.0", 5 | "manifest_version": 2, 6 | "icons": { 7 | "128": "icon.png" 8 | }, 9 | "background": { 10 | "scripts": ["background.js"] 11 | }, 12 | "content_scripts": [ 13 | { 14 | "matches": ["https://webrtc.github.io/samples/*"], 15 | "js": ["content-script.js"] 16 | } 17 | ], 18 | "permissions": [ 19 | "desktopCapture", 20 | "https://webrtc.github.io/samples/*" 21 | ] 22 | } 23 | -------------------------------------------------------------------------------- /src/content/extensions/desktopcapture/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | Desktop capture 7 | 8 | 22 | 23 | 24 | 25 | 26 |

27 | 28 |

29 | 30 | 31 | 32 | -------------------------------------------------------------------------------- /src/content/extensions/multipleroutes/img/netli_1280.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/content/extensions/multipleroutes/img/netli_1280.png -------------------------------------------------------------------------------- /src/content/extensions/multipleroutes/src/README.md: -------------------------------------------------------------------------------- 1 | ## Chrome WebRTC Network Limiter 2 | Configures the WebRTC traffic routing options in Chrome's privacy settings. 3 | 4 | ★ What it does: 5 | This configures WebRTC to not use certain IP addresses or protocols: 6 | - private IP addresses not visible to the public internet (e.g. addresses like 192.168.1.2) 7 | - any public IP addresses associated with network interfaces that are not used for web traffic (e.g. an ISP-provided address, when browsing through a VPN) 8 | - Require WebRTC traffic to go through proxy servers as configured in Chrome. Since most of the proxy servers don't handle UDP, this effectively turns off UDP until UDP proxy support is available in Chrome and such proxies are widely deployed. 9 | 10 | When the extension is installed on Chrome versions prior to M48, WebRTC will only use the public IP address associated with the interface used for web traffic, typically the same addresses that are already provided to sites in browser HTTP requests. For Chrome version M48 and after, this extension provides one more configuration which allows WebRTC to use both the default public address and, for machines behind a NAT, the default private address which is associated with the public one. Said behavior will be the default after a fresh installation of the extension to Chrome M48. For upgrade scenarios, the previous selected configuration should not be changed. 11 | 12 | The extension may also disable non-proxied UDP, but this is not on by default and must be configured using the extension's Options page. 13 | 14 | ★ Notes: 15 | This extension may affect the performance of applications that use WebRTC for audio/video or real-time data communication. Because it limits the potential network paths and protocols, WebRTC may pick a path which results in significantly longer delay or lower quality (e.g. through a VPN) or use TCP only through proxy servers which is not ideal for real-time communication. We are attempting to determine how common this is. 16 | 17 | By installing this item, you agree to the Google Terms of Service and Privacy Policy at https://www.google.com/intl/en/policies/. 18 | 19 | -------------------------------------------------------------------------------- /src/content/extensions/multipleroutes/src/_locales/en/messages.json: -------------------------------------------------------------------------------- 1 | { 2 | "NETLI_DEFAULT_RADIO": { 3 | "message": "Give me the best media experience: This option allows Chrome to explore all network paths to find the best way to send and receive media, which may be different from normal web traffic." 4 | }, 5 | "NETLI_DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES_RADIO": { 6 | "message": "Use my default public and private IP addresses: This option forces Chrome to use the same network path for media as for normal web traffic, except when a web proxy is present. For machines behind a NAT, Chrome will also use the default private address to enhance connectivity. To prevent degraded performance, Chrome will attempt to send media directly instead of using the proxy." 7 | }, 8 | "NETLI_DEFAULT_PUBLIC_INTERFACE_ONLY_RADIO": { 9 | "message": "Use only my default public IP address: This option is the same as Use my default public and private IP addresses except that Chrome will not use the private default address." 10 | }, 11 | "NETLI_DISABLE_NON_PROXIED_UDP_RADIO": { 12 | "message": "Use my proxy server (if present): This option forces Chrome to use the same network path for media as for normal web traffic, including use of a web proxy. Chrome will always attempt to send media through the proxy, which will typically hurt media performance and increase the load on the proxy; furthermore, this behavior may be incompatible with some applications." 13 | }, 14 | "NETLI_OPTION_NOT_SUPPORTED": { 15 | "message": "Grayed out options require newer verion of Chrome." 16 | }, 17 | "NETLI_APPDESC": { 18 | "message": "Configures how WebRTC's network traffic is routed by changing Chrome's privacy settings." 19 | }, 20 | "NETLI_APPNAME": { 21 | "message": "WebRTC Network Limiter" 22 | }, 23 | "NETLI_OPTIONS": { 24 | "message": "WebRTC Network Limiter Options" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /src/content/extensions/multipleroutes/src/background.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/content/extensions/multipleroutes/src/eventPage.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | // This file sets the policy when the extension is installed and registered for 10 | // chrome.runtime.onInstalled event to convert the booleans in pre-M48 version 11 | // to IPHandlingPolicy when chrome is upgraded to M48. 12 | 13 | 'use strict'; 14 | 15 | // If this is installed in a pre-M48 version of Chrome, the only thing to do 16 | // here is to disable MultipleRoute. 17 | const pn = chrome.privacy.network; 18 | const pi = chrome.privacy.IPHandlingPolicy; 19 | 20 | if (!browserSupportsIPHandlingPolicy()) { 21 | pn.webRTCMultipleRoutesEnabled.set({ 22 | value: false 23 | }); 24 | } 25 | 26 | // This function resets the 2 booleans to default values so we can ignore them 27 | // as if they were not set in future chrome.runtime.onInstalled event. This is 28 | // to avoid repeated conversions and overwrite the current setting. 29 | function resetOldBooleans(callback) { 30 | pn.webRTCNonProxiedUdpEnabled.set({ 31 | value: true 32 | }, function() { 33 | pn.webRTCMultipleRoutesEnabled.set({ 34 | value: true 35 | }, function() { 36 | callback('Successfully reset the booleans'); 37 | }); 38 | }); 39 | } 40 | 41 | // Converts the old booleans to the new policy in Preferences and resets the 2 42 | // previous booleans to the default. Future chrome updates could trigger this 43 | // function again but they will either stop the conversion if 44 | // webRTCIPHandlingPolicy is not "default" or for the case of "default", since 45 | // the previous booleans have been reset to default, it'll be translate to 46 | // "default" again. 47 | function convertBooleansToPolicy(isInstall, callback) { 48 | if (!browserSupportsIPHandlingPolicy()) { 49 | return; 50 | } 51 | 52 | pn.webRTCIPHandlingPolicy.get({}, function(details) { 53 | if (details.value !== chrome.privacy.IPHandlingPolicy.DEFAULT) { 54 | if (callback) { 55 | callback( 56 | 'webRTCIPHandlingPolicy has a non-default value, stop now.' 57 | ); 58 | } 59 | return; 60 | } 61 | 62 | getPolicyFromBooleans(function(policy) { 63 | if (policy === pi.DEFAULT && isInstall) { 64 | // It's safe to use the enum value here since 65 | // browserSupportsIPHandlingPolicy must be true. 66 | policy = pi.DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES; 67 | } 68 | pn.webRTCIPHandlingPolicy.set({ 69 | value: policy 70 | }, resetOldBooleans(callback)); 71 | }); 72 | }); 73 | } 74 | 75 | function onInstall(details) { 76 | if (details.reason === 'install' /* extension is installed */ || 77 | details.reason === 'update' /* extension is upgraded */ || 78 | details.reason === 'chrome_update' /* chrome is upgraded */ ) { 79 | convertBooleansToPolicy( 80 | details.reason === 'install', 81 | function(status) { 82 | console.log(status); 83 | }); 84 | } 85 | } 86 | 87 | chrome.runtime.onInstalled.addListener(onInstall); 88 | -------------------------------------------------------------------------------- /src/content/extensions/multipleroutes/src/img/icon_128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/content/extensions/multipleroutes/src/img/icon_128.png -------------------------------------------------------------------------------- /src/content/extensions/multipleroutes/src/img/icon_16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/content/extensions/multipleroutes/src/img/icon_16.png -------------------------------------------------------------------------------- /src/content/extensions/multipleroutes/src/manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "background": { 3 | "page": "background.html", 4 | "persistent": false 5 | }, 6 | "default_locale": "en", 7 | "description": "__MSG_NETLI_APPDESC__", 8 | "icons": { 9 | "16": "img/icon_16.png", 10 | "128": "img/icon_128.png" 11 | }, 12 | "manifest_version": 2, 13 | "minimum_chrome_version": "42.0.2311.135", 14 | "name": "__MSG_NETLI_APPNAME__", 15 | "options_ui": { 16 | "chrome_style": true, 17 | "page": "options.html" 18 | }, 19 | "permissions": [ "privacy" ], 20 | "version": "0.2.1.3" 21 | } 22 | -------------------------------------------------------------------------------- /src/content/extensions/multipleroutes/src/options.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 |

12 | 13 | 16 |

17 |

18 | 21 | 24 |

25 |

26 | 29 | 32 |

33 |

34 | 36 | 39 |

40 |

41 | 44 |

45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /src/content/extensions/multipleroutes/src/utils.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | /* exported getPolicyFromBooleans */ 10 | 11 | 'use strict'; 12 | 13 | const pn = chrome.privacy.network; 14 | let pi = null; 15 | 16 | function browserSupportsIPHandlingPolicy() { 17 | return pn.webRTCIPHandlingPolicy !== undefined; 18 | } 19 | 20 | function browserSupportsNonProxiedUdpBoolean() { 21 | return pn.webRTCNonProxiedUdpEnabled !== undefined; 22 | } 23 | 24 | // Handle the case when this is installed in pre-M48. 25 | if (!browserSupportsIPHandlingPolicy()) { 26 | chrome.privacy.IPHandlingPolicy = {}; 27 | chrome.privacy.IPHandlingPolicy.DEFAULT = 0; 28 | chrome.privacy.IPHandlingPolicy.DEFAULT_PUBLIC_AND_PRIVATE_INTERFACES = 1; 29 | chrome.privacy.IPHandlingPolicy.DEFAULT_PUBLIC_INTERFACE_ONLY = 2; 30 | chrome.privacy.IPHandlingPolicy.DISABLE_NON_PROXIED_UDP = 3; 31 | } 32 | 33 | pi = chrome.privacy.IPHandlingPolicy; 34 | 35 | // Helper function to convert the parameters to policy synchronously. 36 | function convertToPolicy(allowMultiRoute, allowUdp) { 37 | if (!allowUdp) { 38 | return pi.DISABLE_NON_PROXIED_UDP; 39 | } 40 | 41 | if (!allowMultiRoute) { 42 | return pi.DEFAULT_PUBLIC_INTERFACE_ONLY; 43 | } 44 | 45 | return pi.DEFAULT; 46 | } 47 | 48 | // This function just returns the new policy value based on the 2 booleans 49 | // without changing any preferences. 50 | // eslint-disable-next-line no-unused-vars 51 | function getPolicyFromBooleans(callback) { 52 | pn.webRTCMultipleRoutesEnabled.get({}, function(allowMultiRoute) { 53 | if (!browserSupportsNonProxiedUdpBoolean()) { 54 | callback(convertToPolicy(allowMultiRoute.value, true)); 55 | } else { 56 | pn.webRTCNonProxiedUdpEnabled.get({}, function(allowUdp) { 57 | callback(convertToPolicy(allowMultiRoute.value, allowUdp.value)); 58 | }); 59 | } 60 | }); 61 | } 62 | -------------------------------------------------------------------------------- /src/content/getusermedia/audio/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | gUM audio 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 | 35 |

WebRTC samples getUserMedia, audio only 36 |

37 | 38 | 39 | 40 |

Warning: if you're not using headphones, pressing play will cause feedback.

41 | 42 |

Render the audio stream from an audio-only getUserMedia() call with an audio element.

43 | 44 |

The MediaStream object stream passed to the getUserMedia() 45 | callback is in global scope, so you can inspect it from the console.

46 | 47 | View source on GitHub 49 | 50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | -------------------------------------------------------------------------------- /src/content/getusermedia/audio/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | // Put variables in global scope to make them available to the browser console. 12 | const audio = document.querySelector('audio'); 13 | 14 | const constraints = window.constraints = { 15 | audio: true, 16 | video: false 17 | }; 18 | 19 | function handleSuccess(stream) { 20 | const audioTracks = stream.getAudioTracks(); 21 | console.log('Got stream with constraints:', constraints); 22 | console.log('Using audio device: ' + audioTracks[0].label); 23 | stream.oninactive = function() { 24 | console.log('Stream ended'); 25 | }; 26 | window.stream = stream; // make variable available to browser console 27 | audio.srcObject = stream; 28 | } 29 | 30 | function handleError(error) { 31 | console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name); 32 | } 33 | 34 | navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError); 35 | 36 | -------------------------------------------------------------------------------- /src/content/getusermedia/canvas/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | getUserMedia to canvas 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 | 35 |

WebRTC samples getUserMedia ⇒ canvas 36 |

37 | 38 | 39 | 40 | 41 | 42 |

Draw a frame from the video onto the canvas element using the drawImage() method.

43 | 44 |

The variables canvas, video and stream are in global scope, so you can 45 | inspect them from the console.

46 | 47 | View source on GitHub 49 | 50 |
51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/content/getusermedia/canvas/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | // Put variables in global scope to make them available to the browser console. 12 | const video = document.querySelector('video'); 13 | const canvas = window.canvas = document.querySelector('canvas'); 14 | canvas.width = 480; 15 | canvas.height = 360; 16 | 17 | const button = document.querySelector('button'); 18 | button.onclick = function() { 19 | canvas.width = video.videoWidth; 20 | canvas.height = video.videoHeight; 21 | canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height); 22 | }; 23 | 24 | const constraints = { 25 | audio: false, 26 | video: true 27 | }; 28 | 29 | function handleSuccess(stream) { 30 | window.stream = stream; // make stream available to browser console 31 | video.srcObject = stream; 32 | } 33 | 34 | function handleError(error) { 35 | console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name); 36 | } 37 | 38 | navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError); 39 | -------------------------------------------------------------------------------- /src/content/getusermedia/filter/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | getUserMedia + CSS filters 24 | 25 | 26 | 27 | 28 | 29 | 64 | 65 | 66 | 67 | 68 |
69 | 70 |

WebRTC samples getUserMedia + CSS filters 71 |

72 | 73 | 74 | 75 | 76 | 83 | 84 | 85 | 86 | 87 | 88 |

Draw a frame from the getUserMedia video stream onto the canvas element, then apply CSS filters.

89 | 90 |

The variables canvas, video and stream are in global scope, so you can 91 | inspect them from the console.

92 | 93 | View source on GitHub 95 |
96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | -------------------------------------------------------------------------------- /src/content/getusermedia/filter/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | const snapshotButton = document.querySelector('button#snapshot'); 12 | const filterSelect = document.querySelector('select#filter'); 13 | 14 | // Put variables in global scope to make them available to the browser console. 15 | const video = window.video = document.querySelector('video'); 16 | const canvas = window.canvas = document.querySelector('canvas'); 17 | canvas.width = 480; 18 | canvas.height = 360; 19 | 20 | snapshotButton.onclick = function() { 21 | canvas.className = filterSelect.value; 22 | canvas.getContext('2d').drawImage(video, 0, 0, canvas.width, canvas.height); 23 | }; 24 | 25 | filterSelect.onchange = function() { 26 | video.className = filterSelect.value; 27 | }; 28 | 29 | const constraints = { 30 | audio: false, 31 | video: true 32 | }; 33 | 34 | function handleSuccess(stream) { 35 | window.stream = stream; // make stream available to browser console 36 | video.srcObject = stream; 37 | } 38 | 39 | function handleError(error) { 40 | console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name); 41 | } 42 | 43 | navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError); 44 | -------------------------------------------------------------------------------- /src/content/getusermedia/getdisplaymedia/css/styles.css: -------------------------------------------------------------------------------- 1 | video#captured-media { 2 | width: 100%; 3 | height: calc(width * 16 / 9); 4 | } -------------------------------------------------------------------------------- /src/content/getusermedia/getdisplaymedia/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | getDisplayMedia 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
36 |

WebRTC samples Demo of getDisplayMedia and screen recording

37 | 38 |

Screen capturing is currently an experimental feature which is only supported by latest Chrome and Firefox!

39 |

To enable this feature in Chrome, toggle the Experimental Web Platform feature (See chrome://flags/#enable-experimental-web-platform-features).

40 | 41 | 42 |

Display the screensharing stream from getDisplayMedia() in a video element and record the stream.

43 | 44 | View source on GitHub 45 |
46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | -------------------------------------------------------------------------------- /src/content/getusermedia/gum/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | getUserMedia 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 |
34 |

WebRTC samples 35 | getUserMedia

36 | 37 | 38 | 39 | 40 |
41 | 42 |

Warning: if you're not using headphones, pressing play will cause feedback.

43 | 44 |

Display the video stream from getUserMedia() in a video element.

45 | 46 |

The MediaStream object stream passed to the getUserMedia() callback is in 47 | global scope, so you can inspect it from the console.

48 | 49 | View source on GitHub 51 |
52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | -------------------------------------------------------------------------------- /src/content/getusermedia/gum/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 'use strict'; 9 | 10 | // Put variables in global scope to make them available to the browser console. 11 | const constraints = window.constraints = { 12 | audio: false, 13 | video: true 14 | }; 15 | 16 | function handleSuccess(stream) { 17 | const video = document.querySelector('video'); 18 | const videoTracks = stream.getVideoTracks(); 19 | console.log('Got stream with constraints:', constraints); 20 | console.log(`Using video device: ${videoTracks[0].label}`); 21 | window.stream = stream; // make variable available to browser console 22 | video.srcObject = stream; 23 | } 24 | 25 | function handleError(error) { 26 | if (error.name === 'ConstraintNotSatisfiedError') { 27 | let v = constraints.video; 28 | errorMsg(`The resolution ${v.width.exact}x${v.height.exact} px is not supported by your device.`); 29 | } else if (error.name === 'PermissionDeniedError') { 30 | errorMsg('Permissions have not been granted to use your camera and ' + 31 | 'microphone, you need to allow the page access to your devices in ' + 32 | 'order for the demo to work.'); 33 | } 34 | errorMsg(`getUserMedia error: ${error.name}`, error); 35 | } 36 | 37 | function errorMsg(msg, error) { 38 | const errorElement = document.querySelector('#errorMsg'); 39 | errorElement.innerHTML += `

${msg}

`; 40 | if (typeof error !== 'undefined') { 41 | console.error(error); 42 | } 43 | } 44 | 45 | async function init(e) { 46 | try { 47 | const stream = await navigator.mediaDevices.getUserMedia(constraints); 48 | handleSuccess(stream); 49 | e.target.disabled = true; 50 | } catch (e) { 51 | handleError(e); 52 | } 53 | } 54 | 55 | document.querySelector('#showVideo').addEventListener('click', e => init(e)); -------------------------------------------------------------------------------- /src/content/getusermedia/gum/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | export default { 9 | 'It should have a video element': (browser) => { 10 | const path = '/src/content/getusermedia/gum/index.html'; 11 | const url = 'file://' + process.cwd() + path; 12 | 13 | browser.url(url) 14 | .waitForElementVisible('button#showVideo', 1000) 15 | .click('button#showVideo') 16 | .waitForElementVisible('video') 17 | .waitForMediaPlaybackReady('video', 5000) 18 | .end(); 19 | } 20 | }; -------------------------------------------------------------------------------- /src/content/getusermedia/record/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 3px 10px 0; 10 | padding-left: 2px; 11 | padding-right: 2px; 12 | width: 99px; 13 | } 14 | 15 | button:last-of-type { 16 | margin: 0; 17 | } 18 | 19 | p.borderBelow { 20 | margin: 0 0 20px 0; 21 | padding: 0 0 20px 0; 22 | } 23 | 24 | video { 25 | vertical-align: top; 26 | --width: 25vw; 27 | width: var(--width); 28 | height: calc(var(--width) * 0.5625); 29 | } 30 | 31 | video:last-of-type { 32 | margin: 0 0 20px 0; 33 | } 34 | 35 | video#gumVideo { 36 | margin: 0 20px 20px 0; 37 | } 38 | -------------------------------------------------------------------------------- /src/content/getusermedia/record/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | MediaStream Recording 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

WebRTC samples 37 | MediaRecorder

38 | 39 |

For more information see the MediaStream Recording API Editor's Draft.

42 | 43 | 44 | 45 | 46 |
47 | 48 | 49 | 50 | 51 |
52 | 53 |
54 |

Media Stream Constraints options

55 |

Echo cancellation:

56 |
57 | 58 |
59 | 60 |
61 | 62 | View source on GitHub 64 | 65 |
66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/content/getusermedia/record/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | export default { 9 | 'Recording of video is working.': (browser) => { 10 | const path = '/src/content/getusermedia/record/index.html'; 11 | const url = 'file://' + process.cwd() + path; 12 | 13 | browser.url(url).waitForElementVisible('button#record', 1000); 14 | browser.click('button#record'); 15 | browser.waitForReadyState('video#gum', 4, 5000); 16 | browser.pause(1000); 17 | browser.click('button#record'); 18 | browser.expect.element('button#play').to.be.enabled.before(1000); 19 | browser.click('button#play'); 20 | browser.waitForReadyState('video#recorded', 4, 5000); 21 | browser.end(); 22 | } 23 | }; -------------------------------------------------------------------------------- /src/content/getusermedia/resolution/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | export default { 9 | 'It should have a video element with specific width': (browser) => { 10 | const path = '/src/content/getusermedia/resolution/index.html'; 11 | const url = 'file://' + process.cwd() + path; 12 | 13 | browser 14 | .url(url) 15 | .click('button#qvga') 16 | .pause(500) 17 | .waitForElementVisible('video', 5000) 18 | .waitForMediaPlaybackReady('video', 10000) 19 | .assert.videoWidth('video', 320, 'Video width is 320 wide.') 20 | .click('button#vga') 21 | .pause(500) 22 | .waitForElementVisible('video', 5000) 23 | .waitForMediaPlaybackReady('video', 10000) 24 | .assert.videoWidth('video', 640, 'Video width is 640 wide.') 25 | .click('button#hd') 26 | .pause(500) 27 | .waitForElementVisible('video', 5000) 28 | .waitForMediaPlaybackReady('video', 10000) 29 | .assert.videoWidth('video', 1280, 'Video width is 1280 wide.') 30 | .end(); 31 | } 32 | }; -------------------------------------------------------------------------------- /src/content/getusermedia/source/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 13 | Page move 14 | 15 | 16 |

The page has moved to: 17 | this page

18 | 19 | 20 | -------------------------------------------------------------------------------- /src/content/getusermedia/volume/css/main.css: -------------------------------------------------------------------------------- 1 | div#meters > div { 2 | margin: 0 0 1em 0; 3 | } 4 | 5 | div#meters div.label { 6 | display: inline-block; 7 | font-weight: 400; 8 | margin: 0 0.5em 0 0; 9 | width: 3.5em; 10 | } 11 | 12 | div#meters div.value { 13 | display: inline-block; 14 | } 15 | 16 | meter { 17 | width: 50%; 18 | } 19 | 20 | meter#clip { 21 | color: #db4437; 22 | } 23 | 24 | meter#slow { 25 | color: #f4b400; 26 | } 27 | 28 | meter#instant { 29 | color: #0f9d58; 30 | } 31 | -------------------------------------------------------------------------------- /src/content/getusermedia/volume/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Audio stream volume 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

WebRTC samples Audio stream volume 37 |

38 | 39 |

Measure the volume of a local media stream using WebAudio.

40 | 41 |
42 |
43 |
Instant:
44 | 45 |
46 |
47 |
48 |
Slow:
49 | 50 |
51 |
52 |
53 |
Clip:
54 | 55 |
56 |
57 |
58 | 59 |

The 'instant' volume changes approximately every 50ms; the 'slow' volume approximates the average volume over 60 | about a second.

61 |

Note that you will not hear your own voice; use the local audio rendering demo for that. 62 |

63 |

The audioContext, stream and soundMeter variables are in global scope, so 64 | you can inspect them from the console.

65 | 66 | View source on GitHub 68 | 69 |
70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | -------------------------------------------------------------------------------- /src/content/getusermedia/volume/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | /* global AudioContext, SoundMeter */ 10 | 11 | 'use strict'; 12 | 13 | const instantMeter = document.querySelector('#instant meter'); 14 | const slowMeter = document.querySelector('#slow meter'); 15 | const clipMeter = document.querySelector('#clip meter'); 16 | 17 | const instantValueDisplay = document.querySelector('#instant .value'); 18 | const slowValueDisplay = document.querySelector('#slow .value'); 19 | const clipValueDisplay = document.querySelector('#clip .value'); 20 | 21 | try { 22 | window.AudioContext = window.AudioContext || window.webkitAudioContext; 23 | window.audioContext = new AudioContext(); 24 | } catch (e) { 25 | alert('Web Audio API not supported.'); 26 | } 27 | 28 | // Put variables in global scope to make them available to the browser console. 29 | const constraints = window.constraints = { 30 | audio: true, 31 | video: false 32 | }; 33 | 34 | function handleSuccess(stream) { 35 | // Put variables in global scope to make them available to the 36 | // browser console. 37 | window.stream = stream; 38 | const soundMeter = window.soundMeter = new SoundMeter(window.audioContext); 39 | soundMeter.connectToSource(stream, function(e) { 40 | if (e) { 41 | alert(e); 42 | return; 43 | } 44 | setInterval(() => { 45 | instantMeter.value = instantValueDisplay.innerText = 46 | soundMeter.instant.toFixed(2); 47 | slowMeter.value = slowValueDisplay.innerText = 48 | soundMeter.slow.toFixed(2); 49 | clipMeter.value = clipValueDisplay.innerText = 50 | soundMeter.clip; 51 | }, 200); 52 | }); 53 | } 54 | 55 | function handleError(error) { 56 | console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name); 57 | } 58 | 59 | navigator.mediaDevices.getUserMedia(constraints).then(handleSuccess).catch(handleError); 60 | -------------------------------------------------------------------------------- /src/content/getusermedia/volume/js/soundmeter.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | // Meter class that generates a number correlated to audio volume. 12 | // The meter class itself displays nothing, but it makes the 13 | // instantaneous and time-decaying volumes available for inspection. 14 | // It also reports on the fraction of samples that were at or near 15 | // the top of the measurement range. 16 | function SoundMeter(context) { 17 | this.context = context; 18 | this.instant = 0.0; 19 | this.slow = 0.0; 20 | this.clip = 0.0; 21 | this.script = context.createScriptProcessor(2048, 1, 1); 22 | const that = this; 23 | this.script.onaudioprocess = function(event) { 24 | const input = event.inputBuffer.getChannelData(0); 25 | let i; 26 | let sum = 0.0; 27 | let clipcount = 0; 28 | for (i = 0; i < input.length; ++i) { 29 | sum += input[i] * input[i]; 30 | if (Math.abs(input[i]) > 0.99) { 31 | clipcount += 1; 32 | } 33 | } 34 | that.instant = Math.sqrt(sum / input.length); 35 | that.slow = 0.95 * that.slow + 0.05 * that.instant; 36 | that.clip = clipcount / input.length; 37 | }; 38 | } 39 | 40 | SoundMeter.prototype.connectToSource = function(stream, callback) { 41 | console.log('SoundMeter connecting'); 42 | try { 43 | this.mic = this.context.createMediaStreamSource(stream); 44 | this.mic.connect(this.script); 45 | // necessary to make sample run, but should not be. 46 | this.script.connect(this.context.destination); 47 | if (typeof callback !== 'undefined') { 48 | callback(null); 49 | } 50 | } catch (e) { 51 | console.error(e); 52 | if (typeof callback !== 'undefined') { 53 | callback(e); 54 | } 55 | } 56 | }; 57 | 58 | SoundMeter.prototype.stop = function() { 59 | this.mic.disconnect(); 60 | this.script.disconnect(); 61 | }; 62 | -------------------------------------------------------------------------------- /src/content/peerconnection/audio/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | audio { 9 | display: inline-block; 10 | position: relative; 11 | top: 9px; 12 | width: calc(100% - 120px); 13 | } 14 | 15 | button { 16 | margin: 0 20px 0 0; 17 | width: 96px; 18 | } 19 | 20 | table { 21 | border-collapse: collapse; 22 | } 23 | 24 | th, td { 25 | border: 1px solid black; 26 | } 27 | 28 | tr:hover { 29 | background-color: #f5f5f5; 30 | } 31 | 32 | div#audio { 33 | margin: 0 0 29px 0; 34 | } 35 | 36 | div#audio > div { 37 | margin: 0 0 20px 0; 38 | } 39 | 40 | div.label { 41 | display: inline-block; 42 | font-weight: 400; 43 | width: 120px; 44 | } 45 | 46 | div.graph-container { 47 | float: left; 48 | margin: 0.5em; 49 | width: calc(50% - 1em); 50 | } 51 | 52 | a#viewSource { 53 | clear: both; 54 | } 55 | -------------------------------------------------------------------------------- /src/content/peerconnection/audio/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | export default { 9 | 'It should play audio remote': (browser) => { 10 | const path = '/src/content/peerconnection/audio/index.html'; 11 | const url = 'file://' + process.cwd() + path; 12 | 13 | // TODO Test all codecs? 14 | browser 15 | .url(url) 16 | .click('#callButton') 17 | .waitForMediaPlaybackReady('#audio2', 5000, 'Receiving remote audio.') 18 | .end(); 19 | } 20 | }; -------------------------------------------------------------------------------- /src/content/peerconnection/bandwidth/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | video { 9 | --width: 45%; 10 | width: var(--width); 11 | height: calc(var(--width) * 0.75); 12 | } 13 | 14 | button { 15 | margin: 0 20px 0 0; 16 | width: 96px; 17 | } 18 | 19 | video#localVideo { 20 | margin: 0 20px 20px 0; 21 | } 22 | 23 | div.label { 24 | display: inline-block; 25 | font-weight: 400; 26 | width: 120px; 27 | } 28 | 29 | div.graph-container { 30 | float: left; 31 | margin: 0.5em; 32 | width: calc(50% - 1em); 33 | } 34 | 35 | a#viewSource { 36 | clear: both; 37 | } 38 | -------------------------------------------------------------------------------- /src/content/peerconnection/bandwidth/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Peer connection: adjust bandwidth 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 |
36 | 37 |

WebRTC samples Peer connection: adjust bandwidth 38 |

39 | 40 | 41 | 42 | 43 |
44 | 45 | 53 | kbps 54 | 55 | 56 |
57 |
58 |
Bitrate
59 | 60 |
61 |
62 |
Packets sent per second
63 | 64 |
65 | 66 | View source on GitHub 68 | 69 |
70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | -------------------------------------------------------------------------------- /src/content/peerconnection/constraints/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 20px 25px 0; 10 | vertical-align: top; 11 | width: 134px; 12 | } 13 | 14 | div#getUserMedia { 15 | padding: 0 0 8px 0; 16 | } 17 | 18 | div.input { 19 | display: inline-block; 20 | margin: 0 4px 0 0; 21 | vertical-align: top; 22 | width: 310px; 23 | } 24 | 25 | div.input > div { 26 | margin: 0 0 20px 0; 27 | vertical-align: top; 28 | } 29 | 30 | div.output { 31 | background-color: #eee; 32 | display: inline-block; 33 | font-family: 'Inconsolata', 'Courier New', monospace; 34 | font-size: 0.9em; 35 | padding: 10px 10px 10px 25px; 36 | position: relative; 37 | top: 10px; 38 | white-space: pre; 39 | width: 270px; 40 | } 41 | 42 | section#statistics div { 43 | display: inline-block; 44 | font-family: 'Inconsolata', 'Courier New', monospace; 45 | vertical-align: top; 46 | width: 308px; 47 | } 48 | 49 | section#statistics div#senderStats { 50 | margin: 0 20px 0 0; 51 | } 52 | 53 | section#constraints > div { 54 | margin: 0 0 20px 0; 55 | } 56 | 57 | section#video > div { 58 | display: inline-block; 59 | margin: 0 20px 0 0; 60 | vertical-align: top; 61 | width: calc(50% - 22px); 62 | } 63 | 64 | section#video > div div { 65 | font-size: 0.9em; 66 | margin: 0 0 0.5em 0; 67 | width: 320px; 68 | } 69 | 70 | h2 { 71 | margin: 0 0 1em 0; 72 | } 73 | 74 | section#constraints label { 75 | display: inline-block; 76 | width: 156px; 77 | } 78 | 79 | section { 80 | margin: 0 0 20px 0; 81 | padding: 0 0 15px 0; 82 | } 83 | 84 | section#video { 85 | width: calc(100% + 20px); 86 | } 87 | 88 | video { 89 | --width: 90%; 90 | width: var(--width); 91 | height: calc(var(--width) * 0.75); 92 | margin: 0 0 10px 0; 93 | } 94 | 95 | @media screen and (max-width: 720px) { 96 | button { 97 | font-weight: 500; 98 | height: 56px; 99 | line-height: 1.3em; 100 | width: 90px; 101 | } 102 | 103 | div#getUserMedia { 104 | padding: 0 0 40px 0; 105 | } 106 | 107 | section#statistics div { 108 | width: calc(50% - 14px); 109 | } 110 | 111 | video { 112 | height: 96px; 113 | } 114 | } 115 | -------------------------------------------------------------------------------- /src/content/peerconnection/create-offer/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | button { 10 | margin: 20px 10px 0 0; 11 | width: 100px; 12 | } 13 | 14 | div#constraints { 15 | margin: 0 0 20px 0; 16 | } 17 | 18 | div#numAudioTracks { 19 | margin: 0 0 20px 0; 20 | } 21 | 22 | div#constraints div { 23 | margin: 0 0 10px 0; 24 | } 25 | 26 | div#constraints input { 27 | margin: 0 10px 0 0; 28 | position: relative; 29 | top: -2px; 30 | } 31 | 32 | div#numAudioTracks input { 33 | max-width: 30%; 34 | position: relative; 35 | top: 2px; 36 | width: 200px; 37 | } 38 | 39 | label { 40 | font-weight: 500; 41 | margin: 0 10px 0 0; 42 | } 43 | 44 | textarea { 45 | height: 200px; 46 | width: 100%; 47 | } 48 | -------------------------------------------------------------------------------- /src/content/peerconnection/create-offer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | createOffer() output 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

WebRTC samples createOffer() output 37 |

38 | 39 |

This page tests the createOffer() method. It creates a peer connection, then prints out the SDP 40 | generated by createOffer(), with the number of desired audio MediaStreamTracks and the 41 | checked constraints. Currently, only audio tracks can be added, as there is no programmatic way to generate 42 | video tracks. (Web Audio is used to generate the audio tracks.)

43 | 44 |
45 | 46 | 47 | 1 48 |
49 | 50 |
51 |
52 | 53 |
54 |
55 | 56 |
57 |
58 | 59 |
60 |
61 | 62 |
63 |
64 | 65 | 66 | 67 | 68 | 69 | View source on GitHub 71 | 72 |
73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | -------------------------------------------------------------------------------- /src/content/peerconnection/create-offer/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | const audioInput = document.querySelector('input#audio'); 12 | const restartInput = document.querySelector('input#restart'); 13 | const vadInput = document.querySelector('input#vad'); 14 | const videoInput = document.querySelector('input#video'); 15 | 16 | const numAudioTracksInput = document.querySelector('div#numAudioTracks input'); 17 | const numAudioTracksDisplay = document.querySelector('span#numAudioTracksDisplay'); 18 | const outputTextarea = document.querySelector('textarea#output'); 19 | const createOfferButton = document.querySelector('button#createOffer'); 20 | 21 | createOfferButton.addEventListener('click', createOffer); 22 | numAudioTracksInput.addEventListener('change', e => numAudioTracksDisplay.innerText = e.target.value); 23 | 24 | async function createOffer() { 25 | outputTextarea.value = ''; 26 | const peerConnection = window.peerConnection = new RTCPeerConnection(null); 27 | const numRequestedAudioTracks = parseInt(numAudioTracksInput.value); 28 | 29 | for (let i = 0; i < numRequestedAudioTracks; i++) { 30 | const acx = new AudioContext(); 31 | const dst = acx.createMediaStreamDestination(); 32 | 33 | // Fill up the peer connection with numRequestedAudioTracks number of tracks. 34 | const track = dst.stream.getTracks()[0]; 35 | peerConnection.addTrack(track, dst.stream); 36 | } 37 | 38 | const offerOptions = { 39 | // New spec states offerToReceiveAudio/Video are of type long (due to 40 | // having to tell how many "m" lines to generate). 41 | // http://w3c.github.io/webrtc-pc/#idl-def-RTCOfferAnswerOptions. 42 | offerToReceiveAudio: (audioInput.checked) ? 1 : 0, 43 | offerToReceiveVideo: (videoInput.checked) ? 1 : 0, 44 | iceRestart: restartInput.checked, 45 | voiceActivityDetection: vadInput.checked 46 | }; 47 | 48 | try { 49 | const offer = await peerConnection.createOffer(offerOptions); 50 | await peerConnection.setLocalDescription(offer); 51 | outputTextarea.value = offer.sdp; 52 | } catch (e) { 53 | outputTextarea.value = `Failed to create offer: ${e}`; 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /src/content/peerconnection/dtmf/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 20px 20px 0; 10 | width: 96px; 11 | } 12 | 13 | div#dialPad button { 14 | background-color: #ddd; 15 | border: 1px solid #ccc; 16 | color: black; 17 | font-size: 1em; 18 | font-weight: 400; 19 | height: 40px; 20 | margin: 0 10px 10px 0; 21 | width: 40px; 22 | } 23 | 24 | div#dialPad button:hover { 25 | background-color: #aaa; 26 | } 27 | 28 | div#dialPad button:active { 29 | background-color: #888; 30 | } 31 | 32 | div#dialPad { 33 | display: inline-block; 34 | margin: 0 20px 20px 0; 35 | vertical-align: top; 36 | } 37 | 38 | div#parameters { 39 | margin: 0 0 25px 0; 40 | } 41 | 42 | div#parameters > div { 43 | height: 28px; 44 | margin: 0 0 10px 0; 45 | } 46 | 47 | div#dtmf { 48 | background-color: #eee; 49 | display: inline-block; 50 | height: 180px; 51 | margin: 0 0 20px 0; 52 | padding: 5px 5px 5px 10px; 53 | width: calc(100% - 239px); 54 | } 55 | 56 | div#dtmf div { 57 | font-family: 'Inconsolata', 'Courier New', monospace; 58 | } 59 | 60 | div#sentTones { 61 | display: inline-block; 62 | line-height: 1.2em; 63 | } 64 | 65 | div#dtmfStatus { 66 | margin: 0 0 10px 0; 67 | } 68 | 69 | div#parameters input[type = range] { 70 | font-size: 1em; 71 | width: 85px; 72 | } 73 | 74 | div#parameters input#tones { 75 | width: calc(100% - 78px); 76 | } 77 | 78 | div#parameters label { 79 | display: inline-block; 80 | font-weight: 400; 81 | height: 28px; 82 | position: relative; 83 | top: 4px; 84 | vertical-align: top; 85 | width: 68px; 86 | } 87 | 88 | 89 | -------------------------------------------------------------------------------- /src/content/peerconnection/dtmf/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | export default { 9 | 'It should send DTMF codes': (browser) => { 10 | const path = '/src/content/peerconnection/dtmf/index.html'; 11 | const url = 'file://' + process.cwd() + path; 12 | 13 | if (browser.options.desiredCapabilities.browserName === 'safari') { 14 | browser.end(); 15 | return; 16 | } 17 | 18 | browser 19 | .url(url) 20 | .click('#callButton') 21 | .waitForMediaPlaybackReady('audio', 1000, 'Receiving remote audio.') 22 | .useXpath() 23 | .click('/html/body/div/div[@id=\'dialPad\']/div[1]/button[1]') // 1 24 | .click('/html/body/div/div[@id=\'dialPad\']/div[3]/button[1]') // 9 25 | .click('/html/body/div/div[@id=\'dialPad\']/div[3]/button[4]') // # 26 | .click('/html/body/div/div[@id=\'dialPad\']/div[4]/button[1]') // A 27 | .useCss() 28 | .assert.value('input#sentTones', '1 9 # A ') 29 | .click('#hangupButton') 30 | .end(); 31 | } 32 | }; 33 | -------------------------------------------------------------------------------- /src/content/peerconnection/multiple-relay/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | button { 10 | margin: 20px 10px 0 0; 11 | width: 100px; 12 | } 13 | 14 | div#buttons { 15 | margin: 0 0 20px 0; 16 | } 17 | 18 | div#status { 19 | height: 2em; 20 | margin: 1em 0 0 0; 21 | } 22 | 23 | input#audio { 24 | margin: 0 0.5em 0 0; 25 | position: relative; 26 | top: -1px; 27 | } 28 | 29 | video { 30 | --width: 45%; 31 | width: var(--width); 32 | height: calc(var(--width) * 0.75); 33 | } 34 | 35 | -------------------------------------------------------------------------------- /src/content/peerconnection/multiple-relay/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Peer connection relay 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

WebRTC samples Peer connection relay 37 |

38 | 39 |
40 | 41 | 42 |
43 | 44 |
45 | 46 |
47 | 48 | 49 | 50 | 51 |
52 | 53 |
54 | 55 | View source on GitHub 57 | 58 |
59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/content/peerconnection/multiple-relay/js/main.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | /* global VideoPipe */ 12 | 13 | const video1 = document.querySelector('video#video1'); 14 | const video2 = document.querySelector('video#video2'); 15 | 16 | const statusDiv = document.querySelector('div#status'); 17 | 18 | const audioCheckbox = document.querySelector('input#audio'); 19 | 20 | const startButton = document.querySelector('button#start'); 21 | const callButton = document.querySelector('button#call'); 22 | const insertRelayButton = document.querySelector('button#insertRelay'); 23 | const hangupButton = document.querySelector('button#hangup'); 24 | 25 | startButton.onclick = start; 26 | callButton.onclick = call; 27 | insertRelayButton.onclick = insertRelay; 28 | hangupButton.onclick = hangup; 29 | 30 | const pipes = []; 31 | 32 | let localStream; 33 | let remoteStream; 34 | 35 | function gotStream(stream) { 36 | console.log('Received local stream'); 37 | video1.srcObject = stream; 38 | localStream = stream; 39 | callButton.disabled = false; 40 | } 41 | 42 | function gotremoteStream(stream) { 43 | remoteStream = stream; 44 | video2.srcObject = stream; 45 | console.log('Received remote stream'); 46 | console.log(`${pipes.length} element(s) in chain`); 47 | statusDiv.textContent = `${pipes.length} element(s) in chain`; 48 | insertRelayButton.disabled = false; 49 | } 50 | 51 | function start() { 52 | console.log('Requesting local stream'); 53 | startButton.disabled = true; 54 | const options = audioCheckbox.checked ? {audio: true, video: true} : {audio: false, video: true}; 55 | navigator.mediaDevices 56 | .getUserMedia(options) 57 | .then(gotStream) 58 | .catch(function(e) { 59 | alert('getUserMedia() failed'); 60 | console.log('getUserMedia() error: ', e); 61 | }); 62 | } 63 | 64 | function call() { 65 | callButton.disabled = true; 66 | insertRelayButton.disabled = false; 67 | hangupButton.disabled = false; 68 | console.log('Starting call'); 69 | pipes.push(new VideoPipe(localStream, gotremoteStream)); 70 | } 71 | 72 | function insertRelay() { 73 | pipes.push(new VideoPipe(remoteStream, gotremoteStream)); 74 | insertRelayButton.disabled = true; 75 | } 76 | 77 | function hangup() { 78 | console.log('Ending call'); 79 | while (pipes.length > 0) { 80 | const pipe = pipes.pop(); 81 | pipe.close(); 82 | } 83 | insertRelayButton.disabled = true; 84 | hangupButton.disabled = true; 85 | callButton.disabled = false; 86 | } 87 | -------------------------------------------------------------------------------- /src/content/peerconnection/multiple/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 20px 0 0; 10 | width: 83px; 11 | } 12 | 13 | button#hangupButton { 14 | margin: 0; 15 | } 16 | 17 | video { 18 | margin: 0 0 20px 0; 19 | --width: 40%; 20 | width: var(--width); 21 | height: calc(var(--width) * 0.75); 22 | } 23 | 24 | video#video1 { 25 | margin: 0 20px 20px 0; 26 | } 27 | 28 | @media screen and (max-width: 400px) { 29 | button { 30 | margin: 0 11px 10px 0; 31 | } 32 | 33 | video { 34 | height: 90px; 35 | margin: 0 0 10px 0; 36 | width: calc(50% - 8px); 37 | } 38 | 39 | video#video1 { 40 | margin: 0 10px 10px 0; 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/content/peerconnection/multiple/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Multiple peer connections 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

WebRTC samples Multiple peer connections 37 |

38 | 39 | 40 | 41 | 42 | 43 |
44 | 45 | 46 | 47 |
48 | 49 |

View the console to see logging and to inspect the MediaStream object localStream.

50 | 51 |

For more information about RTCPeerConnection, see Getting 53 | Started With WebRTC.

54 | 55 | 56 | View source on GitHub 58 | 59 |
60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/content/peerconnection/multiple/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | /* eslint-env node */ 9 | 10 | 'use strict'; 11 | export default { 12 | 'Video and buttons state change during multiple peer connection setup': (browser) => { 13 | const path = '/src/content/peerconnection/multiple/index.html'; 14 | const url = 'file://' + process.cwd() + path; 15 | 16 | browser.url(url).waitForElementVisible('#startButton', 1000, 'Check that the start button is visible'); 17 | browser.waitForReadyState('#video1', 0, 1000); 18 | browser.waitForReadyState('#video2', 0, 1000); 19 | browser.waitForReadyState('#video3', 0, 1000); 20 | browser.expect.element('#callButton').to.not.be.enabled.before(1000); 21 | browser.click('#startButton'); 22 | browser.waitForReadyState('#video1', 4, 1000); 23 | browser.expect.element('#callButton').to.be.enabled.before(1000); 24 | browser.expect.element('#hangupButton').to.not.be.enabled.before(1000); 25 | browser.click('#callButton'); 26 | browser.waitForReadyState('#video2', 4, 1000); 27 | browser.waitForReadyState('#video3', 4, 1000); 28 | browser.expect.element('#hangupButton').to.be.enabled.before(1000); 29 | browser.end(); 30 | } 31 | }; 32 | -------------------------------------------------------------------------------- /src/content/peerconnection/munge-sdp/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 20px 20px 0; 10 | vertical-align: top; 11 | width: 155px; 12 | } 13 | div#buttons { 14 | border-bottom: 1px solid #eee; 15 | margin: 1em 0 1em 0; 16 | padding: 0 0 1em 0; 17 | } 18 | div#local { 19 | margin: 0 20px 0 0; 20 | } 21 | div#preview { 22 | border-bottom: 1px solid #eee; 23 | margin: 0 0 1em 0; 24 | padding: 0 0 0.5em 0; 25 | } 26 | div#preview > div { 27 | display: inline-block; 28 | vertical-align: top; 29 | width: calc(50% - 12px); 30 | } 31 | div#select { 32 | margin: 0 0 1em 0; 33 | } 34 | div#selectSource { 35 | margin: 0 0 1em 0; 36 | } 37 | div.source { 38 | display: inline-block; 39 | margin: 0 0 1em 0; 40 | } 41 | form { 42 | margin: 0 0 1em 0; 43 | white-space: nowrap; 44 | } 45 | h2 { 46 | margin: 0 0 0.5em 0; 47 | } 48 | label { 49 | margin: 0 0.4em 0 0; 50 | } 51 | textarea { 52 | color: #444; 53 | font-size: 0.9em; 54 | font-weight: 300; 55 | height: 7.0em; 56 | padding: 5px; 57 | width: calc(100% - 10px); 58 | } 59 | video { 60 | height: 225px; 61 | } 62 | 63 | @media screen and (max-width: 550px) { 64 | button { 65 | font-weight: 500; 66 | height: 56px; 67 | line-height: 1.3em; 68 | margin: 0 7px 15px 0; 69 | width: 86px; 70 | } 71 | button:nth-child(3n+0) { 72 | margin: 0 0 15px 0; 73 | } 74 | video { 75 | height: 96px; 76 | } 77 | } 78 | 79 | @media screen and (max-width: 800px) { 80 | button { 81 | margin: 0 15px 15px 0; 82 | width: 155px; 83 | } 84 | div#selectSource { 85 | margin: 0 0 0.5em 0; 86 | } 87 | div.source { 88 | margin: 0 0 .2em 0; 89 | } 90 | select { 91 | margin: 0 1.5em 0 0; 92 | } 93 | textarea { 94 | font-size: 0.7em; 95 | } 96 | } 97 | 98 | @media screen and (max-width: 500px) { 99 | textarea { 100 | font-size: 0.5em; 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /src/content/peerconnection/munge-sdp/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | /* eslint-env node */ 9 | 10 | 'use strict'; 11 | export default { 12 | 'Checking element state during manual signalling': (browser) => { 13 | const path = '/src/content/peerconnection/munge-sdp/index.html'; 14 | const url = 'file://' + process.cwd() + path; 15 | 16 | browser.url(url).waitForElementVisible('#getMedia', 1000, 'Check that the getMedia button is visible'); 17 | browser.expect.element('#createPeerConnection').to.not.be.enabled.before(1000); 18 | browser.expect.element('#createOffer').to.not.be.enabled.before(1000); 19 | browser.expect.element('#setOffer').to.not.be.enabled.before(1000); 20 | browser.expect.element('#createAnswer').to.not.be.enabled.before(1000); 21 | browser.expect.element('#setAnswer').to.not.be.enabled.before(1000); 22 | browser.expect.element('#hangup').to.not.be.enabled.before(1000); 23 | browser.click('#getMedia'); 24 | browser.waitForMediaPlaybackReady('div#local video', 5000); 25 | browser.expect.element('#createPeerConnection').to.be.enabled.before(1000); 26 | browser.click('#createPeerConnection'); 27 | browser.expect.element('#createOffer').to.be.enabled.before(1000); 28 | browser.expect.element('#setOffer').to.be.enabled.before(1000); 29 | browser.expect.element('#createAnswer').to.be.enabled.before(1000); 30 | browser.expect.element('#setAnswer').to.be.enabled.before(1000); 31 | browser.expect.element('#hangup').to.be.enabled.before(1000); 32 | browser 33 | .click('#createOffer') 34 | .click('#setOffer') 35 | .click('#createAnswer') 36 | .click('#setAnswer'); 37 | browser.waitForMediaPlaybackReady('div#remote video', 5000); 38 | browser.click('#hangup'); 39 | browser.expect.element('#createPeerConnection').to.not.be.enabled.before(1000); 40 | browser.expect.element('#createOffer').to.not.be.enabled.before(1000); 41 | browser.expect.element('#setOffer').to.not.be.enabled.before(1000); 42 | browser.expect.element('#createAnswer').to.not.be.enabled.before(1000); 43 | browser.expect.element('#setAnswer').to.not.be.enabled.before(1000); 44 | browser.expect.element('#hangup').to.not.be.enabled.before(1000); 45 | browser.end(); 46 | } 47 | }; 48 | -------------------------------------------------------------------------------- /src/content/peerconnection/old-new-stats/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2018 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 20px 25px 0; 10 | vertical-align: top; 11 | width: 134px; 12 | } 13 | 14 | div#getUserMedia { 15 | padding: 0 0 8px 0; 16 | } 17 | 18 | div.input { 19 | display: inline-block; 20 | margin: 0 4px 0 0; 21 | vertical-align: top; 22 | width: 310px; 23 | } 24 | 25 | div.input > div { 26 | margin: 0 0 20px 0; 27 | vertical-align: top; 28 | } 29 | 30 | div.output { 31 | background-color: #eee; 32 | display: inline-block; 33 | font-family: 'Inconsolata', 'Courier New', monospace; 34 | font-size: 0.9em; 35 | padding: 10px 10px 10px 25px; 36 | position: relative; 37 | top: 10px; 38 | white-space: pre; 39 | width: 270px; 40 | } 41 | 42 | section#statistics div { 43 | display: inline-block; 44 | font-family: 'Inconsolata', 'Courier New', monospace; 45 | vertical-align: top; 46 | width: 308px; 47 | } 48 | 49 | section#statistics div#senderStats { 50 | margin: 0 20px 0 0; 51 | } 52 | 53 | section#constraints > div { 54 | margin: 0 0 20px 0; 55 | } 56 | 57 | section#video > div { 58 | display: inline-block; 59 | margin: 0 20px 0 0; 60 | vertical-align: top; 61 | width: calc(50% - 22px); 62 | } 63 | 64 | section#video > div div { 65 | font-size: 0.9em; 66 | margin: 0 0 0.5em 0; 67 | width: 320px; 68 | } 69 | 70 | h2 { 71 | margin: 0 0 1em 0; 72 | } 73 | 74 | section#constraints label { 75 | display: inline-block; 76 | width: 156px; 77 | } 78 | 79 | section { 80 | margin: 0 0 20px 0; 81 | padding: 0 0 15px 0; 82 | } 83 | 84 | section#video { 85 | width: calc(100% + 20px); 86 | } 87 | 88 | video { 89 | --width: 100%; 90 | width: var(--width); 91 | height: calc(var(--width) * 0.75); 92 | margin: 0 0 10px 0; 93 | } 94 | 95 | @media screen and (max-width: 720px) { 96 | button { 97 | font-weight: 500; 98 | height: 56px; 99 | line-height: 1.3em; 100 | width: 90px; 101 | } 102 | 103 | div#getUserMedia { 104 | padding: 0 0 40px 0; 105 | } 106 | 107 | section#statistics div { 108 | width: calc(50% - 14px); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /src/content/peerconnection/pc1/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 20px 0 0; 10 | width: 83px; 11 | } 12 | 13 | button#hangupButton { 14 | margin: 0; 15 | } 16 | 17 | video { 18 | --width: 45%; 19 | width: var(--width); 20 | height: calc(var(--width) * 0.75); 21 | margin: 0 0 20px 0; 22 | vertical-align: top; 23 | } 24 | 25 | video#localVideo { 26 | margin: 0 20px 20px 0; 27 | } 28 | 29 | div.box { 30 | margin: 1em; 31 | } 32 | 33 | @media screen and (max-width: 400px) { 34 | button { 35 | width: 83px; 36 | margin: 0 11px 10px 0; 37 | } 38 | 39 | video { 40 | height: 90px; 41 | margin: 0 0 10px 0; 42 | width: calc(50% - 7px); 43 | } 44 | video#localVideo { 45 | margin: 0 10px 20px 0; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/content/peerconnection/pc1/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Peer connection 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 |

WebRTC samples 36 | Peer connection

37 | 38 |

This sample shows how to setup a connection between two peers using 39 | RTCPeerConnection. 40 | An option to specify the SDP semantics for 41 | the connection is also available (unified-plan, plan-b or default). 42 |

43 | 44 | 45 | 46 | 47 |
48 | 49 | 50 | 51 |
52 | 53 |
54 | SDP Semantics: 55 | 60 |
61 | 62 |

View the console to see logging. The MediaStream object localStream, and the RTCPeerConnection 63 | objects pc1 and pc2 are in global scope, so you can inspect them in the console as 64 | well.

65 | 66 |

For more information about RTCPeerConnection, see Getting 68 | Started With WebRTC.

69 | 70 | 71 | View source on GitHub 73 | 74 |
75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /src/content/peerconnection/pc1/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | /* eslint-env node */ 9 | 'use strict'; 10 | export default { 11 | 'It should have select elements for each media device': (browser) => { 12 | const path = '/src/content/peerconnection/pc1/index.html'; 13 | const url = 'file://' + process.cwd() + path; 14 | 15 | browser.url(url).waitForElementVisible('#startButton', 1000, 'Check that the startButton button is visible'); 16 | browser.waitForReadyState('#localVideo', 0, 1000); 17 | browser.waitForReadyState('#remoteVideo', 0, 1000); 18 | browser.expect.element('#callButton').to.not.be.enabled.before(1000); 19 | browser.expect.element('#hangupButton').to.not.be.enabled.before(1000); 20 | browser.click('#startButton'); 21 | browser.expect.element('#startButton').to.not.be.enabled.before(1000); 22 | browser.expect.element('#callButton').to.be.enabled.before(1000); 23 | browser.expect.element('#hangupButton').to.not.be.enabled.before(1000); 24 | browser.waitForReadyState('#localVideo', 4, 1000); 25 | browser.click('#callButton'); 26 | browser.waitForReadyState('#remoteVideo', 4, 1000); 27 | browser.expect.element('#startButton').to.not.be.enabled.before(1000); 28 | browser.expect.element('#callButton').to.not.be.enabled.before(1000); 29 | browser.expect.element('#hangupButton').to.be.enabled.before(1000); 30 | browser.click('#hangupButton'); 31 | browser.expect.element('#startButton').to.not.be.enabled.before(1000); 32 | browser.expect.element('#callButton').to.be.enabled.before(1000); 33 | browser.expect.element('#hangupButton').to.not.be.enabled.before(1000); 34 | browser.end(); 35 | } 36 | }; 37 | -------------------------------------------------------------------------------- /src/content/peerconnection/pr-answer/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | PeerConnection PRANSWER Demo 24 | 25 | 26 | 27 | 28 | 29 | 30 | 37 | 38 | 39 |
40 | 41 |

WebRTC samples Use pranswer when setting up a peer connection 42 |

43 | 44 | 45 | 46 |
47 | 48 | 49 | 50 |

View the console to see logging and to inspect the MediaStream object localStream.

51 |
52 | 53 | 54 | 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /src/content/peerconnection/restart-ice/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 20px 0 0; 10 | width: 83px; 11 | } 12 | 13 | button#hangupButton { 14 | margin: 0; 15 | } 16 | 17 | video { 18 | --width: 100%; 19 | width: var(--width); 20 | height: calc(var(--width) * 0.75); 21 | margin: 0; 22 | } 23 | 24 | div#video > div { 25 | display: inline-block; 26 | margin: 0 5px 0 0; 27 | vertical-align: top; 28 | width: calc(50% - 22px); 29 | } 30 | 31 | @media screen and (max-width: 400px) { 32 | button { 33 | width: 83px; 34 | margin: 0 11px 10px 0; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /src/content/peerconnection/restart-ice/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | ICE Restart 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

WebRTC samples 37 | Peer connection

38 | 39 |
40 |
41 | 42 | 43 |

Not connected.

44 |
45 |
46 | 47 | 48 |

Not connected.

49 |
50 |
51 | 52 |
53 | 54 | 55 | 56 | 57 |
58 | 59 |

View the console to see logging. The MediaStream object localStream, and the RTCPeerConnection 60 | objects localPeerConnection and remotePeerConnection are in global scope, so you can 61 | inspect them in the console as well.

62 | 63 |

For more information about RTCPeerConnection, see Getting 65 | Started With WebRTC.

66 | 67 | 68 | View source on GitHub 70 | 71 |
72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /src/content/peerconnection/restart-ice/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | /* eslint-env node */ 9 | 'use strict'; 10 | export default { 11 | 'Checking the state of buttons, video, and the changing of the candidate ID at during ICE restart.': (browser) => { 12 | const path = '/src/content/peerconnection/restart-ice/index.html'; 13 | const url = 'file://' + process.cwd() + path; 14 | 15 | browser.url(url).waitForElementVisible('#startButton', 1000, 'Check that the startButton button is visible'); 16 | browser.waitForReadyState('#localVideo', 0, 1000); 17 | browser.expect.element('#localCandidateId').to.have.value.that.equals(null); 18 | browser.expect.element('#callButton').to.not.be.enabled.before(1000); 19 | browser.expect.element('#restartButton').to.not.be.enabled.before(1000); 20 | browser.expect.element('#hangupButton').to.not.be.enabled.before(1000); 21 | browser.click('#startButton'); 22 | browser.waitForReadyState('#localVideo', 4, 1000); 23 | browser.expect.element('#startButton').to.not.be.enabled.before(1000); 24 | browser.expect.element('#callButton').to.be.enabled.before(1000); 25 | browser.expect.element('#restartButton').to.not.be.enabled.before(1000); 26 | browser.expect.element('#hangupButton').to.not.be.enabled.before(1000); 27 | browser.click('#callButton'); 28 | browser.waitForReadyState('#remoteVideo', 4, 1000); 29 | browser.expect.element('#startButton').to.not.be.enabled.before(1000); 30 | browser.expect.element('#callButton').to.not.be.enabled.before(1000); 31 | browser.expect.element('#restartButton').to.be.enabled.before(1000); 32 | browser.expect.element('#hangupButton').to.be.enabled.before(1000); 33 | browser.click('#hangupButton'); 34 | browser.expect.element('#startButton').to.not.be.enabled.before(1000); 35 | browser.expect.element('#callButton').to.be.enabled.before(1000); 36 | browser.expect.element('#restartButton').to.not.be.enabled.before(1000); 37 | browser.expect.element('#hangupButton').to.not.be.enabled.before(1000); 38 | browser.end(); 39 | } 40 | }; 41 | -------------------------------------------------------------------------------- /src/content/peerconnection/states/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 20px 20px 0; 10 | width: 86.5px; 11 | } 12 | div#buttons { 13 | border-bottom: 1px solid #eee; 14 | margin: 0 0 20px 0; 15 | } 16 | div#states { 17 | border-bottom: 1px solid #eee; 18 | } 19 | div#states > div { 20 | margin: 0 0 20px 0; 21 | min-height: 24px; /* to cope with Unicode character size :^| */ 22 | } 23 | div.label { 24 | display: inline-block; 25 | font-weight: 400; 26 | width: 111px; 27 | } 28 | div.value { 29 | display: inline-block; 30 | } 31 | video { 32 | margin: 0 0 20px 0; 33 | --width: 45%; 34 | width: var(--width); 35 | height: calc(var(--width) * 0.75); 36 | } 37 | video#video1 { 38 | margin: 0 20px 20px 0; 39 | } 40 | 41 | @media screen and (min-width: 730px) { 42 | video { 43 | height: 231px; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /src/content/peerconnection/states/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Peer connection: states 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

WebRTC samples Peer connection: states 37 |

38 | 39 | 40 | 41 | 42 |
43 | 44 | 45 | 46 |
47 | 48 |
49 |
50 |
PC1 state:
51 |
52 |
53 |
54 |
PC1 ICE state:
55 |
56 |
57 |
58 |
PC2 state:
59 |
60 |
61 |
62 |
PC2 ICE state:
63 |
64 |
65 |
66 | 67 |

View the console to see logging. The MediaStream object localStream, and the RTCPeerConnection 68 | objects localPeerConnection and remotePeerConnection are in global scope, so you can 69 | inspect them in the console as well.

70 | 71 |

For more information about RTCPeerConnection, see Getting 73 | Started With WebRTC.

74 | 75 | 76 | View source on GitHub 78 | 79 |
80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | -------------------------------------------------------------------------------- /src/content/peerconnection/trickle-ice/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 20px 10px 0 0; 10 | width: 130px; 11 | } 12 | button#gather { 13 | display: block; 14 | } 15 | section#iceServers input { 16 | margin: 0 0 10px; 17 | width: 260px; 18 | } 19 | section#iceConstraints label { 20 | margin: 0 1em 0 0; 21 | } 22 | section#iceServers label { 23 | display: inline-block; 24 | width: 150px; 25 | } 26 | 27 | section#iceOptions label { 28 | display: inline-block; 29 | width: 200px; 30 | } 31 | 32 | select#servers { 33 | font-size: 1em; 34 | padding: 5px; 35 | width: 420px; 36 | } 37 | div#iceTransports span { 38 | margin: 0 1em 0 0; 39 | } 40 | table#candidates { 41 | font-size: 0.7em; 42 | overflow-y: auto; 43 | text-align: right; 44 | width: 100%; 45 | } 46 | th { 47 | font-weight: bold; 48 | } 49 | th:nth-child(3),td:nth-child(3) { 50 | text-align: left 51 | } 52 | th:nth-child(6),td:nth-child(6) { 53 | text-align: left 54 | } 55 | 56 | .gray { 57 | color: gray 58 | } 59 | 60 | #poolValue { 61 | display: inline-block; 62 | width: 30px 63 | } 64 | 65 | #getUserMediaPermissions { 66 | display: none; 67 | } 68 | -------------------------------------------------------------------------------- /src/content/peerconnection/trickle-ice/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | /* eslint-env node */ 9 | 'use strict'; 10 | export default { 11 | 'Checking that the ICE candidates are populated when the button is pressed.': (browser) => { 12 | const path = '/src/content/peerconnection/trickle-ice/index.html'; 13 | const url = 'file://' + process.cwd() + path; 14 | 15 | browser.url(url).waitForElementVisible('#gather', 1000, 'Check that the gather candidate button is visible'); 16 | browser.expect.element('tbody#candidatesBody tr:first-child').to.not.be.present.before(100); 17 | browser.click('#gather'); 18 | browser.expect.element('tbody#candidatesBody tr:first-child').to.be.visible.before(5000); 19 | browser.end(); 20 | } 21 | }; 22 | -------------------------------------------------------------------------------- /src/content/peerconnection/upgrade/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 20px 0 0; 10 | width: 83px; 11 | } 12 | 13 | button#hangupButton { 14 | margin: 0; 15 | } 16 | 17 | video { 18 | --width: 45%; 19 | width: var(--width); 20 | height: calc(var(--width) * 0.75); 21 | margin: 0 0 20px 0; 22 | vertical-align: top; 23 | } 24 | 25 | video#localVideo { 26 | margin: 0 20px 20px 0; 27 | } 28 | 29 | @media screen and (max-width: 400px) { 30 | button { 31 | width: 83px; 32 | margin: 0 11px 10px 0; 33 | } 34 | 35 | video { 36 | height: 90px; 37 | margin: 0 0 10px 0; 38 | width: calc(50% - 7px); 39 | } 40 | video#localVideo { 41 | margin: 0 10px 20px 0; 42 | } 43 | 44 | } 45 | -------------------------------------------------------------------------------- /src/content/peerconnection/upgrade/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Peer connection - upgrade 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 |

WebRTC samples 36 | Peer connection

37 | 38 | 39 | 40 | 41 |
42 | 43 | 44 | 45 | 46 |
47 | 48 |

View the console to see logging. The MediaStream object localStream, and the RTCPeerConnection 49 | objects pc1 and pc2 are in global scope, so you can inspect them in the console as 50 | well.

51 | 52 |

For more information about RTCPeerConnection, see Getting 54 | Started With WebRTC.

55 | 56 | 57 | View source on GitHub 59 | 60 |
61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | -------------------------------------------------------------------------------- /src/content/peerconnection/upgrade/test/test.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | /* eslint-env node */ 9 | 'use strict'; 10 | export default { 11 | 'Checking that video is enabled when call is upgraded': (browser) => { 12 | const path = '/src/content/peerconnection/upgrade/index.html'; 13 | const url = 'file://' + process.cwd() + path; 14 | 15 | browser.url(url).waitForElementVisible('#startButton', 1000, 'Check that the start button is visible'); 16 | browser.expect.element('#callButton').to.not.be.enabled.before(1000); 17 | browser.expect.element('#upgradeButton').to.not.be.enabled.before(1000); 18 | browser.expect.element('#hangupButton').to.not.be.enabled.before(1000); 19 | browser.waitForReadyState('#localVideo', 0, 1000); 20 | browser.waitForReadyState('#remoteVideo', 0, 1000); 21 | browser.click('#startButton'); 22 | browser.expect.element('#startButton').to.not.be.enabled.before(1000); 23 | browser.expect.element('#callButton').to.be.enabled.before(1000); 24 | browser.expect.element('#upgradeButton').to.not.be.enabled.before(1000); 25 | browser.expect.element('#hangupButton').to.not.be.enabled.before(1000); 26 | browser.click('#callButton'); 27 | browser.expect.element('#startButton').to.not.be.enabled.before(1000); 28 | browser.expect.element('#callButton').to.not.be.enabled.before(1000); 29 | browser.expect.element('#upgradeButton').to.be.enabled.before(1000); 30 | browser.expect.element('#hangupButton').to.be.enabled.before(1000); 31 | browser.click('#upgradeButton'); 32 | browser.waitForReadyState('#localVideo', 4, 5000); 33 | browser.waitForReadyState('#remoteVideo', 4, 5000); 34 | browser.expect.element('#startButton').to.not.be.enabled.before(1000); 35 | browser.expect.element('#callButton').to.not.be.enabled.before(1000); 36 | browser.expect.element('#upgradeButton').to.not.be.enabled.before(1000); 37 | browser.expect.element('#hangupButton').to.be.enabled.before(1000); 38 | browser.click('#hangupButton'); 39 | browser.expect.element('#startButton').to.not.be.enabled.before(1000); 40 | browser.expect.element('#callButton').to.be.enabled.before(1000); 41 | browser.expect.element('#upgradeButton').to.not.be.enabled.before(1000); 42 | browser.expect.element('#hangupButton').to.not.be.enabled.before(1000); 43 | browser.end(); 44 | } 45 | }; 46 | -------------------------------------------------------------------------------- /src/content/peerconnection/webaudio-input/audio/Shamisen-C4.wav: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/content/peerconnection/webaudio-input/audio/Shamisen-C4.wav -------------------------------------------------------------------------------- /src/content/peerconnection/webaudio-input/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | audio { 10 | margin: 0 0 20px 0; 11 | width: 50%; 12 | } 13 | 14 | button { 15 | margin: 0 20px 20px 0; 16 | width: 89px; 17 | } 18 | 19 | div#options { 20 | margin: 0 0 20px 0; 21 | } 22 | 23 | div#status { 24 | background-color: #eee; 25 | margin: 0 0 20px 0; 26 | min-height: 140px; 27 | overflow-y: scroll; 28 | padding: 0 0 0 10px; 29 | width: 50%; 30 | } 31 | 32 | input[type='checkbox'] { 33 | margin: 0 10px 0 0; 34 | position: relative; 35 | top: -2px; 36 | } 37 | 38 | label { 39 | font-weight: 400; 40 | } 41 | 42 | li { 43 | margin: 0 0 10px 0; 44 | } 45 | 46 | ul { 47 | list-style-type: square; 48 | padding: 0 0 0 18px; 49 | } 50 | -------------------------------------------------------------------------------- /src/content/peerconnection/webaudio-input/js/webaudioextended.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | 'use strict'; 10 | 11 | // WebAudioExtended helper class which takes care of the WebAudio related parts. 12 | 13 | function WebAudioExtended() { 14 | window.AudioContext = window.AudioContext || window.webkitAudioContext; 15 | /* global AudioContext */ 16 | this.context = new AudioContext(); 17 | this.soundBuffer = null; 18 | } 19 | 20 | WebAudioExtended.prototype.start = function() { 21 | this.filter = this.context.createBiquadFilter(); 22 | this.filter.type = 'highpass'; 23 | this.filter.frequency.setValueAtTime(1500, this.context.currentTime + 1); 24 | }; 25 | 26 | WebAudioExtended.prototype.applyFilter = function(stream) { 27 | this.mic = this.context.createMediaStreamSource(stream); 28 | this.mic.connect(this.filter); 29 | this.peer = this.context.createMediaStreamDestination(); 30 | this.filter.connect(this.peer); 31 | return this.peer.stream; 32 | }; 33 | 34 | WebAudioExtended.prototype.renderLocally = function(enabled) { 35 | if (enabled) { 36 | this.mic.connect(this.context.destination); 37 | } else { 38 | this.mic.disconnect(0); 39 | this.mic.connect(this.filter); 40 | } 41 | }; 42 | 43 | WebAudioExtended.prototype.stop = function() { 44 | this.mic.disconnect(0); 45 | this.filter.disconnect(0); 46 | this.mic = null; 47 | this.peer = null; 48 | }; 49 | 50 | WebAudioExtended.prototype.addEffect = function() { 51 | let effect = this.context.createBufferSource(); 52 | effect.buffer = this.soundBuffer; 53 | if (this.peer) { 54 | effect.connect(this.peer); 55 | effect.start(0); 56 | } 57 | }; 58 | 59 | WebAudioExtended.prototype.loadCompleted = function() { 60 | this.context.decodeAudioData(this.request.response, function(buffer) { 61 | this.soundBuffer = buffer; 62 | }.bind(this)); 63 | }; 64 | 65 | WebAudioExtended.prototype.loadSound = function(url) { 66 | this.request = new XMLHttpRequest(); 67 | this.request.open('GET', url, true); 68 | this.request.responseType = 'arraybuffer'; 69 | this.request.onload = this.loadCompleted.bind(this); 70 | this.request.send(); 71 | }; 72 | -------------------------------------------------------------------------------- /src/content/peerconnection/webaudio-output/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | button { 10 | margin: 0 20px 0 0; 11 | width: 83px; 12 | } 13 | 14 | button#hangupButton { 15 | margin: 0; 16 | } 17 | 18 | canvas { 19 | background-color: #666; 20 | vertical-align: top; 21 | --width: 45%; 22 | width: var(--width); 23 | height: calc(var(--width) * 0.75); 24 | } 25 | 26 | video { 27 | --width: 45%; 28 | width: var(--width); 29 | height: calc(var(--width) * 0.75); 30 | margin: 0 20px 20px 0; 31 | } 32 | 33 | video#remoteVideo { 34 | display: none; 35 | } 36 | 37 | @media screen and (max-width: 400px) { 38 | button { 39 | margin: 0 11px 10px 0; 40 | width: 83px; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /src/content/peerconnection/webaudio-output/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Peer connection as input to Web Audio 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 |

WebRTC samples Peer connection as input to Web Audio 37 |

38 | 39 | 40 | 41 | 42 | 43 | 44 |
45 | 46 | 47 | 48 |
49 | 50 |

View the console to see logging. The MediaStream object localStream, and the RTCPeerConnection 51 | objects localPeerConnection and remotePeerConnection are in global scope, so you can 52 | inspect them in the console as well.

53 | 54 |

For more information about RTCPeerConnection, see Getting 56 | Started With WebRTC.

57 | 58 | 59 | View source on GitHub 61 | 62 |
63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | -------------------------------------------------------------------------------- /src/content/wasm/audioctx/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 1em 1em 0; 10 | width: 90px; 11 | } 12 | div#buttons { 13 | margin: 0 0 1em 0; 14 | } 15 | div#send { 16 | margin: 0 20px 1em 0; 17 | } 18 | div#sendReceive { 19 | border-bottom: 1px solid #eee; 20 | margin: 0; 21 | padding: 0 0 10px 0; 22 | } 23 | div#sendReceive > div { 24 | display: inline-block; 25 | width: calc(50% - 20px); 26 | } 27 | form { 28 | margin: 0 0 1em 0; 29 | white-space: nowrap; 30 | } 31 | form span { 32 | font-weight: 300; 33 | margin: 0 1em 0 0; 34 | white-space: normal; 35 | } 36 | textarea { 37 | color: #444; 38 | font-size: 0.9em; 39 | font-weight: 300; 40 | height: 7.0em; 41 | padding: 5px; 42 | width: calc(100% - 10px); 43 | } 44 | 45 | video, canvas { 46 | --width: 45%; 47 | width: var(--width); 48 | height: calc(var(--width) * 0.75); 49 | margin: 0 0 20px 0; 50 | vertical-align: top; 51 | } 52 | #localCanvas { 53 | display: none; 54 | } 55 | -------------------------------------------------------------------------------- /src/content/wasm/audioctx/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Transmit text 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 |
38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /src/content/wasm/audioctx/js/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const framesPerPacket = 2048; 3 | const buffer = []; 4 | 5 | const pc1 = new RTCPeerConnection(); 6 | const pc2 = new RTCPeerConnection(); 7 | pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate); 8 | pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate); 9 | let receiveChannel; 10 | navigator.mediaDevices.getUserMedia({audio: true}) 11 | .then(stream => { 12 | localVideo.srcObject = stream; 13 | 14 | const sendChannel = pc1.createDataChannel('sendDataChannel'); 15 | sendChannel.binaryType = 'arraybuffer'; 16 | let receiveChannel; 17 | const recvBuffer = []; 18 | pc2.ontrack = (e) => remoteVideo2.srcObject = e.streams[0]; 19 | pc1.createOffer() 20 | .then(offer => { 21 | return pc2.setRemoteDescription(offer) 22 | .then(() => pc1.setLocalDescription(offer)); 23 | }) 24 | .then(() => pc2.createAnswer()) 25 | .then(answer => { 26 | return pc1.setRemoteDescription(answer) 27 | .then(() => pc2.setLocalDescription(answer)); 28 | }) 29 | .catch(e => console.error(e)); 30 | 31 | 32 | const audioCtx = new AudioContext(); 33 | const source = audioCtx.createMediaStreamSource(stream); 34 | // var processor = audioCtx.createScriptProcessor(framesPerPacket, 2, 2); 35 | const processor = audioCtx.createScriptProcessor(framesPerPacket, 1, 1); 36 | source.connect(processor); 37 | processor.onaudioprocess = function (e) { 38 | if (sendChannel.readyState !== 'open') return; 39 | const channelData = e.inputBuffer.getChannelData(0); 40 | sendChannel.send(channelData); 41 | }; 42 | 43 | // Receiving end. 44 | pc2.ondatachannel = e => { 45 | receiveChannel = e.channel; 46 | receiveChannel.binaryType = 'arraybuffer'; 47 | receiveChannel.onmessage = (ev) => { 48 | const data = new Float32Array(ev.data); 49 | buffer.push(data); 50 | bytesReceived += ev.data.byteLength; 51 | }; 52 | }; 53 | 54 | // Playback, hacky, using script processor 55 | const destination = audioCtx.createMediaStreamDestination(); 56 | document.querySelector("#remoteVideo").srcObject = destination.stream; 57 | const playbackProcessor = audioCtx.createScriptProcessor(framesPerPacket, 1, 1); 58 | const oscillator = audioCtx.createOscillator(); 59 | oscillator.type = 'square'; 60 | oscillator.frequency.setValueAtTime(440, audioCtx.currentTime); // value in hertz 61 | oscillator.connect(playbackProcessor).connect(audioCtx.destination); 62 | playbackProcessor.onaudioprocess = function (e) { 63 | const data = buffer.shift(); 64 | if (!data) { 65 | return; 66 | } 67 | const outputBuffer = e.outputBuffer; 68 | const channel1 = outputBuffer.getChannelData(0); 69 | for(let i=0; i < framesPerPacket; i++) { 70 | channel1[i] = data[i]; 71 | } 72 | }; 73 | oscillator.start(); 74 | 75 | // measure bitrate. 76 | let bytesReceived = 0; 77 | let lastTime = Date.now(); 78 | setInterval(() => { 79 | const now = Date.now(); 80 | console.log('bitrate', Math.floor(8000.0 * bytesReceived / (now - lastTime))); 81 | bytesReceived = 0; 82 | lastTime = now; 83 | }, 1000); 84 | }); 85 | -------------------------------------------------------------------------------- /src/content/wasm/libvpx/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 1em 1em 0; 10 | width: 90px; 11 | } 12 | div#buttons { 13 | margin: 0 0 1em 0; 14 | } 15 | div#send { 16 | margin: 0 20px 1em 0; 17 | } 18 | div#sendReceive { 19 | border-bottom: 1px solid #eee; 20 | margin: 0; 21 | padding: 0 0 10px 0; 22 | } 23 | div#sendReceive > div { 24 | display: inline-block; 25 | width: calc(50% - 20px); 26 | } 27 | form { 28 | margin: 0 0 1em 0; 29 | white-space: nowrap; 30 | } 31 | form span { 32 | font-weight: 300; 33 | margin: 0 1em 0 0; 34 | white-space: normal; 35 | } 36 | textarea { 37 | color: #444; 38 | font-size: 0.9em; 39 | font-weight: 300; 40 | height: 7.0em; 41 | padding: 5px; 42 | width: calc(100% - 10px); 43 | } 44 | 45 | video, canvas { 46 | --width: 45%; 47 | width: var(--width); 48 | height: calc(var(--width) * 0.75); 49 | margin: 0 0 20px 0; 50 | vertical-align: top; 51 | } 52 | #localCanvas { 53 | display: none; 54 | } 55 | -------------------------------------------------------------------------------- /src/content/wasm/libvpx/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | WebAssembly and libVPX 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 | 37 | 38 |
39 | 40 | 41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | -------------------------------------------------------------------------------- /src/content/wasm/webp/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 1em 1em 0; 10 | width: 90px; 11 | } 12 | div#buttons { 13 | margin: 0 0 1em 0; 14 | } 15 | div#send { 16 | margin: 0 20px 1em 0; 17 | } 18 | div#sendReceive { 19 | border-bottom: 1px solid #eee; 20 | margin: 0; 21 | padding: 0 0 10px 0; 22 | } 23 | div#sendReceive > div { 24 | display: inline-block; 25 | width: calc(50% - 20px); 26 | } 27 | form { 28 | margin: 0 0 1em 0; 29 | white-space: nowrap; 30 | } 31 | form span { 32 | font-weight: 300; 33 | margin: 0 1em 0 0; 34 | white-space: normal; 35 | } 36 | textarea { 37 | color: #444; 38 | font-size: 0.9em; 39 | font-weight: 300; 40 | height: 7.0em; 41 | padding: 5px; 42 | width: calc(100% - 10px); 43 | } 44 | 45 | video, canvas { 46 | --width: 45%; 47 | width: var(--width); 48 | height: calc(var(--width) * 0.75); 49 | margin: 0 0 20px 0; 50 | vertical-align: top; 51 | } 52 | #localCanvas { 53 | display: none; 54 | } 55 | -------------------------------------------------------------------------------- /src/content/wasm/webp/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Encode using libwebp 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 | 36 | 37 | 38 |
39 | 40 | 41 |
42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | -------------------------------------------------------------------------------- /src/content/wasm/webp/js/libwebp.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | 9 | /* More information about these options at jshint.com/docs/options */ 10 | 11 | /* globals trace, mergeConstraints, parseJSON */ 12 | 13 | /* exported LibWebP */ 14 | 15 | 'use strict'; 16 | 17 | var LibWebP = function() { 18 | const src = '../../../wasm/libwebp/a.out.js'; 19 | console.warn('loading wasm module:', src); 20 | const script = document.createElement('script'); 21 | script.src = src; 22 | 23 | script.onerror = () => { 24 | console.warn('failed to load the script'); 25 | }; 26 | 27 | script.onload = () => { 28 | console.log('script loaded, waiting for wasm...'); 29 | 30 | Module.onRuntimeInitialized = () => { 31 | console.warn('libwebp.version', '0x' + _version().toString(16)); 32 | }; 33 | }; 34 | 35 | document.body.appendChild(script); 36 | }; 37 | 38 | LibWebP.prototype.encode = function(image) { 39 | const sourcePtr = Module._create_buffer(image.width, image.height); 40 | Module.HEAP8.set(image.data, sourcePtr); 41 | 42 | const quality = 100; 43 | Module._encode(sourcePtr, image.width, image.height, quality); 44 | Module._destroy_buffer(sourcePtr); 45 | 46 | const resultPtr = Module._get_result_pointer(); 47 | const resultSize = Module._get_result_size(); 48 | const resultView = new Uint8Array(Module.HEAP8.buffer, resultPtr, resultSize); 49 | const result = new Uint8Array(resultView); 50 | Module._free_result(resultPtr); 51 | 52 | return result; 53 | }; 54 | 55 | LibWebP.prototype.decode = function(buffer) { 56 | const size = buffer.length; 57 | const sourcePtr = Module._create_buffer(size, 1); 58 | Module.HEAP8.set(buffer, sourcePtr); 59 | Module._decode(sourcePtr, size); 60 | Module._destroy_buffer(sourcePtr); 61 | 62 | const resultPtr = Module._get_result_pointer(); 63 | if (!resultPtr) throw new Error('Invalid LibWebP image.'); 64 | 65 | const width = Module._get_result_width(); 66 | const height = Module._get_result_height(); 67 | const resultView = new Uint8Array(Module.HEAP8.buffer, resultPtr, width*height*4); 68 | const result = new Uint8Array(resultView); 69 | Module._free_result(resultPtr); 70 | 71 | return {data:result, width, height}; 72 | }; 73 | -------------------------------------------------------------------------------- /src/content/wasm/webp/js/main.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | const localContext = localCanvas.getContext('2d'); 3 | const remoteContext = remoteCanvas.getContext('2d'); 4 | 5 | const libwebp = new LibWebP(); 6 | navigator.mediaDevices.getUserMedia({video: {width: 320, height: 240}}) 7 | .then(stream => { 8 | const pc1 = new RTCPeerConnection(); 9 | const pc2 = new RTCPeerConnection(); 10 | pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate); 11 | pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate); 12 | const sendChannel = pc1.createDataChannel('sendDataChannel'); 13 | sendChannel.binaryType = 'arraybuffer'; 14 | pc1.addTrack(stream.getTracks()[0], stream); 15 | let receiveChannel; 16 | const recvBuffer = []; 17 | pc2.ondatachannel = e => { 18 | receiveChannel = e.channel; 19 | receiveChannel.binaryType = 'arraybuffer'; 20 | receiveChannel.onmessage = (ev) => { 21 | const encoded = new Uint8Array(ev.data); 22 | const {data, width, height} = libwebp.decode(encoded); 23 | const frame = remoteContext.createImageData(width, height); 24 | frame.data.set(data, 0); 25 | remoteContext.putImageData(frame, 0, 0); 26 | }; 27 | }; 28 | pc2.ontrack = (e) => remoteVideo2.srcObject = e.streams[0]; 29 | pc1.createOffer() 30 | .then(offer => { 31 | return pc2.setRemoteDescription(offer) 32 | .then(() => pc1.setLocalDescription(offer)); 33 | }) 34 | .then(() => pc2.createAnswer()) 35 | .then(answer => { 36 | return pc1.setRemoteDescription(answer) 37 | .then(() => pc2.setLocalDescription(answer)); 38 | }) 39 | .catch(e => console.error(e)); 40 | 41 | 42 | localVideo.srcObject = stream; 43 | localVideo2.srcObject = stream; 44 | const width = 320; 45 | const height = 240; 46 | 47 | localCanvas.width = width; 48 | localCanvas.height = height; 49 | remoteCanvas.width = width; 50 | remoteCanvas.height = height; 51 | 52 | let bytesSent = 0; 53 | let frames = 0; 54 | let lastTime = Date.now(); 55 | const fps = 30; 56 | setInterval(() => { 57 | localContext.drawImage(localVideo, 0, 0, width, height); 58 | const frame = localContext.getImageData(0, 0, width, height); 59 | const encoded = libwebp.encode(frame); 60 | sendChannel.send(encoded); // 320x240 fits a single 65k frame. 61 | bytesSent += encoded.length; 62 | frames++; 63 | }, 1000.0 / fps); 64 | setInterval(() => { 65 | const now = Date.now(); 66 | console.log('bitrate', Math.floor(8000.0 * bytesSent / (now - lastTime)), 67 | 'fps', Math.floor(1000.0 * frames / (now - lastTime))); 68 | bytesSent = 0; 69 | frames = 0; 70 | lastTime = now; 71 | }, 1000); 72 | }); 73 | -------------------------------------------------------------------------------- /src/content/wasm/webrtc/css/main.css: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | button { 9 | margin: 0 20px 0 0; 10 | width: 83px; 11 | } 12 | 13 | button#hangupButton { 14 | margin: 0; 15 | } 16 | 17 | video { 18 | --width: 45%; 19 | width: var(--width); 20 | height: calc(var(--width) * 0.75); 21 | margin: 0 0 20px 0; 22 | vertical-align: top; 23 | } 24 | 25 | video#localVideo { 26 | margin: 0 20px 20px 0; 27 | } 28 | 29 | div.box { 30 | margin: 1em; 31 | } 32 | 33 | @media screen and (max-width: 400px) { 34 | button { 35 | width: 83px; 36 | margin: 0 11px 10px 0; 37 | } 38 | 39 | video { 40 | height: 90px; 41 | margin: 0 0 10px 0; 42 | width: calc(50% - 7px); 43 | } 44 | video#localVideo { 45 | margin: 0 10px 20px 0; 46 | } 47 | 48 | } 49 | -------------------------------------------------------------------------------- /src/content/wasm/webrtc/index.html: -------------------------------------------------------------------------------- 1 | 2 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | Peer connection 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 |
35 |

WebRTC samples 36 | Peer connection

37 | 38 |

This sample shows how to setup a connection between two peers using 39 | RTCPeerConnection. 40 | An option to specify the SDP semantics for 41 | the connection is also available (unified-plan, plan-b or default). 42 |

43 | 44 | 45 | 46 | 47 |
48 | 49 | 50 | 51 |
52 | 53 |
54 | SDP Semantics: 55 | 60 |
61 | 62 |

View the console to see logging. The MediaStream object localStream, and the RTCPeerConnection 63 | objects pc1 and pc2 are in global scope, so you can inspect them in the console as 64 | well.

65 | 66 |

For more information about RTCPeerConnection, see Getting 68 | Started With WebRTC.

69 | 70 | 71 | View source on GitHub 73 | 74 |
75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | -------------------------------------------------------------------------------- /src/images/webrtc-icon-192x192.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/images/webrtc-icon-192x192.png -------------------------------------------------------------------------------- /src/js/lib/ga.js: -------------------------------------------------------------------------------- 1 | (function(i, s, o, g, r, a, m) { 2 | i['GoogleAnalyticsObject']=r; i[r]=i[r]||function() { 3 | (i[r].q=i[r].q||[]).push(arguments); 4 | }, i[r].l=1*new Date(); a=s.createElement(o), 5 | m=s.getElementsByTagName(o)[0]; a.async=1; a.src=g; m.parentNode.insertBefore(a, m); 6 | })(window, document, 'script', '//www.google-analytics.com/analytics.js', 'ga'); 7 | 8 | ga('create', 'UA-48530561-1', 'auto'); 9 | ga('send', 'pageview'); 10 | -------------------------------------------------------------------------------- /src/js/third_party/webgl_teapot/images/bump.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/js/third_party/webgl_teapot/images/bump.jpg -------------------------------------------------------------------------------- /src/js/third_party/webgl_teapot/images/skybox-negx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/js/third_party/webgl_teapot/images/skybox-negx.jpg -------------------------------------------------------------------------------- /src/js/third_party/webgl_teapot/images/skybox-negy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/js/third_party/webgl_teapot/images/skybox-negy.jpg -------------------------------------------------------------------------------- /src/js/third_party/webgl_teapot/images/skybox-negz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/js/third_party/webgl_teapot/images/skybox-negz.jpg -------------------------------------------------------------------------------- /src/js/third_party/webgl_teapot/images/skybox-posx.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/js/third_party/webgl_teapot/images/skybox-posx.jpg -------------------------------------------------------------------------------- /src/js/third_party/webgl_teapot/images/skybox-posy.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/js/third_party/webgl_teapot/images/skybox-posy.jpg -------------------------------------------------------------------------------- /src/js/third_party/webgl_teapot/images/skybox-posz.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/js/third_party/webgl_teapot/images/skybox-posz.jpg -------------------------------------------------------------------------------- /src/js/videopipe.js: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2015 The WebRTC project authors. All Rights Reserved. 3 | * 4 | * Use of this source code is governed by a BSD-style license 5 | * that can be found in the LICENSE file in the root of the source 6 | * tree. 7 | */ 8 | // 9 | // A "videopipe" abstraction on top of WebRTC. 10 | // 11 | // The usage of this abstraction: 12 | // var pipe = new VideoPipe(mediastream, handlerFunction); 13 | // handlerFunction = function(mediastream) { 14 | // do_something 15 | // } 16 | // pipe.close(); 17 | // 18 | // The VideoPipe will set up 2 PeerConnections, connect them to each 19 | // other, and call HandlerFunction when the stream is available in the 20 | // second PeerConnection. 21 | // 22 | 23 | function errorHandler(context) { 24 | return function(error) { 25 | trace('Failure in ' + context + ': ' + error.toString); 26 | }; 27 | } 28 | 29 | // eslint-disable-next-line no-unused-vars 30 | function successHandler(context) { 31 | return function() { 32 | trace('Success in ' + context); 33 | }; 34 | } 35 | 36 | function noAction() { 37 | } 38 | 39 | 40 | function VideoPipe(stream, handler) { 41 | let servers = null; 42 | let pc1 = new RTCPeerConnection(servers); 43 | let pc2 = new RTCPeerConnection(servers); 44 | 45 | pc1.addStream(stream); 46 | pc1.onicecandidate = function(event) { 47 | if (event.candidate) { 48 | pc2.addIceCandidate(new RTCIceCandidate(event.candidate), 49 | noAction, errorHandler('AddIceCandidate')); 50 | } 51 | }; 52 | pc2.onicecandidate = function(event) { 53 | if (event.candidate) { 54 | pc1.addIceCandidate(new RTCIceCandidate(event.candidate), 55 | noAction, errorHandler('AddIceCandidate')); 56 | } 57 | }; 58 | pc2.onaddstream = function(e) { 59 | handler(e.stream); 60 | }; 61 | pc1.createOffer(function(desc) { 62 | pc1.setLocalDescription(desc); 63 | pc2.setRemoteDescription(desc); 64 | pc2.createAnswer(function(desc2) { 65 | pc2.setLocalDescription(desc2); 66 | pc1.setRemoteDescription(desc2); 67 | }, errorHandler('pc2.createAnswer')); 68 | }, errorHandler('pc1.createOffer')); 69 | this.pc1 = pc1; 70 | this.pc2 = pc2; 71 | } 72 | 73 | VideoPipe.prototype.close = function() { 74 | this.pc1.close(); 75 | this.pc2.close(); 76 | }; 77 | -------------------------------------------------------------------------------- /src/video/chrome.mp4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/video/chrome.mp4 -------------------------------------------------------------------------------- /src/video/chrome.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/video/chrome.webm -------------------------------------------------------------------------------- /src/video/mixed-content.webm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/video/mixed-content.webm -------------------------------------------------------------------------------- /src/wasm/libvpx/libvpx.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/wasm/libvpx/libvpx.wasm -------------------------------------------------------------------------------- /src/wasm/libwebp/a.out.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/wasm/libwebp/a.out.wasm -------------------------------------------------------------------------------- /src/wasm/webrtc/fetch-worker.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/wasm/webrtc/fetch-worker.js -------------------------------------------------------------------------------- /src/wasm/webrtc/webrtc.js.mem: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/wasm/webrtc/webrtc.js.mem -------------------------------------------------------------------------------- /src/wasm/webrtc/webrtc.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/wasm/webrtc/webrtc.wasm -------------------------------------------------------------------------------- /src/wasm/webrtc/webrtc.wasm.map: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webrtcHacks/samples/6f3dda452bae504946aacbdcb090fd8c2d596fc6/src/wasm/webrtc/webrtc.wasm.map --------------------------------------------------------------------------------