# Technical Documentation: pion/webrtc

> ℹ️ **Provenance:** Multi-Tier Ingestion · [CodeWiki Reference](https://codewiki.google/github.com/pion/webrtc)

### Overview (`README.md`)

<h1 align="center">
  <a href="https://pion.ly"><img src="./.github/pion-gopher-webrtc.png" alt="Pion WebRTC" height="250px"></a>
  <br>
  Pion WebRTC
  <br>
</h1>
<h4 align="center">A pure Go implementation of the WebRTC API</h4>
<p align="center">
  <a href="https://pion.ly"><img src="https://img.shields.io/badge/pion-webrtc-gray.svg?longCache=true&colorB=brightgreen" alt="Pion WebRTC"></a>
  <a href="https://sourcegraph.com/github.com/pion/webrtc?badge"><img src="https://sourcegraph.com/github.com/pion/webrtc/-/badge.svg" alt="Sourcegraph Widget"></a>
  <a href="https://discord.gg/PngbdqpFbt"><img src="https://img.shields.io/badge/join-us%20on%20discord-gray.svg?longCache=true&logo=discord&colorB=brightblue" alt="join us on Discord"></a> <a href="https://bsky.app/profile/pion.ly"><img src="https://img.shields.io/badge/follow-us%20on%20bluesky-gray.svg?longCache=true&logo=bluesky&colorB=brightblue" alt="Follow us on Bluesky"></a> <a href="https://twitter.com/_pion?ref_src=twsrc%5Etfw"><img src="https://img.shields.io/twitter/url.svg?label=Follow%20%40_pion&style=social&url=https%3A%2F%2Ftwitter.com%2F_pion" alt="Twitter Widget"></a>
  <a href="https://github.com/pion/awesome-pion" alt="Awesome Pion"><img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg"></a>
  <br>
  <img alt="GitHub Workflow Status" src="https://img.shields.io/github/actions/workflow/status/pion/webrtc/test.yaml">
  <a href="https://pkg.go.dev/github.com/pion/webrtc/v4"><img src="https://pkg.go.dev/badge/github.com/pion/webrtc/v4.svg" alt="Go Reference"></a>
  <a href="https://codecov.io/gh/pion/webrtc"><img src="https://codecov.io/gh/pion/webrtc/branch/main/graph/badge.svg" alt="Coverage Status"></a>
  <a href="https://goreportcard.com/report/github.com/pion/webrtc/v4"><img src="https://goreportcard.com/badge/github.com/pion/webrtc/v4" alt="Go Report Card"></a>
  <a href="LICENSE"><img src="https://img.shields.io/badge/License-MIT-yellow.svg" alt="License: MIT"></a>
</p>
<br>

### New Release

Pion WebRTC v4.0.0 has been released! See the [release notes](https://github.com/pion/webrtc/wiki/Release-WebRTC@v4.0.0) to learn about new features and breaking changes.

If you aren't able to upgrade yet check the [tags](https://github.com/pion/webrtc/tags) for the latest `v3` release.

We would love your feedback! Please create GitHub issues or Join the [Discord](https://discord.gg/PngbdqpFbt) to follow development and speak with the maintainers.

-----

### Usage
[Go Modules](https://blog.golang.org/using-go-modules) are mandatory for using Pion WebRTC. So make sure you set `export GO111MODULE=on`, and explicitly specify `/v4` (or an earlier version) when importing.


**[example applications](examples/README.md)** contains code samples of common things people build with Pion WebRTC.

**[example-webrtc-applications](https://github.com/pion/example-webrtc-applications)** contains more full featured examples that use 3rd party libraries.

**[awesome-pion](https://github.com/pion/awesome-pion)** contains projects that have used Pion, and serve as real world examples of usage.

**[GoDoc](https://pkg.go.dev/github.com/pion/webrtc/v4)** is an auto generated API reference. All our Public APIs are commented.

**[FAQ](https://github.com/pion/webrtc/wiki/FAQ)** has answers to common questions. If you have a question not covered please ask in [Discord](https://discord.gg/PngbdqpFbt) we are always looking to expand it.

Now go build something awesome! Here are some **ideas** to get your creative juices flowing:
* Send a video file to multiple browser in real time for perfectly synchronized movie watching.
* Send a webcam on an embedded device to your browser with no additional server required!
* Securely send data between two servers, without using pub/sub.
* Record your webcam and do special effects server side.
* Build a conferencing application that processes audio/video and make decisions off of it.
* Remotely control a robots and stream its cameras in realtime.

### Need Help?
Check out [WebRTC for the Curious](https://webrtcforthecurious.com). A book about WebRTC in depth, not just about the APIs.
Learn the full details of ICE, SCTP, DTLS, SRTP, and how they work together to make up the WebRTC stack. This is also a great
resource if you are trying to debug. Learn the tools of the trade and how to approach WebRTC issues. This book is vendor
agnostic and will not have any Pion specific information.

Pion has an active community on [Discord](https://discord.gg/PngbdqpFbt). Please ask for help about anything, questions don't have to be Pion specific!
Come share your interesting project you are working on. We are here to support you.

One of the maintainers of Pion [Sean-Der](https://github.com/sean-der) is available to help. Schedule at [siobud.com/meeting](https://siobud.com/meeting)
He is available to talk about Pion or general WebRTC questions, feel free to reach out about anything!

### Features
#### PeerConnection API
* Go implementation of [webrtc-pc](https://w3c.github.io/webrtc-pc/) and [webrtc-stats](https://www.w3.org/TR/webrtc-stats/)
* DataChannels
* Send/Receive audio and video
* Renegotiation
* Plan-B and Unified Plan
* [SettingEngine](https://pkg.go.dev/github.com/pion/webrtc/v4#SettingEngine) for Pion specific extensions


#### Connectivity
* Full ICE Agent
* ICE Restart
* Trickle ICE
* STUN
* TURN (UDP, TCP, DTLS and TLS)
* mDNS candidates

#### DataChannels
* Ordered/Unordered
* Lossy/Lossless

#### Media
* API with direct RTP/RTCP access
* Opus, PCM, H264, VP8 and VP9 packetizer
* API also allows developer to pass their own packetizer
* IVF, Ogg, H264 and Matroska provided for easy sending and saving
* [getUserMedia](https://github.com/pion/mediadevices) implementation (Requires Cgo)
* Easy integration with x264, libvpx, GStreamer and ffmpeg.
* [Simulcast](https://github.com/pion/webrtc/tree/main/examples/simulcast)
* [SVC](https://github.com/pion/rtp/blob/main/codecs/vp9_packet.go#L138)
* [NACK](https://github.com/pion/interceptor/pull/4)
* [Sender/Receiver Reports](https://github.com/pion/interceptor/tree/main/pkg/report)
* [Transport Wide Congestion Control Feedback](https://github.com/pion/interceptor/tree/main/pkg/twcc)
* [Bandwidth Estimation](https://github.com/pion/webrtc/tree/main/examples/bandwidth-estimation-from-disk)

#### Security
* TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 and TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA for DTLS v1.2
* SRTP_AEAD_AES_256_GCM and SRTP_AES128_CM_HMAC_SHA1_80 for SRTP
* Hardware acceleration available for GCM suites

#### Pure Go
* No Cgo usage
* Wide platform support
  * Windows, macOS, Linux, FreeBSD
  * iOS, Android
  * [WASM](https://github.com/pion/webrtc/wiki/WebAssembly-Development-and-Testing) see [examples](examples/README.md#webassembly)
  *  386, amd64, arm, mips, ppc64
* Easy to build *Numbers generated on Intel(R) Core(TM) i5-2520M CPU @ 2.50GHz*
  * **Time to build examples/play-from-disk** - 0.66s user 0.20s system 306% cpu 0.279 total
  * **Time to run entire test suite** - 25.60s user 9.40s system 45% cpu 1:16.69 total
* Tools to measure performance [provided](https://github.com/pion/rtsp-bench)

### Roadmap
The library is in active development, please refer to the [roadmap](https://github.com/pion/webrtc/issues/9) to track our major milestones.
We also maintain a list of [Big Ideas](https://github.com/pion/webrtc/wiki/Big-Ideas) these are things we want to build but don't have a clear plan or the resources yet.
If you are looking to get involved this is a great place to get started! We would also love to hear your ideas! Even if you can't implement it yourself, it could inspire others.

### Sponsoring
Work on Pion's congestion control and bandwidth estimation was funded through the [User-Operated Internet](https://nlnet.nl/useroperated/) fund, a fund established by [NLnet](https://nlnet.nl/) made possible by financial support from the [PKT Community](https://pkt.cash/)/[The Network Steward](https://pkt.cash/network-steward) and stichting [Technology Commons Trust](https://technologycommons.org/).

### Community
Pion has an active community on the [Discord](https://discord.gg/PngbdqpFbt).

Follow the [Pion Bluesky](https://bsky.app/profile/pion.ly) or [Pion Twitter](https://twitter.com/_pion) for project updates and important WebRTC news.

We are always looking to support **your projects**. Please reach out if you have something to build!
If you need commercial support or don't want to use public methods you can contact us at [team@pion.ly](mailto:team@pion.ly)

### Contributing
Check out the [contributing wiki](https://github.com/pion/webrtc/wiki/Contributing) to join the group of amazing people making this project possible

### License
MIT License - see [LICENSE](LICENSE) for full text

---

### Overview (`examples/README.md`)

<h1 align="center">
  Examples
</h1>

We've built an extensive collection of examples covering common use-cases. You can modify and extend these examples to get started quickly.

For more full featured examples that use 3rd party libraries see our **[example-webrtc-applications](https://github.com/pion/example-webrtc-applications)** repo.

### Overview
#### Media API
* [Reflect](reflect): The reflect example demonstrates how to have Pion send back to the user exactly what it receives using the same PeerConnection.
* [Play from Disk](play-from-disk): The play-from-disk example demonstrates how to send video to your browser from a file saved to disk.
* [Play from Disk Renegotiation](play-from-disk-renegotiation): The play-from-disk-renegotiation example is an extension of the play-from-disk example, but demonstrates how you can add/remove video tracks from an already negotiated PeerConnection.
* [Insertable Streams](insertable-streams): The insertable-streams example demonstrates how Pion can be used to send E2E encrypted video and decrypt via insertable streams in the browser.
* [Save to Disk](save-to-disk): The save-to-disk example shows how to record your webcam and save the footage to disk on the server side.
* [Broadcast](broadcast): The broadcast example demonstrates how to broadcast a video to multiple peers. A broadcaster uploads the video once and the server forwards it to all other peers.
* [RTP Forwarder](rtp-forwarder): The rtp-forwarder example demonstrates how to forward your audio/video streams using RTP.
* [RTP to WebRTC](rtp-to-webrtc): The rtp-to-webrtc example demonstrates how to take RTP packets sent to a Pion process into your browser.
* [Simulcast](simulcast): The simulcast example demonstrates how to accept and demux 1 Track that contains 3 Simulcast streams. It then returns the media as 3 independent Tracks back to the sender.
* [Swap Tracks](swap-tracks): The swap-tracks example demonstrates deeper usage of the Pion Media API. The server accepts 3 media streams, and then dynamically routes them back as a single stream to the user.
* [RTCP Processing](rtcp-processing) The rtcp-processing example demonstrates Pion's RTCP APIs. This allow access to media statistics and control information.
* [Quick Switch](quick-switch) Use WebRTC to switch quickly between video feeds. Similiar to swap-tracks, but user controls when video is switched and uses static files.

#### Data Channel API
* [Data Channels](data-channels): The data-channels example shows how you can send/recv DataChannel messages from a web browser.
* [Data Channels Detach](data-channels-detach): The data-channels-detach example shows how you can send/recv DataChannel messages using the underlying DataChannel implementation directly. This provides a more idiomatic way of interacting with Data Channels.
* [Data Channels Flow Control](data-channels-flow-control): Example data-channels-flow-control shows how to use the DataChannel API efficiently. You can measure the amount the rate at which the remote peer is receiving data, and structure your application accordingly.
* [ORTC](ortc): Example ortc shows how you an use the ORTC API for DataChannel communication.
* [Pion to Pion](pion-to-pion): Example pion-to-pion is an example of two pion instances communicating directly! It therefore has no corresponding web page.

#### Miscellaneous
* [Custom Logger](custom-logger) The custom-logger demonstrates how the user can override the logging and process messages instead of printing to stdout. It has no corresponding web page.
* [ICE Restart](ice-restart) Example ice-restart demonstrates how a WebRTC connection can roam between networks. This example restarts ICE in a loop and prints the new addresses it uses each time.
* [ICE Single Port](ice-single-port) Example ice-single-port demonstrates how multiple WebRTC connections can be served from a single port. By default Pion listens on a new port for every PeerConnection. Pion can be configured to use a single port for multiple connections.
* [ICE TCP](ice-tcp) Example ice-tcp demonstrates how a WebRTC connection can be made over TCP instead of UDP. By default Pion only does UDP. Pion can be configured to use a TCP port, and this TCP port can be used for many connections.
* [ICE Proxy](ice-proxy) Example ice-proxy demonstrates how to use a proxy for TURN connections.
* [Trickle ICE](trickle-ice) Example trickle-ice example demonstrates Pion WebRTC's Trickle ICE APIs. This is important to use since it allows ICE Gathering and Connecting to happen concurrently.
* [VNet](vnet) Example vnet demonstrates Pion's network virtualisation library. This example connects two PeerConnections over a virtual network and prints statistics about the data traveling over it.

### Usage
We've made it easy to run the browser based examples on your local machine.

1. Build and run the example server:
    ``` sh
    git clone https://github.com/pion/webrtc.git webrtc
    cd pion/webrtc/examples
    go run examples.go
    ```

2. Browse to [localhost](http://localhost) to browse through the examples. Note that you can change the port of the server using the ``--address`` flag:
    ``` sh
    go run examples.go --address localhost:8080
    go run examples.go --address :8080            # listen on all available interfaces
    ```

### WebAssembly
Pion WebRTC can be used when compiled to WebAssembly, also known as WASM. In
this case the library will act as a wrapper around the JavaScript WebRTC API.
This allows you to use WebRTC from Go in both server and browser side code with
little to no changes

Some of our examples have support for WebAssembly. The same examples server documented above can be used to run the WebAssembly examples. However, you have to compile them first. This is done as follows:

1. If the example supports WebAssembly it will contain a `main.go` file under the `jsfiddle` folder.
2. Build this `main.go` file as follows:
    ```
    GOOS=js GOARCH=wasm go build -o demo.wasm
    ```
3. Start the example server. Refer to the [usage](#usage) section for how you can build the example server.
4. Browse to [localhost](http://localhost). The page should now give you the option to run the example using the WebAssembly binary.

---

### Overview (`examples/bandwidth-estimation-from-disk/README.md`)

# bandwidth-estimation-from-disk
bandwidth-estimation-from-disk demonstrates how to use Pion's Bandwidth Estimation APIs.

Pion provides multiple Bandwidth Estimators, but they all satisfy one interface. This interface
emits an int for how much bandwidth is available to send. It is then up to the sender to meet that number.

## Instructions
### Create IVF files named `high.ivf` `med.ivf` and `low.ivf`
```
ffmpeg -i $INPUT_FILE -g 30 -b:v .3M  -s 320x240   low.ivf
ffmpeg -i $INPUT_FILE -g 30 -b:v 1M   -s 858x480   med.ivf
ffmpeg -i $INPUT_FILE -g 30 -b:v 2.5M -s 1280x720  high.ivf
```

### Download bandwidth-estimation-from-disk

```
go install github.com/pion/webrtc/v4/examples/bandwidth-estimation-from-disk@latest
```

### Open bandwidth-estimation-from-disk example page
[jsfiddle.net](https://jsfiddle.net/a1cz42op/) you should see two text-areas, 'Start Session' button and 'Copy browser SessionDescription to clipboard'

### Run bandwidth-estimation-from-disk with your browsers Session Description as stdin
The `output.ivf` you created should be in the same directory as `bandwidth-estimation-from-disk`. In the jsfiddle press 'Copy browser Session Description to clipboard' or copy the base64 string manually.

Now use this value you just copied as the input to `bandwidth-estimation-from-disk`

#### Linux/macOS
Run `echo $BROWSER_SDP | bandwidth-estimation-from-disk`
#### Windows
1. Paste the SessionDescription into a file.
1. Run `bandwidth-estimation-from-disk < my_file`

### Input bandwidth-estimation-from-disk's Session Description into your browser
Copy the text that `bandwidth-estimation-from-disk` just emitted and copy into the second text area in the jsfiddle

### Hit 'Start Session' in jsfiddle, enjoy your video!
A video should start playing in your browser above the input boxes. When `bandwidth-estimation-from-disk` switches quality levels it will print the old and new file like so.

```
Switching from low.ivf to med.ivf
Switching from med.ivf to high.ivf
Switching from high.ivf to med.ivf
```


Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/broadcast/README.md`)

# broadcast
broadcast is a Pion WebRTC application that demonstrates how to broadcast a video to many peers, while only requiring the broadcaster to upload once.

This could serve as the building block to building conferencing software, and other applications where publishers are bandwidth constrained.

## Instructions
### Download broadcast
```
go install github.com/pion/webrtc/v4/examples/broadcast@latest
```

### Open broadcast example page
[jsfiddle.net](https://jsfiddle.net/us4h58jx/) You should see two buttons `Publish a Broadcast` and `Join a Broadcast`

### Run Broadcast
#### Linux/macOS
Run `broadcast` OR run `main.go` in `github.com/pion/webrtc/examples/broadcast`

### Start a publisher

* Click `Publish a Broadcast`
* Press `Copy browser SDP to clipboard` or copy the `Browser base64 Session Description` string manually
* Run `curl localhost:8080 -d "$BROWSER_OFFER"`. `$BROWSER_OFFER` is the value you copied in the last step.
* The `broadcast` terminal application will respond with an answer, paste this into the second input field in your browser.
* Press `Start Session`
* The connection state will be printed in the terminal and under `logs` in the browser.

### Join the broadcast
* Click `Join a Broadcast`
* Copy the string in the first input labelled `Browser base64 Session Description`
* Run `curl localhost:8080 -d "$BROWSER_OFFER"`. `$BROWSER_OFFER` is the value you copied in the last step.
* The `broadcast` terminal application will respond with an answer, paste this into the second input field in your browser.
* Press `Start Session`
* The connection state will be printed in the terminal and under `logs` in the browser.

You can change the listening port using `-port 8011`

You can `Join the broadcast` as many times as you want. The `broadcast` Golang application is relaying all traffic, so your browser only has to upload once.

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/custom-logger/README.md`)

# custom-logger

`custom-logger` is an example demonstrating how to override the default logging behavior of the [Pion WebRTC](https://github.com/pion/webrtc) stack.  
By default, Pion logs everything to `stdout`.  
This example shows how to inject a **custom `LoggerFactory`** to handle logs from every subsystem (ICE, DTLS, SCTP, DataChannel...).

---

##  Features

- Creates a **custom logger** that implements `logging.LeveledLogger`.
- Initializes two peer connections (`offerer` and `answerer`) locally.
- Establishes a WebRTC connection between them.
- Logs events from:
    - `ICE` candidate gathering
    - `DTLS` handshake
    - `SCTP` and `DataChannel` setup
- Prints logs with clear prefixes like `customLogger Debug:`.

Ideal for:
- Integrate with external monitoring systems
- Store logs to files or databases
- Debug complex WebRTC flows in a structured way

---

##  How to run

### 1. Install the example

```
go install github.com/pion/webrtc/v4/examples/custom-logger@latest
```
Make sure  ```$(go env GOPATH)/bin ```  is in your ```PATH```.

You can add it to your PATH like this (zsh):

```
echo 'export PATH="$PATH:$(go env GOPATH)/bin"' >> ~/.zshrc
source ~/.zshrc
```
### 2.Run
`custom-logger` or  `go run main.go`

##  Example output 

```
Creating logger for ice
Creating logger for dtls
Peer Connection State has changed: connected (answerer)
Peer Connection State has changed: connected (offerer)
customLogger Debug: Adding a new peer-reflexive candidate: 10.8.21.1:51196
```


You should see messages from our customLogger, as two PeerConnections start a session

---

### Overview (`examples/data-channels-detach-create/README.md`)

# data-channels-detach-create
data-channels-detach is an example that shows how you can detach a data channel. This allows direct access the underlying [pion/datachannel](https://github.com/pion/datachannel). This allows you to interact with the data channel using a more idiomatic API based on the `io.ReadWriteCloser` interface.

The example is meant to be used with data-channels-detach. This demonstrates two Go Pion processes communicating directly.

## Run data-channels-detach-create and make an offer to data-channels-detach via stdin
```
go run data-channels-detach-create/*.go | go run data-channels-detach/*.go
```

## post the answer from data-channels-detach back to data-channels-detach-create
You will see a base64 SDP printed to your console. You now need to communicate this back to `data-channels-detach-create` this can be done via a HTTP endpoint

`curl localhost:8080/sdp -d "BASE_64_SDP"`

## Output

On sucess you will get output like the following

```
Peer Connection State has changed: connecting
(Long base64 SDP that you should POST)
Peer Connection State has changed: connected
New DataChannel  1374394845054
Data channel ''-'1374394845054' open.
Message from DataChannel: kvmWkjYodyQcIlv
Sending aMDnwlTfDYnfoUy
Sending htqQtnbvygZKlmy
Message from DataChannel: CMjZiNtsmIBpCaN
```

---

### Overview (`examples/data-channels-detach/README.md`)

# data-channels-detach
data-channels-detach is an example that shows how you can detach a data channel. This allows direct access the underlying [pion/datachannel](https://github.com/pion/datachannel). This allows you to interact with the data channel using a more idiomatic API based on the `io.ReadWriteCloser` interface.

The example mirrors the data-channels example.

## Install
```
go install github.com/pion/webrtc/v4/examples/data-channels-detach@latest
```

## Usage
The example can be used in the same way as the data-channel example or can be paired with the data-channels-detach-create example. In the latter case; run both example and exchange the offer/answer text by copy-pasting them on the other terminal.

---

### Overview (`examples/data-channels-flow-control/README.md`)

# data-channels-flow-control
This example demonstrates how to use the following property / methods.

* func (d *DataChannel) BufferedAmount() uint64
* func (d *DataChannel) SetBufferedAmountLowThreshold(th uint64)
* func (d *DataChannel) BufferedAmountLowThreshold() uint64
* func (d *DataChannel) OnBufferedAmountLow(f func())

These methods are equivalent to that of JavaScript WebRTC API.
See https://developer.mozilla.org/en-US/docs/Web/API/RTCDataChannel for more details.

## When do we need it?
Send or SendText methods are called on DataChannel to send data to the connected peer.
The methods return immediately, but it does not mean the data was actually sent onto
the wire. Instead, it is queued in a buffer until it actually gets sent out to the wire.

When you have a large amount of data to send, it is an application's responsibility to
control the buffered amount in order not to indefinitely grow the buffer size to eventually
exhaust the memory.

The rate you wish to send data might be much higher than the rate the data channel can
actually send to the peer over the Internet. The above properties/methods help your
application to pace the amount of data to be pushed into the data channel.


## How to run the example code

The demo code (main.go) implements two endpoints (offerPC and answerPC) in it.

```
                        signaling messages
           +----------------------------------------+
           |                                        |
           v                                        v
   +---------------+                        +---------------+
   |               |          data          |               |
   |    offerPC    |----------------------->|    answerPC   |
   |:PeerConnection|                        |:PeerConnection|
   +---------------+                        +---------------+
```

First offerPC and answerPC will exchange signaling message to establish a peer-to-peer
connection, and data channel (label: "data").

Once the data channel is successfully opened, offerPC will start sending a series of
1024-byte packets to answerPC as fast as it can, until you kill the process by Ctrl-c.


Here's how to run the code.

At the root of the example, `pion/webrtc/examples/data-channels-flow-control/`:
```
$ go run main.go
2019/08/31 14:56:41 OnOpen: data-824635025728. Start sending a series of 1024-byte packets as fast as it can
2019/08/31 14:56:41 OnOpen: data-824637171120. Start receiving data
2019/08/31 14:56:42 Throughput: 179.118 Mbps
2019/08/31 14:56:43 Throughput: 203.545 Mbps
2019/08/31 14:56:44 Throughput: 211.516 Mbps
2019/08/31 14:56:45 Throughput: 216.292 Mbps
2019/08/31 14:56:46 Throughput: 217.961 Mbps
2019/08/31 14:56:47 Throughput: 218.342 Mbps
 :
```

---

### Overview (`examples/data-channels-simple/README.md`)

# WebRTC DataChannel Example in Go

This is a minimal example of a **WebRTC DataChannel** using **Go (Pion)** as the signaling server.

## Features

- Go server for signaling
- Browser-based DataChannel
- ICE candidate exchange
- Real-time messaging between browser and Go server

## Usage

1. Run the server:

```
go run main.go
```

2. Open browser at http://localhost:8080

3. Send messages via DataChannel and see them in terminal & browser logs.

---

### Overview (`examples/data-channels-whip-whep-like/README.md`)

# whip-whep-like

This example demonstrates a WHIP/WHEP-like implementation using Pion WebRTC with DataChannel support for real-time chat.

**Note:** This is similar to but not exactly WHIP/WHEP, as the official WHIP/WHEP specifications focus on media streaming only and do not include DataChannel support. This example extends the WHIP/WHEP pattern to demonstrate peer-to-peer chat functionality with automatic username assignment and message broadcasting.

Key features:
- **Real-time chat** with WebRTC DataChannels
- **Automatic username generation** - Each user gets a unique random username (e.g., SneakyBear46)
- **Message broadcasting** - All connected users receive messages from everyone else
- **WHIP/WHEP-like signaling** - Simple HTTP-based signaling for easy integration

Further details about WHIP+WHEP and the WebRTC DataChannel implementation are below the instructions.

## Instructions

### Download the example

This example requires you to clone the repo since it is serving static HTML.

```
git clone https://github.com/pion/webrtc.git
cd webrtc/examples/data-channels-whip-whep-like
```

### Run the server
Execute `go run *.go`

### Connect and chat

1. Open [http://localhost:8080](http://localhost:8080) in your browser
2. Click "Publish" or "Subscribe" to establish a DataChannel connection
3. You'll be assigned a random username (e.g., "SneakyBear46")
4. Type a message and click "Send Message" to broadcast to all connected users
5. Open multiple tabs/windows to test multi-user chat

Congrats, you have used Pion WebRTC! Now start building something cool

## Why WHIP/WHEP for signaling?

This example uses a WHIP/WHEP-like signaling approach where an Offer is uploaded via HTTP and the server responds with an Answer. This simple API contract makes it easy to integrate WebRTC into web applications.

**Difference from standard WHIP/WHEP:** The official WHIP/WHEP specifications are designed for media streaming (audio/video) only. This example extends that pattern to include DataChannel support for real-time chat functionality.

## Implementation details

### Username generation
Each connected user is automatically assigned a unique username combining:
- An adjective (e.g., Sneaky, Brave, Quick)
- An animal noun (e.g., Bear, Fox, Eagle)
- A random number (0-999)

Congrats, you have used Pion WebRTC! Now start building something cool

## Why WHIP/WHEP?

WHIP/WHEP mandates that a Offer is uploaded via HTTP. The server responds with a Answer. With this strong API contract WebRTC support can be added to tools like OBS.

For more info on WHIP/WHEP specification, feel free to read some of these great resources:
- https://webrtchacks.com/webrtc-cracks-the-whip-on-obs/
- https://datatracker.ietf.org/doc/draft-ietf-wish-whip/
- https://datatracker.ietf.org/doc/draft-ietf-wish-whep/
- https://bloggeek.me/whip-whep-webrtc-live-streaming

---

### Overview (`examples/data-channels/README.md`)

# data-channels
data-channels is Pion's sample WebRTC app that lets you send and receive DataChannel messages from a web browser.

## Brief Overview
This example will result in messages being sent between a browser and a self-hosted data-channels server. The connection is made by grabbing the browser's generated session description, or SDP, and passing it into the server. The server uses the browser's SDP to then return a new SDP from the server based on the browser's SDP. The server's SDP then gets passed back into the browser which confirms the handshake and forms a connection!

Once the connection is established, messages will automatically be sent from the data-channels server to the browser every 5 seconds. The browser has a button that lets you send a message back to the server when you click on it.

## Instructions
### 1. Download the data-channels server
```
go install github.com/pion/webrtc/v4/examples/data-channels@latest
```

### 2. Open JSFiddle
[Open this JSFiddle example page.](https://jsfiddle.net/e41tgovp/)
The top of the JSFiddle example page contains a text box containing your browser's session description (SDP).
Press `Copy browser SDP to clipboard` or copy the base64 string manually.

### 3. Send the browser's SDP to the server
Depending on your OS:

#### Linux/macOS (including WSL)
In the following command, replace `$BROWSER_SDP` with the copied string.
Run `echo $BROWSER_SDP | data-channels`.

#### Windows
1. Paste the copied string into a file.
2. Run `data-channels < my_file`.

### 4. Send the server's SDP back to the browser
The server will automatically print out a base64 string. Copy it and paste it into the second textbox in the JSFiddle page.

### 5. Start the session!
Under Start Session you should see 'Checking' as it starts connecting. If everything worked you should see `New DataChannel foo 1`.

Pion WebRTC will send random messages every 5 seconds that will appear in your browser.

### 6. Send a message from the browser to the server!
You can put whatever you want in the `Message` text area, and when you hit `Send Message` it should appear in your terminal!

## Example finished!
Congrats, you have used Pion WebRTC! Now start building something cool :)

## Architecture Overview

```mermaid
flowchart TB
    Browser--Copy Offer from TextArea-->Pion
    Pion--Copy Text Print to Console-->Browser
    subgraph Pion[Go Peer]
        p1[Create PeerConnection]
        p2[OnConnectionState Handler]
        p3[Print Connection State]
        p2-->p3
        p4[OnDataChannel Handler]
        p5[OnDataChannel Open]
        p6[Send Random Message every 5 seconds to DataChannel]
        p4-->p5-->p6
        p7[OnDataChannel Message]
        p8[Log Incoming Message to Console]
        p4-->p7-->p8
        p9[Read Session Description from Standard Input]
        p10[SetRemoteDescription with Session Description from Standard Input]
        p11[Create Answer]
        p12[Block until ICE Gathering is Complete]
        p13[Print Answer with ICE Candidatens included to Standard Output]
    end
    subgraph Browser[Browser Peer]
        b1[Create PeerConnection]
        b2[Create DataChannel 'foo']
        b3[OnDataChannel Message]
        b4[Log Incoming Message to Console]
        b3-->b4
        b5[Create Offer]
        b6[SetLocalDescription with Offer]
        b7[Print Offer with ICE Candidates included]

    end
```

---

### Overview (`examples/ice-proxy/README.md`)

# ICE Proxy
`ice-proxy` demonstrates Pion WebRTC's capabilities for utilizing a proxy in WebRTC connections.

This proxy functionality is particularly useful when direct peer-to-peer communication is restricted, such as in environments with strict firewalls. It primarily leverages TURN (Traversal Using Relays around NAT) with TCP connections to enable communication with the outside world.

## Instructions

### Download ice-proxy
The example is self-contained and requires no input.

```bash
go install github.com/pion/webrtc/v4/examples/ice-proxy@latest
```

### Run ice-proxy
```bash
ice-proxy
```

Upon execution, four distinct entities will be launched:
* `TURN Server`: This server facilitates relaying media traffic when direct communication between agents is not possible, simulating a scenario where peers are behind restrictive NATs.
* `Proxy HTTP Server`: A straightforward HTTP proxy designed to forward all TCP traffic to a specified target.
* `Offering Agent`: In a typical WebRTC setup, this would be a web browser. In this example, it's a simplified Pion client that initiates the WebRTC connection. This agent attempts direct communication with the answering agent.
* `Answering Agent`: This typically represents a web server. In this demonstration, it's configured to use the TURN server, simulating a scenario where the agent is not directly reachable. This agent exclusively uses a relay connection via the TURN server, with a proxy acting as an intermediary between the agent and the TURN server.

---

### Overview (`examples/ice-restart/README.md`)

# ice-restart
ice-restart demonstrates Pion WebRTC's ICE Restart abilities.

## Instructions

### Download ice-restart
This example requires you to clone the repo since it is serving static HTML.

```
git clone https://github.com/pion/webrtc.git
cd webrtc/examples/ice-restart
```

### Run ice-restart
Execute `go run *.go`

### Open the Web UI
Open [http://localhost:8080](http://localhost:8080). This will automatically start a PeerConnection. This page will now prints stats about the PeerConnection
and allow you to do an ICE Restart at anytime.

* `ICE Restart` is the button that causes a new offer to be made with `iceRestart: true`.
* `ICE Connection States` will contain all the connection states the PeerConnection moves through.
* `ICE Selected Pairs` will print the selected pair every 3 seconds. Note how the uFrag/uPwd/Port change everytime you start the Restart process.
* `Inbound DataChannel Messages` containing the current time sent by the Pion process every 3 seconds.

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/ice-single-port/README.md`)

# ice-single-port
ice-single-port demonstrates Pion WebRTC's ability to serve many PeerConnections on a single port.

Pion WebRTC has no global state, so by default ports can't be shared between two PeerConnections.
Using the SettingEngine, a developer can manually share state between many PeerConnections to allow
multiple PeerConnections to use the same port.

## Instructions

### Download ice-single-port
This example requires you to clone the repo since it is serving static HTML.

```
git clone https://github.com/pion/webrtc.git
cd webrtc/examples/ice-single-port
```

### Run ice-single-port
Execute `go run *.go`

### Open the Web UI
Open [http://localhost:8080](http://localhost:8080). This will automatically open 10 PeerConnections. This page will print
a Local/Remote line for each PeerConnection. Note that all 10 PeerConnections have different ports for their Local port.
However for the remote they all will be using port 8443.

Congrats, you have used Pion WebRTC! Now start building something cool.

---

### Overview (`examples/ice-tcp/README.md`)

# ice-tcp
ice-tcp demonstrates Pion WebRTC's ICE TCP abilities.

## Instructions

### Download ice-tcp
This example requires you to clone the repo since it is serving static HTML.

```
git clone https://github.com/pion/webrtc.git
cd webrtc/examples/ice-tcp
```

### Run ice-tcp
Execute `go run *.go`

### Open the Web UI
Open [http://localhost:8080](http://localhost:8080). This will automatically start a PeerConnection. This page will now prints stats about the PeerConnection. The UDP candidates will be filtered out from the SDP.

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/insertable-streams/README.md`)

# insertable-streams
insertable-streams demonstrates how to use insertable streams with Pion.
This example modifies the video with a single-byte XOR cipher before sending, and then
decrypts in Javascript.

insertable-streams allows the browser to process encoded video. You could implement
E2E encryption, add metadata or insert a completely different video feed!

## Instructions
### Create IVF named `output.ivf` that contains a VP8 track
```
ffmpeg -i $INPUT_FILE -g 30 output.ivf
```

### Download insertable-streams
```
go install github.com/pion/webrtc/v4/examples/insertable-streams@latest
```

### Open insertable-streams example page
[jsfiddle.net](https://jsfiddle.net/t5xoaryc/) you should see two text-areas and a 'Start Session' button. You will also have a 'Decrypt' checkbox.
When unchecked the browser will not decrypt the incoming video stream, so it will stop playing or display certificates.

### Run insertable-streams with your browsers SessionDescription as stdin
The `output.ivf` you created should be in the same directory as `insertable-streams`. In the jsfiddle the top textarea is your browser, copy that and:

#### Linux/macOS
Run `echo $BROWSER_SDP | insertable-streams`
#### Windows
1. Paste the SessionDescription into a file.
1. Run `insertable-streams < my_file`

### Input insertable-streams's SessionDescription into your browser
Copy the text that `insertable-streams` just emitted and copy into second text area

### Hit 'Start Session' in jsfiddle, enjoy your video!
A video should start playing in your browser above the input boxes. `insertable-streams` will exit when the file reaches the end.

To stop decrypting the stream uncheck the box and the video will not be viewable.

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/ortc-media/README.md`)

# ortc-media
ortc demonstrates Pion WebRTC's [ORTC](https://ortc.org/) capabilities. Instead of using the Session Description Protocol
to configure and communicate ORTC provides APIs. Users then can implement signaling with whatever protocol they wish.
ORTC can then be used to implement WebRTC. A ORTC implementation can parse/emit Session Description and act as a WebRTC
implementation.

In this example we have defined a simple JSON based signaling protocol.

## Instructions
### Create IVF named `output.ivf` that contains a VP8/VP9/AV1 track
```
ffmpeg -i $INPUT_FILE -g 30 -b:v 2M output.ivf
```

**Note**: In the `ffmpeg` command which produces the .ivf file, the argument `-b:v 2M` specifies the video bitrate to be 2 megabits per second. We provide this default value to produce decent video quality, but if you experience problems with this configuration (such as dropped frames etc.), you can decrease this. See the [ffmpeg documentation](https://ffmpeg.org/ffmpeg.html#Options) for more information on the format of the value.


### Download ortc-media
```
go install github.com/pion/webrtc/v4/examples/ortc-media@latest
```

### Run first client as offerer
`ortc-media -offer` this will emit a base64 message. Copy this message to your clipboard.

## Run the second client as answerer
Run the second client. This should be launched with the message you copied in the previous step as stdin.

`echo BASE64_MESSAGE_YOU_COPIED | ortc-media`

This will emit another base64 message. Copy this new message.

## Send base64 message to first client via CURL

* Run `curl localhost:8080 -d "BASE64_MESSAGE_YOU_COPIED"`. `BASE64_MESSAGE_YOU_COPIED` is the value you copied in the last step.

### Enjoy
The client that accepts media will print when it gets the first media packet. The SSRC will be different every run.

```
Got RTP Packet with SSRC 3097857772
```

Media packets will continue to flow until the end of the file has been reached.

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/ortc/README.md`)

# ortc
ortc demonstrates Pion WebRTC's [ORTC](https://ortc.org/) capabilities. Instead of using the Session Description Protocol
to configure and communicate ORTC provides APIs. Users then can implement signaling with whatever protocol they wish.
ORTC can then be used to implement WebRTC. A ORTC implementation can parse/emit Session Description and act as a WebRTC
implementation.

In this example we have defined a simple JSON based signaling protocol.

## Instructions
### Download ortc
```
go install github.com/pion/webrtc/v4/examples/ortc@latest
```

### Run first client as offerer
`ortc -offer` this will emit a base64 message. Copy this message to your clipboard.

## Run the second client as answerer
Run the second client. This should be launched with the message you copied in the previous step as stdin.

`echo $BASE64_MESSAGE_YOU_COPIED | ortc`

This will emit another base64 message. Copy this new message.

## Send base64 message to first client via CURL

* Run `curl localhost:8080 -d "BASE64_MESSAGE_YOU_COPIED"`. `BASE64_MESSAGE_YOU_COPIED` is the value you copied in the last step.

### Enjoy
If everything worked you will see `Data channel 'Foo'-'' open.` in each terminal.

Each client will send random messages every 5 seconds that will appear in the terminal

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/pion-to-pion/README.md`)

# pion-to-pion
pion-to-pion is an example of two pion instances communicating directly!

The SDP offer and answer are exchanged automatically over HTTP.
The `answer` side acts like a HTTP server and should therefore be ran first.

## Instructions
First run `answer`:
```sh
go install github.com/pion/webrtc/v4/examples/pion-to-pion/answer@latest
answer
```
Next, run `offer`:
```sh
go install github.com/pion/webrtc/v4/examples/pion-to-pion/offer@latest
offer
```

You should see them connect and start to exchange messages.

## You can use Docker-compose to start this example:
```sh
docker-compose up -d
```

Now, you can see message exchanging, using `docker logs`.

---

### Overview (`examples/play-from-disk-fec/README.md`)

# play-from-disk-fec
play-from-disk-fec demonstrates how to use forward error correction (FlexFEC-03) while sending video to your Chrome-based browser from files saved to disk. The example is designed to drop 40% of the media packets, but browser will recover them using the FEC packets and the delivered packets.

## Instructions
### Create IVF named `output.ivf` that contains a VP8/VP9/AV1 track
```
ffmpeg -i $INPUT_FILE -g 30 -b:v 2M output.ivf
```

**Note**: In the `ffmpeg` command which produces the .ivf file, the argument `-b:v 2M` specifies the video bitrate to be 2 megabits per second. We provide this default value to produce decent video quality, but if you experience problems with this configuration (such as dropped frames etc.), you can decrease this. See the [ffmpeg documentation](https://ffmpeg.org/ffmpeg.html#Options) for more information on the format of the value.

### Download play-from-disk-fec

```
go install github.com/pion/webrtc/v4/examples/play-from-disk-fec@latest
```

### Open play-from-disk-fec example page
Open [jsfiddle.net](https://jsfiddle.net/hgzwr9cm/) in your browser. You should see two text-areas and buttons for the offer-answer exchange.

### Run play-from-disk-fec to generate an offer
The `output.ivf` you created should be in the same directory as `play-from-disk-fec`.

When you run play-from-disk-fec, it will generate an offer in base64 format and print it to stdout.

### Input play-from-disk-fec's offer into your browser
Copy the base64 offer that `play-from-disk-fec` just emitted and paste it into the first text area in the jsfiddle (labeled "Remote Session Description")

### Hit 'Start Session' in jsfiddle to generate an answer
Click the 'Start Session' button. This will process the offer and generate an answer, which will appear in the second text area.

### Save the browser's answer to a file
Copy the base64-encoded answer from the second text area (labeled "Browser Session Description") and save it to a file named `answer.txt` in the same directory where you're running `play-from-disk-fec`.

### Press Enter to continue
Once you've saved the answer to `answer.txt`, go back to the terminal where `play-from-disk-fec` is running and press Enter. The program will read the answer file and establish the connection.

### Enjoy your video!
A video should start playing in your browser above the input boxes. `play-from-disk-fec` will exit when the file reaches the end

You can watch the stats about transmitted/dropped media & FEC packets in the stdout.

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/play-from-disk-playlist-control/README.md`)

# ogg-playlist-sctp
Streams Opus pages from multi or single track Ogg containers, exposes the playlist over an SCTP DataChannel, and lets the browser hop between tracks while showing artist/title metadata parsed from OpusTags.

## What this showcases
- Reads multi-stream Ogg containers with `oggreader` and keeps per-serial playback state.
- Publishes playlist + now-playing metadata (artist/title/vendor/comments) over a DataChannel.
- Browser can send `next`, `prev`, or a 1-based track number to jump around.
- Audio is sent as an Opus `TrackLocalStaticSample` over RTP, metadata/control ride over SCTP.

## Prepare a demo playlist
The example looks for `playlist.ogg` in the working directory.
You can provide your own `playlist.ogg` or generate it by running one of the following ffmpeg commands:

**Fake two-track Ogg with metadata (artist/title per stream)**
```sh
ffmpeg \
  -f lavfi -t 8 -i "sine=frequency=330" \
  -f lavfi -t 8 -i "sine=frequency=660" \
  -map 0:a -map 1:a \
  -c:a libopus -page_duration 20000 \
  -metadata:s:a:0 artist="Pion Artist" -metadata:s:a:0 title="Fake Intro" \
  -metadata:s:a:1 artist="Open-Source Friend" -metadata:s:a:1 title="Fake Outro" \
  playlist.ogg
```

**Single-track fallback with tags**
```sh
ffmpeg -f lavfi -t 10 -i "sine=frequency=480" \
  -c:a libopus -page_duration 20000 \
  -metadata artist="Solo Bot" -metadata title="One Track Demo" \
  playlist.ogg
```

## Run it
1. Build the binary:
   ```sh
   go install github.com/pion/webrtc/v4/examples/play-from-disk-playlist-control@latest
   ```
2. Run it from the directory containing `playlist.ogg` (override port with `-addr` if you like):
   ```sh
   play-from-disk-playlist-control
   # or
   play-from-disk-playlist-control -addr :8080
   ```
3. Open the hosted UI in your browser and press **Start Session**:
   ```
   http://localhost:8080
   ```
   Signaling is WHEP-style: the browser POSTs plain SDP to `/whep` and the server responds with the answer SDP. Use the buttons or type `next` / `prev` / a track number to switch tracks. Playlist metadata and now-playing updates arrive over the DataChannel; Opus audio flows on the media track.

---

### Overview (`examples/play-from-disk-renegotiation/README.md`)

# play-from-disk-renegotiation
play-from-disk-renegotiation demonstrates Pion WebRTC's renegotiation abilities.

For a simpler example of playing a file from disk we also have [examples/play-from-disk](/examples/play-from-disk)

## Instructions

### Download play-from-disk-renegotiation
This example requires you to clone the repo since it is serving static HTML.

```
git clone https://github.com/pion/webrtc.git
cd webrtc/examples/play-from-disk-renegotiation
```

### Create IVF named `output.ivf` that contains a VP8, VP9 or AV1 track

To encode video to VP8:
```
ffmpeg -i $INPUT_FILE -c:v libvpx -g 30 -b:v 2M output.ivf
```

alternatively, to encode video to AV1 (Note: AV1 is CPU intensive, you may need to adjust `-cpu-used`):
```
ffmpeg -i $INPUT_FILE -c:v libaom-av1 -cpu-used 8 -g 30 -b:v 2M output.ivf
```

Or to encode video to VP9:
```
ffmpeg -i $INPUT_FILE -c:v libvpx-vp9 -cpu-used 4 -g 30 -b:v 2M output.ivf
```

If you have a VP8, VP9 or AV1 file in a different container you can use `ffmpeg` to mux it into IVF:
```
ffmpeg -i $INPUT_FILE -c:v copy -an output.ivf
```

**Note**: In the `ffmpeg` command, the argument `-b:v 2M` specifies the video bitrate to be 2 megabits per second. We provide this default value to produce decent video quality, but if you experience problems with this configuration (such as dropped frames etc.), you can decrease this. See the [ffmpeg documentation](https://ffmpeg.org/ffmpeg.html#Options) for more information on the format of the value.

### Run play-from-disk-renegotiation

The `output.ivf` you created should be in the same directory as `play-from-disk-renegotiation`. Execute `go run *.go`

### Open the Web UI
Open [http://localhost:8080](http://localhost:8080) and you should have a `Add Track` and `Remove Track` button.  Press these to add as many tracks as you want, or to remove as many as you wish.

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/play-from-disk/README.md`)

# play-from-disk
play-from-disk demonstrates how to send video and/or audio to your browser from files saved to disk.

For an example of playing H264 from disk see [play-from-disk-h264](https://github.com/pion/example-webrtc-applications/tree/main/play-from-disk-h264)

## Instructions
### Create IVF named `output.ivf` that contains a VP8/VP9/AV1 track and/or `output.ogg` that contains a Opus track
```
ffmpeg -i "$INPUT_FILE" -g 30 -b:v 2M output.ivf
ffmpeg -i "$INPUT_FILE" -vn -c:a libopus -ac 2 -frame_duration 20 -page_duration 20000 -map_metadata -1 output.ogg
```

**Note**: In the `ffmpeg` command which produces the .ivf file, the argument `-b:v 2M` specifies the video bitrate to be 2 megabits per second. We provide this default value to produce decent video quality, but if you experience problems with this configuration (such as dropped frames etc.), you can decrease this. See the [ffmpeg documentation](https://ffmpeg.org/ffmpeg.html#Options) for more information on the format of the value.

### Download play-from-disk

```
go install github.com/pion/webrtc/v4/examples/play-from-disk@latest
```

### Open play-from-disk example page
[jsfiddle.net](https://jsfiddle.net/8kup9mvn/) you should see two text-areas, 'Start Session' button and 'Copy browser SessionDescription to clipboard'

### Run play-from-disk with your browsers Session Description as stdin
The `output.ivf` you created should be in the same directory as `play-from-disk`. In the jsfiddle press 'Copy browser Session Description to clipboard' or copy the base64 string manually.

Now use this value you just copied as the input to `play-from-disk`

#### Linux/macOS
Run `echo $BROWSER_SDP | play-from-disk`
#### Windows
1. Paste the SessionDescription into a file.
1. Run `play-from-disk < my_file`

### Input play-from-disk's Session Description into your browser
Copy the text that `play-from-disk` just emitted and copy into the second text area in the jsfiddle

### Hit 'Start Session' in jsfiddle, enjoy your video!
A video should start playing in your browser above the input boxes. `play-from-disk` will exit when the file reaches the end

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/quick-switch/README.md`)

# quick-switch
quick-switch demonstrates how to quickly switch between multiple videos using WebRTC.
Similiar to how sites like TikTok quickly swipe between videos


<video src="https://github.com/user-attachments/assets/07f15044-3aeb-44e2-a866-14bd4258aca0" autoplay loop muted> </video>

The logic in the frontend is purposefully kept as simple as possible. Making it easy to use this on any platform that supports WebRTC.

In the `main.go` we have one video track, and we switch which video file is written to it.

## Instructions

### Download quick-switch
This example requires you to clone the repo since it is serving static HTML.

```
git clone https://github.com/pion/webrtc.git
cd webrtc/examples/quick-switch
```

### Create your videos
This example expects AV1 inside a ivf container. I used the follow to encode for my demo.

```
ffmpeg -y \
  -i $YOUR_INPUT_VIDEO \
  -c:v libaom-av1 \
  -usage realtime \
  -lag-in-frames 0 \
  -crf 30 \
  -b:v 0 \
  -g 15 \
  -keyint_min 15 \
  -sc_threshold 0 \
  -pix_fmt yuv420p \
  -f ivf \
  output.ivf
```


### Run quick-switch
Execute `go run *.go`

### Open the Web UI
Open [http://localhost:8080](http://localhost:8080). This will automatically start a PeerConnection.

Press 'Next Video' and have fun! If you have ideas on how to make it better we would love to hear.

---

### Overview (`examples/reflect/README.md`)

# reflect
reflect demonstrates how with one PeerConnection you can send video to Pion and have the packets sent back. This example could be easily extended to do server side processing.

## Instructions
### Download reflect
```
go install github.com/pion/webrtc/v4/examples/reflect@latest
```

### Open reflect example page
[jsfiddle.net](https://jsfiddle.net/g643ft1k/) you should see two text-areas and a 'Start Session' button.

### Run reflect, with your browsers SessionDescription as stdin
In the jsfiddle the top textarea is your browser's Session Description. Press `Copy browser SDP to clipboard` or copy the base64 string manually.
We will use this value in the next step.

#### Linux/macOS
Run `echo $BROWSER_SDP | reflect`
#### Windows
1. Paste the SessionDescription into a file.
1. Run `reflect < my_file`

### Input reflect's SessionDescription into your browser
Copy the text that `reflect` just emitted and copy into second text area

### Hit 'Start Session' in jsfiddle, enjoy your video!
Your browser should send video to Pion, and then it will be relayed right back to you.

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/repacketize/README.md`)

# repacketize

repacketize demonstrates how many video codecs can be received, depacketized and packetized by Pion over RTP.

## Instructions

### Download and run repacketize

```
go install github.com/pion/webrtc/v4/examples/repacketize@latest
```

### Open repacketize local page

[localhost:8080](http://localhost:8080/) you should see a dropdown selector and a "Start" button.

### Select one of the video codecs

Availability of codecs depends on the browser you are accessing the page from; Safari and Google Chrome on Windows should support all of them.

### Hit 'Start', enjoy your video

Your browser should send video to Pion, and then it will be relayed right back to you.

Congrats, you have used Pion WebRTC! Now start building something cool.

---

### Overview (`examples/rtcp-processing/README.md`)

# rtcp-processing
rtcp-processing demonstrates the Public API for processing RTCP packets in Pion WebRTC.

This example is only processing messages for a RTPReceiver. A RTPReceiver is used for accepting
media from a remote peer.  These APIs also exist on the RTPSender when sending media to a remote peer.

RTCP is used for statistics and control information for media in WebRTC. Using these messages
you can get information about the quality of the media, round trip time and packet loss. You can
also craft messages to influence the media quality.

## Instructions
### Download rtcp-processing
```
go install github.com/pion/webrtc/v4/examples/rtcp-processing@latest
```

### Open rtcp-processing example page
[jsfiddle.net](https://jsfiddle.net/zurq6j7x/) you should see two text-areas, 'Start Session' button and 'Copy browser SessionDescription to clipboard'

### Run rtcp-processing with your browsers Session Description as stdin
In the jsfiddle press 'Copy browser Session Description to clipboard' or copy the base64 string manually.

Now use this value you just copied as the input to `rtcp-processing`

#### Linux/macOS
Run `echo $BROWSER_SDP | rtcp-processing`
#### Windows
1. Paste the SessionDescription into a file.
1. Run `rtcp-processing < my_file`

### Input rtcp-processing's Session Description into your browser
Copy the text that `rtcp-processing` just emitted and copy into the second text area in the jsfiddle

### Hit 'Start Session' in jsfiddle
You will see console messages for each inbound RTCP message from the remote peer.

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/rtp-forwarder/README.md`)

# rtp-forwarder
rtp-forwarder is a simple application that shows how to forward your webcam/microphone via RTP using Pion WebRTC.

## Instructions
### Download rtp-forwarder
```
go install github.com/pion/webrtc/v4/examples/rtp-forwarder@latest
```

### Open rtp-forwarder example page
[jsfiddle.net](https://jsfiddle.net/fm7btvr3/) you should see your Webcam, two text-areas and `Copy browser SDP to clipboard`, `Start Session` buttons

### Run rtp-forwarder, with your browsers SessionDescription as stdin
In the jsfiddle the top textarea is your browser's Session Description. Press `Copy browser SDP to clipboard` or copy the base64 string manually.
We will use this value in the next step.

#### Linux/macOS
Run `echo $BROWSER_SDP | rtp-forwarder`
#### Windows
1. Paste the SessionDescription into a file.
1. Run `rtp-forwarder < my_file`

### Input rtp-forwarder's SessionDescription into your browser
Copy the text that `rtp-forwarder` just emitted and copy into second text area

### Hit 'Start Session' in jsfiddle and enjoy your RTP forwarded stream!
You can run any of these commands at anytime. The media is live/stateless, you can switch commands without restarting Pion.

#### VLC
Open `rtp-forwarder.sdp` with VLC and enjoy your live video!

#### ffmpeg/ffprobe
Run `ffprobe -i rtp-forwarder.sdp -protocol_whitelist file,udp,rtp` to get more details about your streams

Run `ffplay -i rtp-forwarder.sdp -protocol_whitelist file,udp,rtp` to play your streams

You can add `-fflags nobuffer -flags low_delay -framedrop` to lower the latency. You will have worse playback in networks with jitter. Read about minimizing the delay on [Stackoverflow](https://stackoverflow.com/a/49273163/5472819).

#### Twitch/RTMP
`ffmpeg -protocol_whitelist file,udp,rtp -i rtp-forwarder.sdp -c:v libx264 -preset veryfast -b:v 3000k -maxrate 3000k -bufsize 6000k -pix_fmt yuv420p -g 50 -c:a aac -b:a 160k -ac 2 -ar 44100 -f flv rtmp://live.twitch.tv/app/$STREAM_KEY` Make sure to replace `$STREAM_KEY` at the end of the URL first.

---

### Overview (`examples/rtp-to-webrtc/README.md`)

# rtp-to-webrtc
rtp-to-webrtc demonstrates how to consume a RTP stream video UDP, and then send to a WebRTC client.

With this example we have pre-made GStreamer and ffmpeg pipelines, but you can use any tool you like!

## Instructions
### Download rtp-to-webrtc
```
go install github.com/pion/webrtc/v4/examples/rtp-to-webrtc@latest
```

### Open jsfiddle example page
[jsfiddle.net](https://jsfiddle.net/z7ms3u5r/) you should see two text-areas and a 'Start Session' button


### Run rtp-to-webrtc with your browsers SessionDescription as stdin
In the jsfiddle the top textarea is your browser's SessionDescription, copy that and:

#### Linux/macOS
Run `echo $BROWSER_SDP | rtp-to-webrtc`

#### Windows
1. Paste the SessionDescription into a file.
1. Run `rtp-to-webrtc < my_file`

### Send RTP to listening socket
You can use any software to send VP8 packets to port 5004. We also have the pre made examples below


#### GStreamer
```
gst-launch-1.0 videotestsrc ! video/x-raw,width=640,height=480,format=I420 ! vp8enc error-resilient=partitions keyframe-max-dist=10 auto-alt-ref=true cpu-used=5 deadline=1 ! rtpvp8pay ! udpsink host=127.0.0.1 port=5004
```

#### ffmpeg
```
ffmpeg -re -f lavfi -i testsrc=size=640x480:rate=30 -vcodec libvpx -cpu-used 5 -deadline 1 -g 10 -error-resilient 1 -auto-alt-ref 1 -f rtp 'rtp://127.0.0.1:5004?pkt_size=1200'
```

If you wish to send audio replace all occurrences of `vp8` with Opus in `main.go` then run

```
ffmpeg -f lavfi -i 'sine=frequency=1000' -c:a libopus -b:a 48000 -sample_fmt s16p -ssrc 1 -payload_type 111 -f rtp -max_delay 0 -application lowdelay 'rtp://127.0.0.1:5004?pkt_size=1200'
```

If you wish to send H264 instead of VP8 replace all occurrences of `vp8` with H264 in `main.go` then run

```
ffmpeg -re -f lavfi -i testsrc=size=640x480:rate=30 -pix_fmt yuv420p -c:v libx264 -g 10 -preset ultrafast -tune zerolatency -f rtp 'rtp://127.0.0.1:5004?pkt_size=1200'
```

### Input rtp-to-webrtc's SessionDescription into your browser
Copy the text that `rtp-to-webrtc` just emitted and copy into second text area

### Hit 'Start Session' in jsfiddle, enjoy your video!
A video should start playing in your browser above the input boxes.

Congrats, you have used Pion WebRTC! Now start building something cool

## Dealing with broken/lossy inputs
Pion WebRTC also provides a [SampleBuilder](https://pkg.go.dev/github.com/pion/webrtc/v3@v3.0.4/pkg/media/samplebuilder). This consumes RTP packets and returns samples.
It can be used to re-order and delay for lossy streams. You can see its usage in this example in [daf27b](https://github.com/pion/webrtc/commit/daf27bd0598233b57428b7809587ec3c09510413).

Currently it isn't working with H264, but is useful for VP8 and Opus. See [#1652](https://github.com/pion/webrtc/issues/1652) for the status of fixing for H264.

---

### Overview (`examples/save-to-disk-av1/README.md`)

# save-to-disk-av1
save-to-disk-av1 is a simple application that shows how to save a video to disk using AV1.

If you wish to save VP8 and Opus instead of AV1 see [save-to-disk](https://github.com/pion/webrtc/tree/main/examples/save-to-disk)

If you wish to save VP8/Opus inside the same file see [save-to-webm](https://github.com/pion/example-webrtc-applications/tree/main/save-to-webm)

You can then send this video back to your browser using [play-from-disk](https://github.com/pion/webrtc/tree/main/examples/play-from-disk)

## Instructions
### Download save-to-disk-av1
```
go install github.com/pion/webrtc/v4/examples/save-to-disk-av1@latest
```

### Open save-to-disk-av1 example page
[jsfiddle.net](https://jsfiddle.net/8jv91r25/) you should see your Webcam, two text-areas and two buttons: `Copy browser SDP to clipboard`, `Start Session`.

### Run save-to-disk-av1, with your browsers SessionDescription as stdin
In the jsfiddle the top textarea is your browser's Session Description. Press `Copy browser SDP to clipboard` or copy the base64 string manually.
We will use this value in the next step.

#### Linux/macOS
Run `echo $BROWSER_SDP | save-to-disk-av1`
#### Windows
1. Paste the SessionDescription into a file.
1. Run `save-to-disk-av1 < my_file`

### Input save-to-disk-av1's SessionDescription into your browser
Copy the text that `save-to-disk-av1` just emitted and copy into second text area

### Hit 'Start Session' in jsfiddle, wait, close jsfiddle, enjoy your video!
In the folder you ran `save-to-disk-av1` you should now have a file `output.ivf` play with your video player of choice!
> Note: In order to correctly create the files, the remote client (JSFiddle) should be closed. The Go example will automatically close itself.

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/save-to-disk/README.md`)

# save-to-disk
save-to-disk is a simple application that shows how to record your webcam/microphone using Pion WebRTC and save VP8/Opus to disk.

If you wish to save VP9 instead of VP8 you can just replace all occurences of VP8 with VP9 in [main.go](https://github.com/pion/example-webrtc-applications/tree/main/save-to-disk/main.go).

If you wish to save VP8/Opus inside the same file see [save-to-webm](https://github.com/pion/example-webrtc-applications/tree/main/save-to-webm)

If you wish to save AV1 instead see [save-to-disk-av1](https://github.com/pion/webrtc/tree/main/examples/save-to-disk-av1)

You can then send this video back to your browser using [play-from-disk](https://github.com/pion/webrtc/tree/main/examples/play-from-disk)

## Instructions
### Download save-to-disk
```
go install github.com/pion/webrtc/v4/examples/save-to-disk@latest
```

### Open save-to-disk example page
[jsfiddle.net](https://jsfiddle.net/2nwt1vjq/) you should see your Webcam, two text-areas and two buttons: `Copy browser SDP to clipboard`, `Start Session`.

### Run save-to-disk, with your browsers SessionDescription as stdin
In the jsfiddle the top textarea is your browser's Session Description. Press `Copy browser SDP to clipboard` or copy the base64 string manually.
We will use this value in the next step.

#### Linux/macOS
Run `echo $BROWSER_SDP | save-to-disk`
#### Windows
1. Paste the SessionDescription into a file.
1. Run `save-to-disk < my_file`

### Input save-to-disk's SessionDescription into your browser
Copy the text that `save-to-disk` just emitted and copy into second text area

### Hit 'Start Session' in jsfiddle, wait, close jsfiddle, enjoy your video!
In the folder you ran `save-to-disk` you should now have a file `output-1.ivf` play with your video player of choice!
> Note: In order to correctly create the files, the remote client (JSFiddle) should be closed. The Go example will automatically close itself.

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/sctp-interleaving-inspect/README.md`)

# SCTP Interleaving Inspector

This browser example uses `pion/ice`, `pion/dtls`, `pion/sctp`, and
`pion/datachannel` directly so it can intercept raw SCTP messages and parses them.

```sh
go run .
```

Open <http://localhost:8080> and click **Connect**. The page creates the
browser offer automatically, connects to the Pion stack, and reports whether
INIT/INIT-ACK advertised I-DATA chunk type 64, whether I-DATA was actually
observed, and whether legacy DATA chunks were seen.

As I wrote this, firefox should have I-DATA enabled by default, for chrome, you'll need to run chrome with this flag:

```
[chrome] -user-data-dir=/tmp/chrome-sctp-test --force-fieldtrials="WebRTC-DataChannel-Dcsctp/Enabled/WebRTC-DataChannelMessageInterleaving/Enabled/" http://localhost:8080
```

---

### Overview (`examples/simulcast/README.md`)

# simulcast
demonstrates of how to handle incoming track with multiple simulcast rtp streams and show all them back.

The browser will not send higher quality streams unless it has the available bandwidth. You can look at
the bandwidth estimation in `chrome://webrtc-internals`. It is under `VideoBwe` when `Read Stats From: Legacy non-Standard`
is selected.

## Instructions
### Download simulcast
```
go install github.com/pion/webrtc/v4/examples/simulcast@latest
```

### Open simulcast example page
[jsfiddle.net](https://jsfiddle.net/tz4d5bhj/) you should see two text-areas and two buttons: `Copy browser SDP to clipboard`, `Start Session`.

### Run simulcast, with your browsers SessionDescription as stdin
In the jsfiddle the top textarea is your browser's Session Description. Press `Copy browser SDP to clipboard` or copy the base64 string manually.
We will use this value in the next step.

#### Linux/macOS
Run `echo $BROWSER_SDP | simulcast`
#### Windows
1. Paste the SessionDescription into a file.
1. Run `simulcast < my_file`

### Input simulcast's SessionDescription into your browser
Copy the text that `simulcast` just emitted and copy into second text area

### Hit 'Start Session' in jsfiddle, enjoy your video!
Your browser should send a simulcast track to Pion, and then all 3 incoming streams will be relayed back.

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/stats/README.md`)

# stats
stats demonstrates how to use the [webrtc-stats](https://www.w3.org/TR/webrtc-stats/) implementation provided by Pion WebRTC.

This API gives you access to the statistical information about a PeerConnection. This can help you understand what is happening
during a session and why.

## Instructions
### Download stats
```
go install github.com/pion/webrtc/v4/examples/stats@latest
```

### Open stats example page
[jsfiddle.net](https://jsfiddle.net/s179hacu/) you should see your Webcam, two text-areas and two buttons: `Copy browser SDP to clipboard`, `Start Session`.

### Run stats, with your browsers SessionDescription as stdin
In the jsfiddle the top textarea is your browser's Session Description. Press `Copy browser SDP to clipboard` or copy the base64 string manually.
We will use this value in the next step.

#### Linux/macOS
Run `echo $BROWSER_SDP | stats`
#### Windows
1. Paste the SessionDescription into a file.
1. Run `stats < my_file`

### Input stats' SessionDescription into your browser
Copy the text that `stats` just emitted and copy into second text area

### Hit 'Start Session' in jsfiddle
The `stats` program will now print the InboundRTPStreamStats for each incoming stream and Remote IP+Ports.
You will see the following in your console. The exact fields will change as we add more values.

```
Stats for: video/VP8
InboundRTPStreamStats:
        PacketsReceived: 1255
        PacketsLost: 0
        Jitter: 588.9559641717999
        LastPacketReceivedTimestamp: 2023-04-26 13:16:16.63591134 -0400 EDT m=+18.317378921
        HeaderBytesReceived: 25100
        BytesReceived: 1361125
        FIRCount: 0
        PLICount: 0
        NACKCount: 0


remote-candidate IP(192.168.1.93) Port(59239)
remote-candidate IP(172.18.176.1) Port(59241)
remote-candidate IP(fd4d:d991:c340:6749:8c53:ee52:ae8c:14d4) Port(59238)
```

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/swap-tracks/README.md`)

# swap-tracks
swap-tracks demonstrates how to swap multiple incoming tracks on a single outgoing track.

## Instructions
### Download swap-tracks
```
go install github.com/pion/webrtc/v4/examples/swap-tracks@latest
```

### Open swap-tracks example page
[jsfiddle.net](https://jsfiddle.net/1rx5on86/) you should see two text-areas and two buttons: `Copy browser SDP to clipboard`, `Start Session`.

### Run swap-tracks, with your browsers SessionDescription as stdin
In the jsfiddle the top textarea is your browser's Session Description. Press `Copy browser SDP to clipboard` or copy the base64 string manually.
We will use this value in the next step.

#### Linux/macOS
Run `echo $BROWSER_SDP | swap-tracks`
#### Windows
1. Paste the SessionDescription into a file.
1. Run `swap-tracks < my_file`

### Input swap-tracks's SessionDescription into your browser
Copy the text that `swap-tracks` just emitted and copy into second text area

### Hit 'Start Session' in jsfiddle, enjoy your video!
Your browser should send streams to Pion, and then a stream will be relayed back, changing every 5 seconds.

Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/trickle-ice/README.md`)

# trickle-ice
trickle-ice demonstrates Pion WebRTC's Trickle ICE APIs.  ICE is the subsystem WebRTC uses to establish connectivity.

Trickle ICE is the process of sharing addresses as soon as they are gathered. This parallelizes
establishing a connection with a remote peer and starting sessions with TURN servers. Using Trickle ICE
can dramatically reduce the amount of time it takes to establish a WebRTC connection.

Trickle ICE isn't mandatory to use, but highly recommended.

## Instructions

### Download trickle-ice
This example requires you to clone the repo since it is serving static HTML.

```
git clone https://github.com/pion/webrtc.git
cd webrtc/examples/trickle-ice
```

### Run trickle-ice
Execute `go run *.go`

### Open the Web UI
Open [http://localhost:8080](http://localhost:8080). This will automatically start a PeerConnection.

## Note
Congrats, you have used Pion WebRTC! Now start building something cool

---

### Overview (`examples/vnet/README.md`)

# vnet
vnet is the virtual network layer for Pion. This allows developers to simulate issues that cause issues
with production WebRTC deployments.

See the full documentation for vnet [here](https://github.com/pion/transport/tree/main/vnet#vnet)

## What can vnet do
* Simulate different network topologies. Assert when a STUN/TURN server is actually needed.
* Simulate packet loss, jitter, re-ordering. See how your application performs under adverse conditions.
* Measure the total bandwidth used. Determine the total cost of running your application.
* More! We would love to continue extending this to support everyones needs.

## Instructions
Each directory contains a single `main.go` that aims to demonstrate a single feature of vnet.
They can all be run directly, and require no additional setup.

---

### Overview (`examples/whip-whep/README.md`)

# whip-whep
whip-whep demonstrates using WHIP and WHEP with Pion. Since WHIP+WHEP is standardized signaling you can publish via tools like OBS and GStreamer.
You can then watch it in sub-second time from your browser, or pull the video back into OBS and GStreamer via WHEP.

Further details about the why and how of WHIP+WHEP are below the instructions.

## Instructions

### Download whip-whep

This example requires you to clone the repo since it is serving static HTML.

```
git clone https://github.com/pion/webrtc.git
cd webrtc/examples/whip-whep
```

### Run whip-whep
Execute `go run *.go`

### Publish

You can publish via an tool that supports WHIP or via your browser. To publish via your browser open [http://localhost:8080](http://localhost:8080), and press publish.

To publish via OBS set `Service` to `WHIP` and `Server` to `http://localhost:8080/whip`. The `Bearer Token` can be whatever value you like.


### Subscribe

Once you have started publishing open [http://localhost:8080](http://localhost:8080) and press the subscribe button. You can now view your video you published via
OBS or your browser.

Congrats, you have used Pion WebRTC! Now start building something cool

## Why WHIP/WHEP?

WHIP/WHEP mandates that a Offer is uploaded via HTTP. The server responds with a Answer. With this strong API contract WebRTC support can be added to tools like OBS.

For more info on WHIP/WHEP specification, feel free to read some of these great resources:
- https://webrtchacks.com/webrtc-cracks-the-whip-on-obs/
- https://datatracker.ietf.org/doc/draft-ietf-wish-whip/
- https://datatracker.ietf.org/doc/draft-ietf-wish-whep/
- https://bloggeek.me/whip-whep-webrtc-live-streaming

---

--- METRICS ---
- Files Extracted: 38
- Estimated Token Budget: ~18913 tokens
- Canonical Reference: https://codewiki.google/github.com/pion/webrtc
