snapshot of https://github.com/pion/webrtc.git (main, 2026-09-15; blobs > 131072B omitted)
Some checks failed
REUSE Compliance Check / lint (push) Failing after 0s
Browser E2E / Test (push) Failing after 3s
Test / test (1.24) (push) Failing after 0s
Test / test-i386 (1.25) (push) Failing after 0s
Test / test-i386 (1.24) (push) Failing after 0s
Test / test-windows (1.25) (push) Failing after 0s
Test / test-windows (1.24) (push) Failing after 0s
Test / test (1.25) (push) Failing after 0s
Examples Tests / Test (push) Failing after 3s
Test / test-macos (1.25) (push) Failing after 0s
Test / test-macos (1.24) (push) Failing after 0s
Go mod tidy / tidy (push) Failing after 0s
Test / test-wasm (push) Failing after 0s
CodeQL / analyze (push) Failing after 1s
Fuzz / fuzz (push) Failing after 0s
Some checks failed
REUSE Compliance Check / lint (push) Failing after 0s
Browser E2E / Test (push) Failing after 3s
Test / test (1.24) (push) Failing after 0s
Test / test-i386 (1.25) (push) Failing after 0s
Test / test-i386 (1.24) (push) Failing after 0s
Test / test-windows (1.25) (push) Failing after 0s
Test / test-windows (1.24) (push) Failing after 0s
Test / test (1.25) (push) Failing after 0s
Examples Tests / Test (push) Failing after 3s
Test / test-macos (1.25) (push) Failing after 0s
Test / test-macos (1.24) (push) Failing after 0s
Go mod tidy / tidy (push) Failing after 0s
Test / test-wasm (push) Failing after 0s
CodeQL / analyze (push) Failing after 1s
Fuzz / fuzz (push) Failing after 0s
This commit is contained in:
8
examples/swap-tracks/jsfiddle/demo.css
Normal file
8
examples/swap-tracks/jsfiddle/demo.css
Normal file
@@ -0,0 +1,8 @@
|
||||
/*
|
||||
SPDX-FileCopyrightText: 2026 The Pion community <https://pion.ly>
|
||||
SPDX-License-Identifier: MIT
|
||||
*/
|
||||
textarea {
|
||||
width: 500px;
|
||||
min-height: 75px;
|
||||
}
|
||||
8
examples/swap-tracks/jsfiddle/demo.details
Normal file
8
examples/swap-tracks/jsfiddle/demo.details
Normal file
@@ -0,0 +1,8 @@
|
||||
---
|
||||
# SPDX-FileCopyrightText: 2026 The Pion community <https://pion.ly>
|
||||
# SPDX-License-Identifier: MIT
|
||||
|
||||
name: swap-tracks
|
||||
description: Example of how to have Pion swap incoming tracks on a single outgoing track
|
||||
authors:
|
||||
- Chad Retz
|
||||
35
examples/swap-tracks/jsfiddle/demo.html
Normal file
35
examples/swap-tracks/jsfiddle/demo.html
Normal file
@@ -0,0 +1,35 @@
|
||||
<!--
|
||||
SPDX-FileCopyrightText: 2026 The Pion community <https://pion.ly>
|
||||
SPDX-License-Identifier: MIT
|
||||
-->
|
||||
Browser base64 Session Description<br />
|
||||
<textarea id="localSessionDescription" readonly="true"></textarea> <br />
|
||||
<button onclick="window.copySDP()">
|
||||
Copy browser SDP to clipboard
|
||||
</button>
|
||||
<br />
|
||||
<br />
|
||||
|
||||
Golang base64 Session Description<br />
|
||||
<textarea id="remoteSessionDescription"></textarea> <br/>
|
||||
<button onclick="window.startSession()"> Start Session </button><br />
|
||||
|
||||
<br />
|
||||
|
||||
<div style="display: flex">
|
||||
<div>
|
||||
Browser stream 1<br />
|
||||
<canvas id="canvasOne" height="200" width="200"></canvas>
|
||||
</div>
|
||||
<div>
|
||||
Browser stream 2<br />
|
||||
<canvas id="canvasTwo" height="200" width="200"></canvas>
|
||||
</div>
|
||||
<div>
|
||||
Browser stream 3<br />
|
||||
<canvas id="canvasThree" height="200" width="200"></canvas>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
Video from server<br />
|
||||
<video id="serverVideo" width="200" height="200" autoplay muted></video> <br />
|
||||
93
examples/swap-tracks/jsfiddle/demo.js
Normal file
93
examples/swap-tracks/jsfiddle/demo.js
Normal file
@@ -0,0 +1,93 @@
|
||||
/* eslint-env browser */
|
||||
|
||||
// SPDX-FileCopyrightText: 2026 The Pion community <https://pion.ly>
|
||||
// SPDX-License-Identifier: MIT
|
||||
|
||||
// Create peer conn
|
||||
const pc = new RTCPeerConnection({
|
||||
iceServers: [
|
||||
{
|
||||
urls: 'stun:stun.l.google.com:19302'
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
pc.oniceconnectionstatechange = e => {
|
||||
console.debug('connection state change', pc.iceConnectionState)
|
||||
}
|
||||
pc.onicecandidate = event => {
|
||||
if (event.candidate === null) {
|
||||
document.getElementById('localSessionDescription').value = btoa(JSON.stringify(pc.localDescription))
|
||||
}
|
||||
}
|
||||
|
||||
pc.onnegotiationneeded = e =>
|
||||
pc.createOffer().then(d => pc.setLocalDescription(d)).catch(console.error)
|
||||
|
||||
pc.ontrack = event => {
|
||||
console.log('Got track event', event)
|
||||
document.getElementById('serverVideo').srcObject = new MediaStream([event.track])
|
||||
}
|
||||
|
||||
const canvases = [
|
||||
document.getElementById('canvasOne'),
|
||||
document.getElementById('canvasTwo'),
|
||||
document.getElementById('canvasThree')
|
||||
]
|
||||
|
||||
// Firefox requires getContext to be invoked on an HTML Canvas Element
|
||||
// prior to captureStream
|
||||
const canvasContexts = canvases.map(c => c.getContext('2d'))
|
||||
|
||||
// Capture canvas streams and add to peer conn
|
||||
const streams = canvases.map(c => c.captureStream())
|
||||
streams.forEach(stream => stream.getVideoTracks().forEach(track => pc.addTrack(track, stream)))
|
||||
|
||||
// Start circles
|
||||
requestAnimationFrame(() => drawCircle(canvasContexts[0], '#006699', 0))
|
||||
requestAnimationFrame(() => drawCircle(canvasContexts[1], '#cf635f', 0))
|
||||
requestAnimationFrame(() => drawCircle(canvasContexts[2], '#46c240', 0))
|
||||
|
||||
function drawCircle (ctx, color, angle) {
|
||||
// Background
|
||||
ctx.clearRect(0, 0, 200, 200)
|
||||
ctx.fillStyle = '#eeeeee'
|
||||
ctx.fillRect(0, 0, 200, 200)
|
||||
// Draw and fill in circle
|
||||
ctx.beginPath()
|
||||
const radius = 25 + 50 * Math.abs(Math.cos(angle))
|
||||
ctx.arc(100, 100, radius, 0, Math.PI * 2, false)
|
||||
ctx.closePath()
|
||||
ctx.fillStyle = color
|
||||
ctx.fill()
|
||||
// Call again
|
||||
requestAnimationFrame(() => drawCircle(ctx, color, angle + (Math.PI / 64)))
|
||||
}
|
||||
|
||||
window.startSession = () => {
|
||||
const sd = document.getElementById('remoteSessionDescription').value
|
||||
if (sd === '') {
|
||||
return alert('Session Description must not be empty')
|
||||
}
|
||||
|
||||
try {
|
||||
pc.setRemoteDescription(JSON.parse(atob(sd)))
|
||||
} catch (e) {
|
||||
alert(e)
|
||||
}
|
||||
}
|
||||
|
||||
window.copySDP = () => {
|
||||
const browserSDP = document.getElementById('localSessionDescription')
|
||||
|
||||
browserSDP.focus()
|
||||
browserSDP.select()
|
||||
|
||||
try {
|
||||
const successful = document.execCommand('copy')
|
||||
const msg = successful ? 'successful' : 'unsuccessful'
|
||||
console.log('Copying SDP was ' + msg)
|
||||
} catch (err) {
|
||||
console.log('Unable to copy SDP ' + err)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user