Compare commits

..

3 Commits

Author SHA1 Message Date
e871d5c268 Merge pull request 'Add local TURN server' (#2) from dev into main
All checks were successful
OTA TV / deploy (push) Successful in 2s
Reviewed-on: https://git.dwestgate.us/david/ota-tv-web/pulls/2
2025-04-04 16:02:58 -07:00
david
803de09305 abstract config 2025-04-04 14:28:13 -07:00
david
d6f81ff72b add turn server 2025-04-04 13:58:42 -07:00
2 changed files with 51 additions and 11 deletions

View File

@ -1,8 +1,20 @@
const host = window.location.hostname
const ws0 = new WebSocket(`ws://${host}:3001`);
const ws1 = new WebSocket(`ws://${host}:3002`);
const pc0 = new RTCPeerConnection({ iceServers: [] });
const pc1 = new RTCPeerConnection({ iceServers: [] });
const isSecure = window.location.protocol === 'https:';
const host = window.location.hostname;
const ws0builder = isSecure ? `wss://${host}/ws0` : `ws://${host}:3001`;
const ws1builder = isSecure ? `wss://${host}/ws1` : `ws://${host}:3002`;
const ws0 = new WebSocket(ws0builder);
const ws1 = new WebSocket(ws1builder);
const config = {
iceServers: [
{
urls: ['stun:dwestgate.us:3478','turn:dwestgate.us:3478?transport=udp'],
username: 'webrtcuser',
credential: 'webrtccred'
}
]
};
const pc0 = new RTCPeerConnection(config);
const pc1 = new RTCPeerConnection(config);
const video0 = document.getElementById('video0') as HTMLVideoElement;
const video1 = document.getElementById('video1') as HTMLVideoElement;
@ -65,3 +77,20 @@ ws1.onmessage = async (message) => {
await pc1.addIceCandidate(msg.data);
}
};
// TODO: Not yet working
// const dc0 = pc0.createDataChannel("keepalive");
// dc0.onopen = () =>{
// console.log("Data channel 0 open");
// setInterval(()=>{
// dc0.send("ping");
// },10000)
// }
// const dc1 = pc1.createDataChannel("keepalive");
// dc1.onopen = () =>{
// console.log("Data channel 1 open");
// setInterval(()=>{
// dc1.send("ping");
// },10000)
// }

View File

@ -9,14 +9,14 @@ const FRAME_SIZE = WIDTH * HEIGHT * 1.5; // YUV420p frame size (460800 bytes)
export default class TVWebSocket {
videoDevice: string;
public constructor(port: number, videoDevice) {
this.videoDevice = videoDevice
public constructor(port: number, videoDevice) {
this.videoDevice = videoDevice
const ffmpegProcess = this.startFFmpeg();
const videoTrack = this.createVideoTrack(ffmpegProcess);
const audioTrack = this.createAudioTrack(ffmpegProcess);
ffmpegProcess.stdio[2].on('data',data=>{
ffmpegProcess.stdio[2].on('data', data => {
// console.log("stdio[2] ",data.toString())
})
@ -24,7 +24,7 @@ export default class TVWebSocket {
const wss = new ws.WebSocketServer({ port });
wss.on('connection', async (ws: ws.WebSocket) => {
const peerConnection: RTCPeerConnection = this.createPeerConnection(videoTrack, audioTrack);
const peerConnection: RTCPeerConnection = this.createPeerConnection(videoTrack, audioTrack);
ws.on('message', async (message: Buffer) => {
const { type, data } = JSON.parse(message.toString());
@ -113,7 +113,7 @@ export default class TVWebSocket {
return p;
}
createVideoTrack = (ffmpegProcess: ChildProcessWithoutNullStreams) => {
let videoBuffer = Buffer.alloc(0);
const videoSource = new nonstandard.RTCVideoSource();
@ -185,7 +185,18 @@ export default class TVWebSocket {
}
createPeerConnection = (videoTrack: MediaStreamTrack, audioTrack: MediaStreamTrack): RTCPeerConnection => {
const peerConnection = new RTCPeerConnection({ iceServers: [] });
const peerConnection = new RTCPeerConnection({
iceServers: [
{
urls: 'stun:192.168.0.3:3478'
},
{
urls: 'turn:192.168.0.3:3478?transport=udp',
username: 'webrtcuser',
credential: 'webrtccred'
}
]
});
const stream = new MediaStream()
stream.addTrack(videoTrack)
stream.addTrack(audioTrack);