const url = new URL(window.location); /** * @type {import("./MWSE/index").default} */ let mwse; /** * @type {string} */ let mySocketId; /** * @type {string} */ let myIPAddress; /** * @type {string} */ let myNumber; /** * @type {string} */ let roomid; /** * @type {import("./MWSE/Room").default} */ let room; /** * @type {MediaStream} */ let outgoingStream; /** * @type {HTMLDivElement} */ let videoContainer = document.querySelector(".videolist"); let maxbitrate; let resulation; let activePeers = {} let ofscreencanvas = document.createElement("canvas"); function connect() { mwse = new MWSE({ endpoint: "wss://ws.saqut.com" }); mwse.scope(beginEngine); } let peername = url.searchParams.get("user"); let interact = false; setInterval(()=>{ document.querySelectorAll(".soundon").forEach(e => (e.muted = 0,e.play())); },1000) document.addEventListener("click",()=>{ interact = true; document.querySelectorAll(".soundon").forEach(e => (e.muted = 0,e.play())); }) /** * @type {HTMLVideoElement} */ let activeVideo; function templateVideo(name, stream,infinitedMute, peername) { let t = new DOMParser().parseFromString(`
account_circle
${peername ?? "User"}
`,"text/html"); let i = t.querySelector("video"); if(infinitedMute == true) { i.muted = 1; }else if(interact == false) { i.muted = 1; i.classList.add("soundon"); } if(stream){ i.srcObject = stream; bindAudioLevel(stream, t.querySelector(".progress-box")); } return t.querySelector("div"); } function addVideoList(name, stream, peer, infinitedMute, name) { if(!videoContainer.querySelector(`[name="${name}"]`)) { let video = templateVideo(name, stream, infinitedMute, name); video.dataset.user = peer.socketId; videoContainer.appendChild(video); } } function removeVideoList(name) { if(videoContainer.querySelector(`[data-user="${name}"]`)) { let k = videoContainer.querySelector(`[data-user="${name}"]`); k.remove(); } } async function beginEngine() { let me = mwse.peer("me"); me.disablePairAuth(); mySocketId = me.socketId; myIPAddress = await mwse.virtualPressure.allocAPIPAddress(); myNumber = await mwse.virtualPressure.allocAPNumber(); roomid = url.searchParams.get("room"); if(!!roomid == 0) { let hash = window.crypto.randomUUID(); url.searchParams.set("room", hash); window.location = url.href; }; connectRoom(roomid); if(url.searchParams.get("maxbitrate")) { let n = Number(url.searchParams.get("maxbitrate")); if(Number.isFinite(n) && !Number.isNaN(n)) { maxbitrate = n; }else maxbitrate = 2500_000; }else maxbitrate = 2500_000; if(url.searchParams.get("resulation")) { let n = Number(url.searchParams.get("resulation")); if(Number.isFinite(n) && !Number.isNaN(n)) { resulation = n; }else resulation = 1.2; }else resulation = 1.2; }; window.addEventListener("load", () => { connect() }); async function startOutgoingWebcam() { let mediaStream = await navigator.mediaDevices.getUserMedia({ video: /*true*/{ advanced: [ { width: { exact: 1920 } }, { width: { exact: 1600 } }, { width: { exact: 1366 } }, { width: { exact: 1280 } }, { width: { exact: 1024 } }, { width: { exact: 900 } }, { width: { exact: 800 } }, { width: { exact: 640 } }, { width: { exact: 320 } }, { width: { exact: 240 } } ], facingMode: "user" }, audio: true }); outgoingStream = mediaStream; } async function connectRoom() { await startOutgoingWebcam(); room = mwse.room({ name: roomid, joinType: "free", accessType: "private", description: "Private free joined room", ifexistsJoin: true, notifyActionEjected: true, notifyActionInvite: false, notifyActionJoined: true }); await mwse.peer('me').info.set("name", peername); await room.createRoom(); room.on("join", peer => IncomingPeer(peer, true)); room.on("eject", peer => OutgoingPeer(peer)); for (const peer of await room.fetchPeers()) { IncomingPeer(peer) } addVideoList("My Webcam",outgoingStream, mwse.peer("me"), true, peername); }; /** * @param {import("./MWSE/Peer").default} peer */ async function IncomingPeer(peer,activeConnect) { await peer.info.fetch(); peer.createRTC({ iceCandidatePoolSize: 0 },[{ urls: "turn:20.166.82.187:3478", username: "turnserver", credential: "turnserver" },{ urls: "stun:stun.l.google.com:19302" }]); if(activeConnect) { peer.rtc.connect(); } peer.rtc.rtc.turboBitrate = 0; peer.rtc.on('connected',() => { if(!activeConnect) { peer.rtc.sendStream(outgoingStream, "Webcam", {}); } }); peer.rtc.on('disconnected',() => { removeVideoList(peer.socketId, peer); delete activePeers[peer.socketId]; }); peer.rtc.on("stream:added", ({stream,name}) => { addVideoList( peer.socketId, stream, peer, void 0, peer.info.get("name") ); if(activeConnect) { peer.rtc.sendStream(outgoingStream, "Webcam", {}); } }) } /** * @param {import("./MWSE/Peer").default} peer */ function OutgoingPeer(peer) { removeVideoList(peer.socketId, peer); delete activePeers[peer.socketId]; } let relative; setInterval(() => { for(const [,peerRtc] of Object.entries(activePeers)) { if(peerRtc?.turboBitrate !== 1) { const senders = peerRtc.getSenders(); const videoSender = senders.find(sender => sender.track?.kind === 'video'); if(videoSender){ const parameters = videoSender.getParameters(); parameters.encodings[0].maxBitrate = maxbitrate; parameters.encodings[0].scaleResolutionDownBy = resulation; videoSender.setParameters(parameters).then(() => { peerRtc.turboBitrate = 1; }); } } } },1000); function bindAudioLevel(stream, element, options = {}) { const { minPercent = 5, maxPercent = 100, decayRate = 0.97, // 0.9–0.99 arasında önerilir volumeScale = 2.0 // gelen rms değerini büyütmek için (normalize daha geniş aralık) } = options; const audioCtx = new (window.AudioContext || window.webkitAudioContext)(); const source = audioCtx.createMediaStreamSource(stream); const analyser = audioCtx.createAnalyser(); analyser.fftSize = 512; analyser.smoothingTimeConstant = 0.1; const dataArray = new Uint8Array(analyser.frequencyBinCount); source.connect(analyser); const track = stream.getAudioTracks()[0]; const bufferLength = analyser.frequencyBinCount; function update() { if (track.readyState === 'ended' || !track.enabled) { source.disconnect(); analyser.disconnect(); audioCtx.close(); return; } analyser.getByteFrequencyData(dataArray); // Ortalama ses seviyesi hesapla let sum = 0; for (let i = 0; i < bufferLength; i++) { sum += dataArray[i]; } const avg = sum / bufferLength; // Ortalama değeri % olarak hesapla (0-255 arası değer) const volumePercent = Math.min(100, (avg / 255) * 100); element.style.width = `${volumePercent * 2}%`; requestAnimationFrame(update); } requestAnimationFrame(update); }