Beiträge von qwerto

    Ich kann bei folgender Funktion nicht mein Video sehen und ich weiß nicht warum:

    function renderMain() {
       bigVideo.innerHTML = "";
       const userKey = currentBig;
       if (userKey === "local") {
           const vid = document.createElement("video");
           vid.autoplay = true;
           vid.muted = true;
           if (localVideoOn) {
               vid.srcObject = localStream;
               vid.play().catch(err => alert("Autoplay blockiert:", err));
           } else {
               // Platzhalter, statt video
               const ph = document.createElement("div");
               ph.classList.add("placeholder");
               ph.textContent = username.charAt(0).toUpperCase();
               bigVideo.append(ph);
              return;
          }
          bigVideo.append(vid);
       } else {
         const p = peers[userKey];
         if (p.remoteStream && !p.user.camOff) {
           const vid = document.createElement("video");
           vid.srcObject = p.remoteStream;
           vid.autoplay = true;
           bigVideo.append(vid);
         } else {
           const ph = document.createElement("div");
           ph.classList.add("placeholder");
           ph.textContent = p.user.username[0];
           bigVideo.append(ph);
         }
         // Name & Mic-Icon
         const info = document.createElement("div");
         info.style.position = "absolute";
         info.style.bottom = "5px";
         info.style.left = "5px";
         info.style.color = "#fff";
         info.textContent = p.user.username;
         bigVideo.append(info);
         if (p.user.audioOff) {
           const mic = document.createElement("span");
           mic.style.position="absolute";
           mic.style.bottom="5px";
           mic.style.right="5px";
           mic.textContent="🔇";
           bigVideo.append(mic);
         }
       }

       // Small preview
       smallPreview.innerHTML = "";
       const previewStream = localVideoOn ? localStream : null;
       const vid2 = document.createElement("video");
       if (previewStream) {
           vid2.srcObject = previewStream;
           vid2.play().catch(err => alert("Preview autoplay blockiert:", err));
       }
       vid2.autoplay = vid2.muted = true;
       smallPreview.append(vid2);
     }


    Wie kann ich das Problem lösen? Das ist der komplette Code, falls notwendig:

    // webrtc-client.js
    (async ()=> {
     const socket = io({ query: { room, username, gender }});
     const mainC = document.getElementById("mainContainer");
     const usersC = document.getElementById("usersContainer");
     const bigVideo = document.getElementById("bigVideo");
     const smallPreview = document.getElementById("smallPreview");
     const actionBar = document.getElementById("actionBar");
     const btnMic = document.getElementById("btnToggleMic");
     const btnCam = document.getElementById("btnToggleCam");
     const btnSwitch = document.getElementById("btnSwitchCam");
     const toUsers = document.getElementById("toUsers");
     const toMain = document.getElementById("toMain");
     const usersGrid = document.getElementById("usersGrid");

     let localStream;
    try {
     localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
    } catch (err) {
     alert("Fehler beim Zugriff auf Kamera/Mikrofon:\n" + err.message);
     return; // ggf. abbrechen
    }


     let localVideoOn = true, localAudioOn = true;
     let peers = {}, currentBig = null;

     // Helper: Video-Element erstellen oder Platzhalter
     function makeVideoEl(stream, user) {
       const container = document.createElement("div");
       container.classList.add("userBox");
       const mediaEl = stream
         ? Object.assign(document.createElement("video"), { srcObject: stream, autoplay:true, muted: user.isLocal })
         : (() => {
             const p = document.createElement("div");
             p.classList.add("placeholder");
             p.textContent = user.username[0];
             return p;
           })();
       container.append(mediaEl);

       // Icons
       if (!stream && user.camOff) {
         // show placeholder (already)
       }
       if (user.audioOff) {
         const mic = document.createElement("span");
         mic.classList.add("micIcon");
         mic.textContent = "🔇";
         container.append(mic);
       }
       const gender = document.createElement("span");
       gender.classList.add("genderIcon");
       gender.textContent = user.gender === "m" ? "♂️" : user.gender === "w" ? "♀️" : "⚧️";
       container.append(gender);

       const info = document.createElement("div");
       info.classList.add("userInfo");
       info.textContent = user.username;
       container.append(info);

       return container;
     }

     // Umschalten zwischen Main- und Users-View
     toUsers.onclick  = ()=> mainC.classList.replace("active",""), usersC.classList.add("active");
     toMain.onclick   = ()=> usersC.classList.replace("active",""), mainC.classList.add("active");

     // ActionBar toggle
     bigVideo.onclick = ()=> actionBar.classList.toggle("visible");

     // Button-Events
     btnMic.onclick = () => {
       localAudioOn = !localAudioOn;
       localStream.getAudioTracks()[0].enabled = localAudioOn;
       btnMic.textContent = localAudioOn? "🎤":"🔇";
     };
     btnCam.onclick = () => {
       localVideoOn = !localVideoOn;
       localStream.getVideoTracks()[0].enabled = localVideoOn;
       btnCam.textContent = localVideoOn? "📷":"🚫";
       renderMain(); // Platzhalter ggf. neu zeichnen
     };
     btnSwitch.onclick = () => {
       // Bei 2 Teilnehmern: Video-Swapping
       if (Object.keys(peers).length === 1) {
         const otherId = Object.keys(peers)[0];
         currentBig = currentBig === otherId ? "local" : otherId;
         renderMain();
       }
     };

     // Peer-Verbindungen aufbauen (für jeden weiteren Teilnehmer eins)
     socket.on("roomData", async data => {
       // data: { socketId: { userName, gender } , … }
       // entfernte Verbindungen bereinigen
       for (let id in peers) {
         if (!data[id]) { peers[id].close(); delete peers[id]; }
       }
       // neue Verbindungen
       for (let id in data) {
         if (id === socket.id) continue;
         if (peers[id]) continue;
         const pc = new RTCPeerConnection();
         localStream.getTracks().forEach(t => pc.addTrack(t, localStream));

         pc.onicecandidate = e => e.candidate && socket.emit("signal", { to:id, from:socket.id, data:e.candidate });
         pc.ontrack = e => {
           peers[id].remoteStream = e.streams[0];
           renderMain();
           renderUsers();
         };

         const offer = await pc.createOffer();
         await pc.setLocalDescription(offer);
         socket.emit("signal", { to:id, from:socket.id, data:pc.localDescription });

         peers[id] = { pc, user: data[id], remoteStream: null };
       }

       // Wer spricht? (optional: per Audio-Level-Detection)
       // Für 1 oder 2: currentBig setzen
       if (Object.keys(peers).length <= 1) {
         currentBig = Object.keys(peers)[0] || "local";
       }
       renderMain();
       renderUsers();
     });

     socket.on("signal", async ({ from, data }) => {
       const p = peers[from];
       if (!p) return;
       if (data.type) {
         await p.pc.setRemoteDescription(data);
         if (data.type === "offer") {
           const answer = await p.pc.createAnswer();
           await p.pc.setLocalDescription(answer);
           socket.emit("signal", { to: from, from: socket.id, data: p.pc.localDescription });
         }
       } else {
         await p.pc.addIceCandidate(data);
       }
     });

     // Render-Funktionen
     function renderMain() {
       bigVideo.innerHTML = "";
       const userKey = currentBig;
       if (userKey === "local") {
           const vid = document.createElement("video");
           vid.autoplay = true;
           vid.muted = true;
           if (localVideoOn) {
               vid.srcObject = localStream;
               vid.play().catch(err => alert("Autoplay blockiert:", err));
           } else {
               // Platzhalter, statt video
               const ph = document.createElement("div");
               ph.classList.add("placeholder");
               ph.textContent = username.charAt(0).toUpperCase();
               bigVideo.append(ph);
              return;
          }
          bigVideo.append(vid);
       } else {
         const p = peers[userKey];
         if (p.remoteStream && !p.user.camOff) {
           const vid = document.createElement("video");
           vid.srcObject = p.remoteStream;
           vid.autoplay = true;
           bigVideo.append(vid);
         } else {
           const ph = document.createElement("div");
           ph.classList.add("placeholder");
           ph.textContent = p.user.username[0];
           bigVideo.append(ph);
         }
         // Name & Mic-Icon
         const info = document.createElement("div");
         info.style.position = "absolute";
         info.style.bottom = "5px";
         info.style.left = "5px";
         info.style.color = "#fff";
         info.textContent = p.user.username;
         bigVideo.append(info);
         if (p.user.audioOff) {
           const mic = document.createElement("span");
           mic.style.position="absolute";
           mic.style.bottom="5px";
           mic.style.right="5px";
           mic.textContent="🔇";
           bigVideo.append(mic);
         }
       }

       // Small preview
       smallPreview.innerHTML = "";
       const previewStream = localVideoOn ? localStream : null;
       const vid2 = document.createElement("video");
       if (previewStream) {
           vid2.srcObject = previewStream;
           vid2.play().catch(err => alert("Preview autoplay blockiert:", err));
       }
       vid2.autoplay = vid2.muted = true;
       smallPreview.append(vid2);
     }

     function renderUsers() {
       usersGrid.innerHTML = "";
       // Alle Fremd-User
       Object.entries(peers).forEach(([id, { user, remoteStream }]) => {
         const box = makeVideoEl(remoteStream, { ...user, audioOff: user.audioOff, camOff: !remoteStream });
         usersGrid.append(box);
       });
       // Mein kleines Video oben rechts
       const meBox = makeVideoEl(localStream, { username, gender, isLocal:true, audioOff: !localAudioOn, camOff: !localVideoOn });
       meBox.id = "meBox";
       usersGrid.append(meBox);
     }

     // Initial render
     renderMain();
     renderUsers();
    })();