import { getServerConfig, getRTCConfiguration } from "../../js/config.js"; import { createDisplayStringArray } from "../../js/stats.js"; import { VideoPlayer } from "../../js/videoplayer.js"; import { RenderStreaming } from "../../module/renderstreaming.js"; import { Signaling, WebSocketSignaling } from "../../module/signaling.js"; /** @type {Element} */ let playButton; /** @type {RenderStreaming} */ let renderstreaming; /** @type {boolean} */ let useWebSocket; const codecPreferences = document.getElementById('codecPreferences'); const supportsSetCodecPreferences = window.RTCRtpTransceiver && 'setCodecPreferences' in window.RTCRtpTransceiver.prototype; const messageDiv = document.getElementById('message'); messageDiv.style.display = 'none'; const playerDiv = document.getElementById('player'); const lockMouseCheck = document.getElementById('lockMouseCheck'); const videoPlayer = new VideoPlayer(); setup(); window.document.oncontextmenu = function () { return false; // cancel default menu }; window.addEventListener('resize', function () { videoPlayer.resizeVideo(); }, true); window.addEventListener('beforeunload', async () => { if(!renderstreaming) return; await renderstreaming.stop(); }, true); async function setup() { const res = await getServerConfig(); useWebSocket = res.useWebSocket; showWarningIfNeeded(res.startupMode); showCodecSelect(); showPlayButton(); } function showWarningIfNeeded(startupMode) { const warningDiv = document.getElementById("warning"); if (startupMode == "private") { warningDiv.innerHTML = "

Warning

This sample is not working on Private Mode."; warningDiv.hidden = false; } } function showPlayButton() { if (!document.getElementById('playButton')) { const elementPlayButton = document.createElement('img'); elementPlayButton.id = 'playButton'; elementPlayButton.src = '../../images/Play.png'; elementPlayButton.alt = 'Start Streaming'; playButton = document.getElementById('player').appendChild(elementPlayButton); playButton.addEventListener('click', onClickPlayButton); } } function onClickPlayButton() { playButton.style.display = 'none'; // add video player videoPlayer.createPlayer(playerDiv, lockMouseCheck); setupRenderStreaming(); } async function setupRenderStreaming() { codecPreferences.disabled = true; const signaling = useWebSocket ? new WebSocketSignaling() : new Signaling(); const config = getRTCConfiguration(); renderstreaming = new RenderStreaming(signaling, config); renderstreaming.onConnect = onConnect; renderstreaming.onDisconnect = onDisconnect; renderstreaming.onTrackEvent = (data) => videoPlayer.addTrack(data.track); renderstreaming.onGotOffer = setCodecPreferences; await renderstreaming.start(); await renderstreaming.createConnection(); } function onConnect() { const channel = renderstreaming.createDataChannel("input"); videoPlayer.setupInput(channel); showStatsMessage(); } async function onDisconnect(connectionId) { clearStatsMessage(); messageDiv.style.display = 'block'; messageDiv.innerText = `Disconnect peer on ${connectionId}.`; await renderstreaming.stop(); renderstreaming = null; videoPlayer.deletePlayer(); if (supportsSetCodecPreferences) { codecPreferences.disabled = false; } showPlayButton(); } function setCodecPreferences() { /** @type {RTCRtpCodecCapability[] | null} */ let selectedCodecs = null; if (supportsSetCodecPreferences) { const preferredCodec = codecPreferences.options[codecPreferences.selectedIndex]; if (preferredCodec.value !== '') { const [mimeType, sdpFmtpLine] = preferredCodec.value.split(' '); const { codecs } = RTCRtpSender.getCapabilities('video'); const selectedCodecIndex = codecs.findIndex(c => c.mimeType === mimeType && c.sdpFmtpLine === sdpFmtpLine); const selectCodec = codecs[selectedCodecIndex]; selectedCodecs = [selectCodec]; } } if (selectedCodecs == null) { return; } const transceivers = renderstreaming.getTransceivers().filter(t => t.receiver.track.kind == "video"); if (transceivers && transceivers.length > 0) { transceivers.forEach(t => t.setCodecPreferences(selectedCodecs)); } } function showCodecSelect() { if (!supportsSetCodecPreferences) { messageDiv.style.display = 'block'; messageDiv.innerHTML = `Current Browser does not support RTCRtpTransceiver.setCodecPreferences.`; return; } const codecs = RTCRtpSender.getCapabilities('video').codecs; codecs.forEach(codec => { if (['video/red', 'video/ulpfec', 'video/rtx'].includes(codec.mimeType)) { return; } const option = document.createElement('option'); option.value = (codec.mimeType + ' ' + (codec.sdpFmtpLine || '')).trim(); option.innerText = option.value; codecPreferences.appendChild(option); }); codecPreferences.disabled = false; } /** @type {RTCStatsReport} */ let lastStats; /** @type {number} */ let intervalId; function showStatsMessage() { intervalId = setInterval(async () => { if (renderstreaming == null) { return; } const stats = await renderstreaming.getStats(); if (stats == null) { return; } const array = createDisplayStringArray(stats, lastStats); if (array.length) { messageDiv.style.display = 'block'; messageDiv.innerHTML = array.join('
'); } lastStats = stats; }, 1000); } function clearStatsMessage() { if (intervalId) { clearInterval(intervalId); } lastStats = null; intervalId = null; messageDiv.style.display = 'none'; messageDiv.innerHTML = ''; }