golanggohlsrtmpwebrtcmedia-serverobs-studiortcprtmp-proxyrtmp-serverrtprtsprtsp-proxyrtsp-relayrtsp-serversrtstreamingwebrtc-proxy
		
		
		
		
			You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							164 lines
						
					
					
						
							3.5 KiB
						
					
					
				
			
		
		
	
	
							164 lines
						
					
					
						
							3.5 KiB
						
					
					
				<!DOCTYPE html> | 
						|
<html> | 
						|
<head> | 
						|
<meta charset="utf-8"> | 
						|
<style> | 
						|
html, body { | 
						|
	margin: 0; | 
						|
	padding: 0; | 
						|
	height: 100%; | 
						|
	overflow: hidden; | 
						|
} | 
						|
#video { | 
						|
	width: 100%; | 
						|
	height: 100%; | 
						|
	background: black; | 
						|
} | 
						|
</style> | 
						|
</head> | 
						|
<body> | 
						|
 | 
						|
<video id="video" muted controls autoplay playsinline></video> | 
						|
 | 
						|
<script> | 
						|
 | 
						|
const restartPause = 2000; | 
						|
 | 
						|
class Receiver { | 
						|
	constructor() { | 
						|
		this.terminated = false; | 
						|
		this.ws = null; | 
						|
		this.pc = null; | 
						|
		this.restartTimeout = null; | 
						|
		this.start(); | 
						|
	} | 
						|
 | 
						|
	start() { | 
						|
		console.log("connecting"); | 
						|
 | 
						|
        this.ws = new WebSocket(window.location.href.replace(/^http/, "ws") + 'ws'); | 
						|
 | 
						|
        this.ws.onerror = () => { | 
						|
            console.log("ws error"); | 
						|
            if (this.ws === null) { | 
						|
                return; | 
						|
            } | 
						|
            this.ws.close(); | 
						|
            this.ws = null; | 
						|
        }; | 
						|
 | 
						|
        this.ws.onclose = () => { | 
						|
            console.log("ws closed"); | 
						|
            this.ws = null; | 
						|
            this.scheduleRestart(); | 
						|
        }; | 
						|
 | 
						|
        this.ws.onmessage = (msg) => this.onIceServers(msg); | 
						|
	} | 
						|
 | 
						|
    onIceServers(msg) { | 
						|
        if (this.ws === null) { | 
						|
            return; | 
						|
        } | 
						|
 | 
						|
        const iceServers = JSON.parse(msg.data); | 
						|
 | 
						|
        this.pc = new RTCPeerConnection({ | 
						|
            iceServers, | 
						|
        }); | 
						|
 | 
						|
        this.ws.onmessage = (msg) => this.onRemoteDescription(msg); | 
						|
        this.pc.onicecandidate = (evt) => this.onIceCandidate(evt); | 
						|
 | 
						|
        this.pc.oniceconnectionstatechange = () => { | 
						|
            if (this.pc === null) { | 
						|
                return; | 
						|
            } | 
						|
 | 
						|
            console.log("peer connection state:", this.pc.iceConnectionState); | 
						|
 | 
						|
            switch (this.pc.iceConnectionState) { | 
						|
            case "disconnected": | 
						|
                this.scheduleRestart(); | 
						|
            } | 
						|
        }; | 
						|
 | 
						|
        this.pc.ontrack = (evt) => { | 
						|
            console.log("new track " + evt.track.kind); | 
						|
            document.getElementById("video").srcObject = evt.streams[0]; | 
						|
        }; | 
						|
 | 
						|
        const direction = "sendrecv"; | 
						|
        this.pc.addTransceiver("video", { direction }); | 
						|
        this.pc.addTransceiver("audio", { direction }); | 
						|
 | 
						|
        this.pc.createOffer() | 
						|
            .then((desc) => { | 
						|
                if (this.pc === null || this.ws === null) { | 
						|
                    return; | 
						|
                } | 
						|
 | 
						|
                this.pc.setLocalDescription(desc); | 
						|
 | 
						|
                console.log("sending offer"); | 
						|
                this.ws.send(JSON.stringify(desc)); | 
						|
            }); | 
						|
    } | 
						|
 | 
						|
	onRemoteDescription(msg) { | 
						|
		if (this.pc === null || this.ws === null) { | 
						|
			return; | 
						|
		} | 
						|
 | 
						|
		this.pc.setRemoteDescription(new RTCSessionDescription(JSON.parse(msg.data))); | 
						|
		this.ws.onmessage = (msg) => this.onRemoteCandidate(msg); | 
						|
	} | 
						|
 | 
						|
    onIceCandidate(evt) { | 
						|
        if (this.ws === null) { | 
						|
            return; | 
						|
        } | 
						|
 | 
						|
        if (evt.candidate !== null) { | 
						|
            if (evt.candidate.candidate !== "") { | 
						|
                this.ws.send(JSON.stringify(evt.candidate)); | 
						|
            } | 
						|
        } | 
						|
    } | 
						|
 | 
						|
	onRemoteCandidate(msg) { | 
						|
		if (this.pc === null) { | 
						|
			return; | 
						|
		} | 
						|
 | 
						|
		this.pc.addIceCandidate(JSON.parse(msg.data)); | 
						|
	} | 
						|
 | 
						|
    scheduleRestart() { | 
						|
        if (this.terminated) { | 
						|
            return; | 
						|
        } | 
						|
 | 
						|
        if (this.ws !== null) { | 
						|
            this.ws.close(); | 
						|
            this.ws = null; | 
						|
        } | 
						|
 | 
						|
        if (this.pc !== null) { | 
						|
            this.pc.close(); | 
						|
            this.pc = null; | 
						|
        } | 
						|
 | 
						|
        this.restartTimeout = window.setTimeout(() => { | 
						|
            this.restartTimeout = null; | 
						|
            this.start(); | 
						|
        }, restartPause); | 
						|
    } | 
						|
} | 
						|
 | 
						|
window.addEventListener('DOMContentLoaded', () => new Receiver()); | 
						|
 | 
						|
</script> | 
						|
 | 
						|
</body> | 
						|
</html>
 | 
						|
 |