UNPKG

@stormstreaming/stormstreamer

Version:

A JavaScript library containing core webrtc streamer functionality for embedding live-video streams on a website. Part of StormStreaming Suite.

492 lines (402 loc) 20.3 kB
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Storm Streamer DEVELOPER PAGE</title> <script src="../dist/iife/index.js"></script> </head> <link rel="preconnect" href="https://fonts.googleapis.com"> <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin> <link href="https://fonts.googleapis.com/css2?family=Courier+Prime:ital,wght@0,400;0,700;1,400;1,700&display=swap" rel="stylesheet"> <style> body {font-family: "Courier Prime", monospace;} span {width:100%;float:left; font-size:10px} button {margin:5px;padding:3px 6px; font-family: "Courier Prime", monospace;} label {margin:-20px 0 -20px 0;position:absolute;display: block;background:white;padding-left:10px;padding-right:10px; font-family: "Courier Prime", monospace;font-style: italic;} .selectWrapper {display: flex} .selectWrapper label {position: relative;margin: 0;padding-top: 4px;float:left;font-size: 12px;font-style:normal;} .selectWrapper select {float:left;position: relative} .toolbox {padding:10px;margin-left:10px;position: relative;margin-top:20px;border:2px dashed grey} .toolbox-wrapper {display:flex} ul {margin-right:10px;display: block} li { display: flex; flex-wrap: nowrap; align-items: center;font-size: 14px;font-style: normal;padding-bottom: 10px;} li span { display: inline;font-size: 14px; font-weight: 600;} .value {margin-left:7px} </style> <body> <div id="storm_player_0"> <h1>Storm Streamer - DEVELOPER PAGE</h1> <div id="main" style="width:1280px;height:720px;background:grey"> <div id="vContainer" style="background:red"></div> </div> </div> <div id="vContainer2" style="position:fixed;left:0;top:0;width:30%;z-index:2;background:red"></div> <div id="screenshotSample"></div> <div class="toolbox-wrapper"> <div class="toolbox" style="width:100%;display: flex"> <label>Streamer</label> <ul> <li>StreamKey: <span id="streamKeyValue" class="value"></span></li> <li>PublishState: <span id="publishStateValue" class="value"></span></li> <li>DeviceState: <span id="deviceStateValue" class="value"></span></li> <li>PublishDuration: <span id="publishDurationValue" class="value"></span></li> <li>VideoWidth: <span id="videoWidthValue" class="value"></span></li> <li>VideoHeight: <span id="videoHeightValue" class="value"></span></li> </ul> </div> <div class="toolbox" style="width:100%;display: flex"> <label>Devices</label> <ul> <li>CameraState: <span id="cameraStateValue" class="value"></span></li> <li>MicrophoneState: <span id="microphoneStateValue" class="value"></span></li> <li>Selected Camera: <span id="cameraValue" class="value"></span></li> <li>Selected Microphone: <span id="microphoneValue" class="value"></span></li> <li>Microphone Muted: <span id="microphoneMutedValue" class="value"></span></li> </ul> </div> <div class="toolbox" style="width:100%;display: flex"> <label>STREAM</label> <ul> <li>currentFPS: <span id="currentFPSValue" class="value"></span></li> <li>currentFPS Graph: <div id="currentFPSGraph" style="width:100px;height:20px"></div></li> <li>currentBitrate: <span id="currentBitrateValue" class="value"></span></li> <li>currentBitrate Graph: <div id="currentBitrateGraph" style="width:100px;height:20px"></div></span></li> <li>videoFrames: <span id="videoFramesCountValue" class="value"></span></li> <li>audioFrames: <span id="audioFramesCountValue" class="value"></span></li> </ul> </div> <div class="toolbox" style="width:100%;display: flex"> <label>INFO</label> <ul> <li>publishVBitrate: <span id="publishVBitrateValue" class="value"></span></li> <li>publishABitrate: <span id="publishABitrateValue" class="value"></span></li> <li>Microphone Graph: <div id="micGraph" style="width:100px;height:20px"></div></li> </ul> </div> </div> <div class="toolbox-wrapper"> <div class="toolbox"> <label>Publish</label> <button onclick="storm.publish('test')">publish('test')</button> <button onclick="storm.publish('test2')">publish('test2')</button> <button onclick="storm.unpublish()">unpublish()</button> <button onclick="storm.start()">start()</button> <button onclick="storm.stop()">stop()</button> <button onclick="storm.destroy()">destroy()</button> <button onclick="console.log(storm.getPublishState())">getPublishState()</button> <button onclick="console.log(storm.getDeviceState())">getDeviceState()</button> </div> <div class="toolbox"> <label>Sound</label> <button onclick="storm.muteMicrophone(true)">muteMicrophone(true)</button> <button onclick="storm.muteMicrophone(false)">muteMicrophone(false)</button> <button onclick="storm.mute()">muteSound()</button> <button onclick="storm.unmute()">unmuteSound()</button> <meter id="low_sound" min="0" low="50" high="80" max="100" value="0"></meter> <meter id="high_sound" min="0" low="50" high="80" max="100" value="0"></meter> </div> <div class="toolbox"> <label>Resize</label> <button onclick="storm.setSize(640, 360)">resize(640, 360)</button> <button onclick="storm.setSize(854, 480)">resize(854, 480)</button> <button onclick="storm.setSize(1280, 720)">resize(1280, 720)</button> <button onclick="storm.setWidth(360)">setWidth(360)</button> <button onclick="storm.setWidth('50%')">setWidth('50%')</button> <button onclick="storm.setWidth('100%')">setWidth('100%')</button> <button onclick="storm.setHeight(180)">setHeight(180)</button> <button onclick="storm.setHeight('50%')">setHeight('50%')</button> <button onclick="storm.setHeight('100%')">setHeight('100%')</button> <button onclick="console.log(storm.getWidth())">getWidth()</button> <button onclick="console.log(storm.getHeight())">getHeight()</button> <button onclick="storm.attachToContainer('vContainer')">attachToContainer('vContainer')</button> <button onclick="storm.attachToContainer('vContainer2')">attachToContainer('vContainer2')</button> <button onclick="storm.detachFromContainer()">detachFromContainer()</button> </div> <div class="toolbox"> <label>Camera List</label> <button onclick="console.log(storm.getCurrentCamera())">getCurrentCamera()</button> <button onclick="console.log(storm.getCurrentMicrophone())">getCurrentMicrophone()</button> <button onclick="console.log(storm.getCameraList())">getCameraList()</button> <button onclick="console.log(storm.getMicrophoneList())">getMicrophoneList()</button> <button onclick="console.log(storm.getCamerState())">getCamerState()</button> <button onclick="console.log(storm.getMicrophoneState())">getMicrophoneState()</button> <button onclick="storm.clearSavedDevices()">clearSavedDevices()</button> <button onclick="storm.messSavedDevices()">messSavedDevices()</button> <div class="selectWrapper"> <label for="cameraList">Select Camera: </label> <select id="cameraList"></select> </div> <div class="selectWrapper"> <label for="microphoneList">Select Microphone: </label> <select id="microphoneList"></select> </div> </div> </div> <div class="toolbox-wrapper"> <div class="toolbox" style="width:50%"> <label>Player Log</label> <div id="logContainer"></div> </div> <div class="toolbox" style="width:50%"> <label>Events recording</label> <textarea id="events" rows="30" style="padding:10px;width: calc(100% - 20px)">Events:</textarea> </div> </div> <script> let config = { stream: { serverList: [ // list of streaming server, 2nd, 3rd etc. will be used as backup { host: "localhost", // host or ip to the streaming server application:"webrtc", // application port: 443, // server port ssl: true // whenever SSL connection should be used or not }, ], }, settings: { autoStart: true, video: { scalingMode: "letterbox", containerID:"vContainer", width:"100%", aspectRatio:"16:9", resizeDebounce:0, }, audio: { startVolume:50, }, debug: { console: { enabled: true, logTypes: ["INFO","ERROR", "TRACE", "WARNING", "SUCCESS"], monoColor: false }, container: { enabled: true, containerID: "logContainer", logTypes: ["ERROR", "INFO", "TRACE", "WARNING","SUCCESS"], monoColor: false } } } } let storm = stormStreamer(config); storm.addEventListener("streamKeyInUseInterval", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - StreamKey already in use, restarting... ${event.count}/${event.maxCount}`); }) storm.addEventListener("streamKeyInUse", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - StreamKey already in use, restarting...`); }) storm.addEventListener("publishMetadataUpdate", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - Publish : ${event.metadata.streamWidth}x${event.metadata.streamHeight}`); }) storm.addEventListener("inputDevicesInitialized", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - Devices initialized successfully`); }) storm.addEventListener("savedCameraNotFound", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - Access to saved camera devices was denied, last device id: ${event.savedDeviceID}`); }) storm.addEventListener("savedMicrophoneNotFound", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - Access to saved microphone devices was denied, last device id: ${event.savedDeviceID}`); }) storm.addEventListener("cameraAccessDenied", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - Access to camera devices was denied`); }) storm.addEventListener("microphoneAccessDenied", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - Access to all microphone devices was denied`); }) storm.addEventListener("inputAccessDenied", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - Access to all input devices was denied`); }) storm.addEventListener("publish", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - Publish set to: `+event.streamKey); document.getElementById("streamKeyValue").innerHTML = event.streamKey; }) storm.addEventListener("publish", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - Publish set to: `+event.streamKey); document.getElementById("streamKeyValue").innerHTML = event.streamKey; }) storm.addEventListener("unpublish", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - Stream was unpublished`); document.getElementById("streamKeyValue").innerHTML = ""; }) storm.addEventListener("noCameraFound", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - No Camera has been found`); }) storm.addEventListener("noMicrophoneFound", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - No Microphone has been found`); }) storm.addEventListener("playerReady", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - Core Player is ready for interaction!`); }) storm.addEventListener("microphoneStateChange", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - Mute State Changed: ${event.isMuted}` ); }) storm.addEventListener("serverConnectionInitiate", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - (serverConnectionInitiate) Starting connection to: ${event.serverURL}`); }) storm.addEventListener("serverConnect", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - (serverConnect) Successfully connected to: ${event.serverURL} | seqNum: ${event.sequenceNum} `); }) storm.addEventListener("serverDisconnect", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - serverDisconnect: ${event.serverURL} | seqNum: ${event.sequenceNum} ` ); }) storm.addEventListener("serverConnectionError", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - (serverConnectionError) Could not connect to server: ${event.serverURL}`); }) storm.addEventListener("allConnectionsFailed", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - All servers failed!`); }) storm.addEventListener("videoElementCreate", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - videoElementCreate!`); }) storm.addEventListener("fullScreenEnter", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - fullScreenEnter!`); }) storm.addEventListener("fullScreenExit", function(event){ functionAppend(`Streamer ID: ${event.ref.getStreamerID()} - fullScreenExit!`); }) storm.addEventListener("soundMeter", function(event){ const lowSoundMeter = document.getElementById('low_sound'); const highSoundMeter = document.getElementById('high_sound'); lowSoundMeter.value = event.low*100; highSoundMeter.value = event.high*100; }) storm.addEventListener("deviceListUpdate", function(event){ console.log(event); updateCameraList(event.cameraList); updateMicrophoneList(event.microphoneList); }) storm.initialize(); storm.publish("test"); const graph1 = storm.createBitrateGraph("currentBitrateGraph").start(); const graph2 = storm.createFPSGraph("currentFPSGraph").start(); const graph3 = storm.createMicrophoneGraph("micGraph").start(); function functionAppend(appender){ let allText = document.getElementById("events").value; document.getElementById("events").value = appender+ "\r\n\r\n" +allText } document.getElementById('cameraList').addEventListener('change', () => { console.log("setCamera: "+document.getElementById('cameraList').value); storm.setCamera(document.getElementById('cameraList').value); }); document.getElementById('microphoneList').addEventListener('change', () => { storm.setMicrophone(document.getElementById('microphoneList').value); }); function updateCameraList(cameras) { const cameraList = document.getElementById('cameraList'); cameraList.innerHTML = ''; cameras.forEach(camera => { const option = document.createElement('option'); option.value = camera.id; option.textContent = camera.label; cameraList.appendChild(option); if(camera.isSelected){ document.getElementById("cameraValue").innerHTML = camera.label; cameraList.value = camera.id; } }); } function updateMicrophoneList(microphones) { const micList = document.getElementById('microphoneList'); micList.innerHTML = ''; microphones.forEach(mic => { const option = document.createElement('option'); option.value = mic.id; option.textContent = mic.label; micList.appendChild(option); if(mic.isSelected){ document.getElementById("microphoneValue").innerHTML = mic.label; micList.value = mic.id; } }); } function formatSecondsWithMilliseconds(milliseconds) { const hours = Math.floor(milliseconds / 3600000); milliseconds %= 3600000; const minutes = Math.floor(milliseconds / 60000); milliseconds %= 60000; const seconds = Math.floor(milliseconds / 1000); const milisecondsLeft = milliseconds % 1000; const formattedHours = hours < 10 ? '0' + hours : hours; const formattedMinutes = minutes < 10 ? '0' + minutes : minutes; const formattedSeconds = seconds < 10 ? '0' + seconds : seconds; const formattedMilliseconds = milisecondsLeft.toString().padStart(3, '0'); return `${formattedHours}:${formattedMinutes}:${formattedSeconds}.${formattedMilliseconds}`; } setInterval(() => { // STREAMER // Stream Key (daj tutaj INPUT) const streamKey = storm?.getStreamKey() ?? "None"; document.getElementById("streamKeyValue").innerHTML = streamKey; // Publish State const publishState = storm?.getPublishState() ?? "Unknown"; document.getElementById("publishStateValue").innerHTML = publishState; // Device State const deviceState = storm?.getInputDevicesState() ?? "Unknown"; document.getElementById("deviceStateValue").innerHTML = deviceState; // Publish Duration const now = new Date().getTime(); const publishTime = storm?.getPublishTime() ?? 0; const publishDuration = formatSecondsWithMilliseconds(((publishTime === 0) ? 0 : now - publishTime)); document.getElementById("publishDurationValue").innerHTML = publishDuration; // Video Width const videoWidth = storm?.getStatsController().publishVideoWidth; document.getElementById("videoWidthValue").innerHTML = videoWidth; // Video Height const videoHeight = storm?.getStatsController().publishVideoHeight; document.getElementById("videoHeightValue").innerHTML = videoHeight; // DEVICES // Camera State const cameraState = storm?.getCameraState() ?? "Unknown"; document.getElementById("cameraStateValue").innerHTML = cameraState; // Microphone State const microphoneState = storm?.getMicrophoneState() ?? "Unknown"; document.getElementById("microphoneStateValue").innerHTML = microphoneState; // Selected Camera (daj tutaj INPUT jak w Stream Key) const selectedCamera = storm?.getCurrentCamera()?.label ?? "None"; document.getElementById("cameraValue").innerHTML = selectedCamera; // Selected Microphone (daj tutaj INPUT jak w Stream Key) const selectedMicrophone = storm?.getCurrentMicrophone()?.label ?? "None"; document.getElementById("microphoneValue").innerHTML = selectedMicrophone; // Is Muted const isMicrophoneMuted = storm?.isMicrophoneMuted() ?? false; document.getElementById("microphoneMutedValue").innerHTML = isMicrophoneMuted; // STREAM // Current FPS const videoFPS = storm?.getStatsController().currentFPS ?? 0; document.getElementById("currentFPSValue").innerHTML = videoFPS.toFixed(2); // Current Bitrate const bitrate = storm?.getStatsController().currentBitrate ?? 0; document.getElementById("currentBitrateValue").innerHTML = bitrate; // Delivered Video Frames const videoFrames = storm?.getStatsController().deliveredVideoFrames ?? 0; document.getElementById("videoFramesCountValue").innerHTML = videoFrames; // Delivered Audio Frames const audioFrames = storm?.getStatsController().deliveredAudioFrames ?? 0; document.getElementById("audioFramesCountValue").innerHTML = audioFrames; // INFO // Publish VBitrate const publishVBitrate = storm?.getStatsController().publishVideoBitrate ?? 0; document.getElementById("publishVBitrateValue").innerHTML = publishVBitrate; // Publish VBitrate const publishABitrate = storm?.getStatsController().publishAudioBitrate ?? 0; document.getElementById("publishABitrateValue").innerHTML = publishABitrate; },100) async function embedScreenshot() { const blob = await storm.makeScreenshot(); // Używamy metody makeScreenshot z obiektu storm const screenshotDiv = document.getElementById('screenshotSample'); if (blob) { const imageUrl = URL.createObjectURL(blob); // Tworzymy URL z bloba const imgElement = document.createElement('img'); // Tworzymy nowy element img imgElement.src = imageUrl; // Ustawiamy źródło obrazu screenshotDiv.innerHTML = ''; // Czyścimy poprzednią zawartość diva screenshotDiv.appendChild(imgElement); // Dodajemy img do diva } else { screenshotDiv.innerHTML = '<p>Nie udało się uzyskać zrzutu ekranu.</p>'; // Informacja, gdy zrzut ekranu się nie powiedzie } } </script> </body> </html>