{"id":13402632,"url":"https://github.com/ether/ep_webrtc","last_synced_at":"2026-04-02T02:18:47.502Z","repository":{"id":8991726,"uuid":"10740657","full_name":"ether/ep_webrtc","owner":"ether","description":"Audio \u0026 Video chat for Etherpad - Video Conferencing with a focus on collaboration","archived":false,"fork":false,"pushed_at":"2026-03-12T12:04:11.000Z","size":956,"stargazers_count":75,"open_issues_count":7,"forks_count":25,"subscribers_count":7,"default_branch":"main","last_synced_at":"2026-03-30T15:27:50.907Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ether.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2013-06-17T15:34:46.000Z","updated_at":"2026-03-12T12:04:15.000Z","dependencies_parsed_at":"2023-02-16T18:25:26.148Z","dependency_job_id":"f7e64704-1da2-4c2a-97a4-85e0a72f6694","html_url":"https://github.com/ether/ep_webrtc","commit_stats":{"total_commits":627,"total_committers":17,"mean_commits":36.88235294117647,"dds":0.5805422647527911,"last_synced_commit":"b3e41096ee094d4bdf244ca0878a749bd4f65f8e"},"previous_names":[],"tags_count":140,"template":false,"template_full_name":null,"purl":"pkg:github/ether/ep_webrtc","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ether%2Fep_webrtc","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ether%2Fep_webrtc/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ether%2Fep_webrtc/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ether%2Fep_webrtc/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ether","download_url":"https://codeload.github.com/ether/ep_webrtc/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ether%2Fep_webrtc/sbom","scorecard":{"id":383908,"data":{"date":"2025-08-11","repo":{"name":"github.com/ether/ep_webrtc","commit":"c225251776a256b21386d49153409781eff5e06c"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.2,"checks":[{"name":"Maintained","score":2,"reason":"3 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 2","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/codeql.yml:1","Warn: no topLevel permission defined: .github/workflows/test-and-release.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Code-Review","score":0,"reason":"Found 0/15 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: third-party GitHubAction not pinned by hash: .github/workflows/codeql.yml:14: update your workflow using https://app.stepsecurity.io/secureworkflow/ether/ep_webrtc/codeql.yml/main?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/test-and-release.yml:6: update your workflow using https://app.stepsecurity.io/secureworkflow/ether/ep_webrtc/test-and-release.yml/main?enable=pin","Info:   0 out of   2 third-party GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: Apache License 2.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'main'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 15 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":5,"reason":"5 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-v6h2-p8h4-qcjw","Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg","Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275","Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv","Warn: Project is vulnerable to: GHSA-76p7-773f-r4q5"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-18T16:08:08.789Z","repository_id":8991726,"created_at":"2025-08-18T16:08:08.789Z","updated_at":"2025-08-18T16:08:08.789Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31294527,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-02T01:43:37.129Z","status":"online","status_checked_at":"2026-04-02T02:00:08.535Z","response_time":89,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-07-30T19:01:18.583Z","updated_at":"2026-04-02T02:18:47.461Z","avatar_url":"https://github.com/ether.png","language":"JavaScript","readme":"![Publish Status](https://github.com/ether/ep_webrtc/workflows/Node.js%20Package/badge.svg) ![Backend Tests Status](https://github.com/ether/ep_webrtc/workflows/Backend%20tests/badge.svg)\n\n# ep_webrtc\n\nWebRTC-based audio/video chat and screen sharing with other users visiting the\nsame pad.\n\nThe audio and video streams are peer-to-peer: every user sends a copy of their\naudio/video streams directly to every other user visiting the same pad. Because\nof this, it works well for small groups (2 to 4 users, more if video is disabled\nor everyone has fast Internet connections) but not for large groups.\n\n## Installation\n\n* Option 1: Use the `/admin` interface, search for `ep_webrtc`, and click\n  Install.\n* Option 2:\n  ```shell\n  cd /path/to/etherpad\n  npm install --no-save --legacy-peer-deps ep_webrtc\n  ```\n* Option 3:\n  ```shell\n  cd /path/to/etherpad/node_modules\n  git clone https://github.com/ether/ep_webrtc\n  ```\n\n## Settings\n\n### Plugin On/Off\n\nIn the settings menu there is a toggle to turn the plugin on and off for the\nuser. When toggled, its state is saved in a cookie and applied when any pad is\nvisited. The value can also be changed by adding `av=true` or `av=false` to the\nURL query parameters.\n\nThe default value for this setting can be controlled in the server's\n`settings.json` file (it defaults to `true`):\n\n```json\n  \"ep_webrtc\": {\n    \"enabled\": true\n  }\n```\n\n### Video/Audio On/Off\n\nThe settings menu also contains separate toggles for starting video and audio\nsharing when the plugin is enabled. When toggled, their state is saved in a\ncookie and applied when any pad is visited. They can also be changed by adding\nthe following to the URL query parameters:\n\n* `webrtcaudioenabled=true`\n* `webrtcaudioenabled=false`\n* `webrtcvideoenabled=true`\n* `webrtcvideoenabled=false`\n\nThe default value can be controlled in the server's `settings.json` file:\n\n```json\n  \"ep_webrtc\": {\n    \"audio\": {\n      \"disabled\": \"none\"\n    },\n    \"video\": {\n      \"disabled\": \"none\"\n    }\n  }\n```\n\nSupported values for `\"disabled\"`:\n\n* `\"none\"` (the default): Initially enabled by default.\n* `\"soft\"`: Initially disabled by default.\n* `\"hard\"`: Unavailable (it cannot be enabled).\n\n### Custom Activate Button\n\nThe misnamed `listenClass` setting allows you to specify a CSS selector for an\nelement (or elements) that will activate the plugin when clicked. This is\nusually combined with `\"enabled\": false`. Example:\n\n```json\n  \"ep_webrtc\": {\n    \"enabled\": false,\n    \"listenClass\": \"#startVideoSessionButton\"\n  }\n```\n\n### ICE (STUN/TURN) Servers\n\nBy default, this plugin uses Google's STUN servers. To use custom STUN/TURN\nservers, set `ep_webrtc.iceServers` in your `settings.json` to a list of\n[RTCIceServer](https://developer.mozilla.org/en-US/docs/Web/API/RTCIceServer)\nobjects:\n\n```json\n  \"ep_webrtc\": {\n    \"iceServers\": [\n      {\"urls\": [\"stun:stun.l.google.com:19302\"]}\n    ]\n  }\n```\n\nInclude a TURN server to support users behind symmetric NAT devices. For\nexample:\n\n```json\n  \"ep_webrtc\": {\n    \"iceServers\": [\n      {\n        \"urls\": [\"stun:stun.l.google.com:19302\"]\n      },\n      {\n        \"urls\": [\"turn:turn.example.com:3478\"],\n        \"username\": \"the_username\",\n        \"credential\": \"the_password\"\n      }\n    ]\n  }\n```\n\n#### Ephemeral credentials\n\nTo limit abuse, the [coturn](https://github.com/coturn/coturn) TURN server\nsupports [ephemeral (temporary) usernames and\npasswords](https://github.com/coturn/coturn/blob/60e7a199fe748cb7080594a458d22c2f7bb15a8c/README.turnserver#L664-L729).\nTo take advantage of this feature, configure your TURN entry as follows:\n\n* `credentialType`: Must be set to the exact string `\"coturn ephemeral\n  password\"`.\n* `username`: Ignored. (The username that will be sent to the TURN server is\n  dynamically generated and based on the user's Etherpad-generated author ID.)\n* `credential`: Must be set to coturn's [`static-auth-secret`\n  setting](https://github.com/coturn/coturn/blob/60e7a199fe748cb7080594a458d22c2f7bb15a8c/README.turnserver#L445-L450).\n* `lifetime`: How long (in seconds) the password will remain valid after the\n  user visits a pad. After this amount of time, new TURN connections will fail\n  until the user reloads the page (which will generate a new password). Defaults\n  to 43200 (12 hours).\n\nExample:\n\n```json\n  \"ep_webrtc\": {\n    \"iceServers\": [\n      {\n        \"urls\": [\"stun:stun.l.google.com:19302\"]\n      },\n      {\n        \"urls\": [\"turn:coturn.example.com:3478\"],\n        \"credentialType\": \"coturn ephemeral password\",\n        \"credential\": \"your_coturn_secret\",\n        \"lifetime\": 3600\n      }\n    ]\n  },\n```\n\nThere is also support for ephemeral credentials from the\n[Xirsys](https://xirsys.com/) [API](https://docs.xirsys.com/?pg=api-turn):\n\n  * `credentialType` (required): Must be set to the exact string `\"xirsys\n    ephemeral credentials\"`.\n  * `url` (required): The desired Xirsys TURN API endpoint.\n  * `username` (required): Your Xirsys username.\n  * `credential` (required): Your Xirsys API secret.\n  * `lifetime` (optional; defaults to 43200 = 12 hours): How long (in seconds)\n    the ephemeral credentials will remain valid after the user visits a pad.\n    After this amount of time, new TURN connections will fail until the user\n    reloads the page (which will generate a new password).\n\nExample:\n\n```json\n  \"ep_webrtc\": {\n    \"iceServers\": [\n      {\n        \"credentialType\": \"xirsys ephemeral credentials\",\n        \"url\": \"https://global.xirsys.net/_turn/myChannel\",\n        \"username\": \"myUsername\",\n        \"credential\": \"myPassword\",\n        \"lifetime\": 3600\n      }\n    ]\n  },\n```\n\n#### Horizontally scaled TURN servers\n\nTo spread load across multiple TURN services, you can enable sharding:\n\n```json\n  \"ep_webrtc\": {\n    \"iceServers\": [\n      {\"urls\": [\"stun:shard0.example.com\", \"turn:shard0.example.com\"]},\n      {\"urls\": [\"stun:shard1.example.com\", \"turn:shard1.example.com\"]},\n      {\"urls\": [\"stun:shard2.example.com\", \"turn:shard2.example.com\"]},\n      {\"urls\": [\"stun:shard3.example.com\", \"turn:shard3.example.com\"]},\n    ],\n    \"shardIceServers\": true\n  },\n```\n\nWhen `shardIceServers` is `false` (the default), all clients receive all\nRTCIceServer objects in the `iceServers` list and it's up to the browser to\nfigure out how to use them to connect with peers. When `true`, this plugin\nassigns a single entry from `iceServers` to each pad and gives out only that\nassigned entry to users that connect to the pad. The intention is to provide a\nbetter guarantee of load distribution across a set of TURN servers, and to avoid\nan unnecessary network hop when both peers are configured to force the use of\nTURN.\n\n### Microphone Settings\n\nThe microphone can be configured by setting `audio.constraints` to any [audio\nconstraints](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#parameters)\nvalue acceptable to client browsers. It has the following default value:\n\n```json\n  \"ep_webrtc\": {\n    \"audio\": {\n      \"constraints\": {\n        \"autoGainControl\": {\"ideal\": true},\n        \"echoCancellation\": {\"ideal\": true},\n        \"noiseSuppression\": {\"ideal\": true}\n      }\n    }\n  },\n```\n\nFor a full list of available constraints, see [the\nstandard](https://www.w3.org/TR/2022/CRD-mediacapture-streams-20220307/#constrainable-properties).\n\n### Video Sizes\n\nThe camera's record resolution can be configured by setting `video.constraints`\nto any [video\nconstraints](https://developer.mozilla.org/en-US/docs/Web/API/MediaDevices/getUserMedia#parameters)\nvalue acceptable to client browsers. It has the following default value:\n\n```json\n  \"ep_webrtc\": {\n    \"video\": {\n      \"constraints\": {\n        \"width\": {\"ideal\": 160},\n        \"height\": {\"ideal\": 120}\n      }\n    }\n  },\n```\n\nFor a full list of available constraints, see [the\nstandard](https://www.w3.org/TR/2022/CRD-mediacapture-streams-20220307/#constrainable-properties).\n\nChanging the record resolution does not change the size of the displayed video\nwidgets. To change the video widget size, set `video.sizes.small` and/or\n`video.sizes.large`:\n\n```json\n  \"ep_webrtc\": {\n    \"video\": {\n      \"sizes\": {\n        \"small\": 200,\n        \"large\": 400\n      }\n    }\n  },\n```\n\n## Metrics\n\nYou can see metrics for various errors that users have when attempting to\nconnect their camera/microphone:\n\n* `ep_webrtc_err_Hardware`: Some sort of hardware-related connection problem on\n  the users' computer.\n* `ep_webrtc_err_NotFound`: Could not find user's camera/microphone.\n* `ep_webrtc_err_Abort`: Some sort of other, non-hardware related connection\n  problem on the user's computer.\n* `ep_webrtc_err_Permission`: User did not grant permission to their\n  camera/microphone.\n* `ep_webrtc_err_SecureConnection`: Etherpad is not set up on a secure\n  connection, which is requried for WebRTC.\n* `ep_webrtc_err_Unknown`: Some other unspecified error. Perhaps a bug in this\n  plugin.\n\n## Developing and contributing\n\n### Basic\n\nIf you're just working on the interface and don't need to test connections to\nother computers, you can point your browser to `localhost` instead of `0.0.0.0`.\nWebRTC generally requires a secure connection (https), but [an exception is\nmade](https://w3c.github.io/webappsec-secure-contexts/#localhost) specifically\nfor localhost and domains that end in `.localhost`.\n\n### Developing / Testing Communications\n\nIf you need to test communication, you may get away with opening two browser\nwindows to the same URL on `localhost`. However this may be of limited utility,\nespecially if you're confirming that sound works appropriately. In order to test\non two computers, you'll need your dev computer to serve on an IP address\naccessible from the other computer, at which point you will no longer get away\nwith using `localhost`. You will need SSL certs, though for dev purposes they\ncan be self-signed.\n\n[Generate your certificate](https://serverfault.com/a/224127), which will give\nyou your cert and key files. In `settings.js`, set the full path to them on your\nfile system:\n\n```json\n  \"ssl\": {\n    \"key\": \"/path-to-your/epl-server.key\",\n    \"cert\": \"/path-to-your/epl-server.crt\"\n    // \"ca\" - not needed for dev purposes\n  }\n```\n\nPoint your browser to your outward facing IP address, preceeded by `https://`,\nand accept the security warning (since this is a self-signed cert).\n\n### Bug Reports\n\nPlease submit bug reports or patches at\nhttps://github.com/ether/ep_webrtc/issues\n","funding_links":[],"categories":["JavaScript","others"],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fether%2Fep_webrtc","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fether%2Fep_webrtc","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fether%2Fep_webrtc/lists"}