title: Chrome extension Can't play meeting audio
body: <p>I'm developing a google chrome extension using Manifest V2</p>
  <p>The goal of the extension is to enable the user to start online meetings within the browser</p>
  <p>I developed pages using react, and then inject these pages into an iFrame inside the currently open website</p>
  <p>I can capture the audio/video from the user, and I can send it successfully
  I receive audio &amp; video streams from the other users that join the meeting, and I can play their video.</p>
  <p>The problem is with audio, I receive the stream, but it doesn't play</p>
  <p>I tried playing it</p>
  <ul>
  <li>Inside the video player that has the video working</li>
  <li>in an <code>&lt;audio&gt;</code> tag in the same location as the video</li>
  <li>in an <code>&lt;audio&gt;</code> tag in the first iframe which the user clicked on</li>
  <li>by playing a &quot;silence.mp3&quot; file after the user clicks on the start meeting button, and then adding <code>&lt;audio&gt;</code> tags, or even using js (new Audio())</li>
  <li>in the background script</li>
  </ul>
  <p>in all of these cases, I couldn't play the audio that is streamed</p>
  <p>I'm not even getting an error message in the console</p>
  <p>one thing I did notice, is that I can play my own audio (echo my microphone input), and if I add it to an <code>&lt;audio&gt;</code> tag with controls visible, it starts counting up. But when I put the attendees audio track on <code>&lt;audio&gt;</code> tags, the controls stays at 0:00</p>
  <p>Here's the code for the VideoPlayer.jsx</p>
  <pre><code>import React, { useEffect, useRef, useState } from 'react';
  
  import msg from '../../lib/msg';
  import { Flex } from '@chakra-ui/react';
  
  const VideoPlayer = (props) =&gt; {
    const { sessionId } = props;
    const [participants, setParticipants] = useState([]);
    const [currentParticipant, setCurrentParticipant] = useState(null);
    const [videoTrack, setVideoTrack] = useState(null);
    const [audioTrack, setAudioTrack] = useState(null);
    const [isLocal, setIsLocal] = useState(false);
  
    useEffect(() =&gt; {
      if (currentParticipant) {
        if (currentParticipant.videoTrack) {
          setVideoTrack(currentParticipant.videoTrack);
        } else {
          setVideoTrack(null);
        }
        //set the audio track regardless if it's allowed or not, that's a decision for another function
        if (currentParticipant.audioTrack) {
          setAudioTrack(currentParticipant.audioTrack);
        } else {
          setAudioTrack(null);
        }
      }
    }, [currentParticipant]);
  
    const videoEl = useRef(null);
    const audioEl = useRef(null);
  
    /**
     * Set the video element's source
     */
    useEffect(() =&gt; {
      if (!videoEl.current || !videoTrack) return;
  
      videoEl.current.srcObject = new MediaStream([videoTrack]);
    }, [videoEl, videoTrack]);
  
    /**
     * Set the audio element's source
     */
    useEffect(() =&gt; {
      if (!audioEl.current || !audioTrack || isLocal) return;
      audioEl.current.srcObject = new MediaStream([audioTrack]);
    }, [audioEl, isLocal, audioTrack]);
  
    useEffect(() =&gt; {
      const reloadParticipants = () =&gt; {
        chrome.runtime.getBackgroundPage(function (win) {
          var p = win.getParticipants();
          setParticipants(p);
        });
      };
      const updateTracks = async (message, sender, sendResponse) =&gt; {
        
        chrome.runtime.getBackgroundPage(function (win) {
          var participantList = win.getParticipants();
          var index = participantList.findIndex(
            (item) =&gt; item.session_id === sessionId
          );
          var participant = participantList[index];
          setCurrentParticipant(participant);
          setIsLocal(participant.local);
        });
      };
  
      const msgListeners = [
        { action: msg.broadcast.participantListUpdated, fn: reloadParticipants },
        { action: msg.broadcast.tracksUpdated, fn: updateTracks },
      ];
      const initMessageListeners = async () =&gt; {
        chrome.runtime.onMessage.addListener((message, sender, sendResponse) =&gt; {
          msgListeners.forEach(async (item) =&gt; {
            if (message.action === item.action) {
              await item.fn(message, sender, sendResponse);
            }
          });
        });
      };
  
      initMessageListeners();
      reloadParticipants();
    }, [sessionId]);
  
    return (
      &lt;div className=&quot;tile-container&quot;&gt;
        &lt;audio autoPlay playsInline ref={audioEl} /&gt;
        &lt;video
          autoPlay
          muted
          playsInline
          ref={videoEl}
          style={{
            width: '100%',
            height: '100%',
            position: 'absolute',
            objectFit: 'cover',
          }}
        /&gt;
      &lt;/div&gt;
    );
  };
  
  export default VideoPlayer;
  </code></pre>
  <p>Then I'm using webpack to package it into a page</p>
  <pre><code>import React from 'react';
  import { render } from 'react-dom';
  
  import VideoPlayer from './VideoPlayer';
  import './index.css';
  
  render(&lt;VideoPlayer /&gt;, window.document.querySelector('#app-container'));
  </code></pre>
  <p>I inject this from the content script using this code</p>
  <pre><code>// at top I have the variable
  const videoPlayerUrl = chrome.runtime.getURL('/videoPlayer.html');
  
  // I monitor for an event &quot;participant joined&quot; then call the following function
  const createParticipantOverlay = (item) =&gt; {
      var participantContainer = $(`
      &lt;div id=&quot;participant-${item.session_id}&quot; class=&quot;bm_videoContainer&quot;&gt;
        &lt;iframe
          id=&quot;bm_ownerVideoFrame&quot;
          class=&quot;bm_videoFrame&quot;
          allow=&quot;autoplay *&quot;
          src=&quot;${videoPlayerUrl}?session_id=${item.session_id}&quot;
        &gt;&lt;/iframe&gt;
        &lt;div id=&quot;bm_dragHandler&quot; class=&quot;bm_dragHandler&quot;&gt;&lt;/div&gt;
      &lt;/div&gt;`);
      var container = $('#meeting-container');
      container.append(participantContainer);
  
      var dragHandler = $(`#participant-${item.session_id}`).find(
        '#bm_dragHandler'
      );
      dragHandler.on('mousedown', mouseDown);
      dragHandler.on('mouseup', mouseUp);
      dragHandler.on('mousemove', mouseMove);
    };
  </code></pre>
  <p>note: I'm using daily.co for managing the call</p>