Back to Mediamtx

Web browsers

docs/4-read/07-web-browsers.md

1.20.17.6 KB
Original Source

Web browsers

Web browsers can read a stream from the server with the Media-over-QUIC, WebRTC and HLS protocols, by accessing web pages hosted by the server. It is also possible to embed streams into an external website.

Direct read

Media-over-QUIC

Visit the web page:

https://localhost:8892/mystream

Replace mystream with the path name.

WebRTC

Visit the web page:

http://localhost:8889/mystream

Replace mystream with the path name.

Be aware that not all browsers can read tracks with any codec, check Codec support in browsers.

HLS

The HLS protocol has a higher latency with respect to WebRTC, but there are fewer problems related to connectivity between server and clients. Visit the web page:

http://localhost:8888/mystream

Replace mystream with the path name.

Embed in a website

Live streams can be embedded into an external website by using the WebRTC or HLS protocol. Before embedding, check that the stream is ready and can be accessed with intended protocol by visiting web pages mentioned in the previous section.

Media-over-QUIC in iframe

The simplest way to embed a live stream in a web page, using the Media-over-QUIC protocol, consists in adding an <iframe> tag to the body section of the HTML:

html
<iframe src="https://mediamtx-ip:8892/mystream" scrolling="no"></iframe>

WebRTC in iframe

The simplest way to embed a live stream in a web page, using the WebRTC protocol, consists in adding an <iframe> tag to the body section of the HTML:

html
<iframe src="http://mediamtx-ip:8889/mystream" scrolling="no"></iframe>

The iframe can be controlled by adding query parameters to the URL (example: http://mediamtx-ip:8889/mystream?muted=false). The following parameters are available:

  • controls (boolean): whether to show controls. Default is true.
  • muted (boolean): whether to start the stream muted. Default is true.
  • autoplay (boolean): whether to autoplay the stream. Default is true.
  • playsInline (boolean): whether to play the stream without using the entire window of mobile devices. Default is true.
  • disablepictureinpicture (boolean): whether to disable the ability to open the stream in a dedicated window. Default is false.

The iframe method is fit for most use cases, but it has some limitations:

  • it doesn't allow to pass credentials (username, password or token) from the website to MediaMTX; credentials are asked directly to users.
  • it doesn't allow to directly access the video tag, to extract data from it, or to perform dynamic actions.

WebRTC with JavaScript

In order to overcome the limitations of the iframe-based method, it is possible to load the stream directly inside a <video> tag in the web page, through a JavaScript library.

Download reader.js from the repository and serve it together with the other assets of the website.

If you are using a JavaScript bundler, you can import it by using:

js
import "./reader.js";

Otherwise, you can add a <script> tag to the <head> section of the page:

html
<script defer src="./reader.js"></script>

Add a <video> tag:

html
<video
  id="myvideo"
  controls
  muted
  autoplay
  playsinline
  width="640"
  height="480"
></video>

After the video tag, add a script that initializes the stream when the page is fully loaded:

html
<script>
  let reader = null;

  window.addEventListener("load", () => {
    reader = new MediaMTXWebRTCReader({
      url: "http://mediamtx-ip:8889/mystream/whep",
      user: "", // fill if needed
      pass: "", // fill if needed
      token: "", // fill if needed
      onError: (err) => {
        console.error(err);
      },
      onTrack: (evt) => {
        document.getElementById("myvideo").srcObject = evt.streams[0];
      },
      onDataChannel: (evt) => {
        evt.channel.binaryType = "arraybuffer";
        evt.channel.onmessage = (evt) => {
          console.log("data channel message", evt.data);
        };
      },
    });
  });

  window.addEventListener("beforeunload", () => {
    if (reader !== null) {
      reader.close();
    }
  });
</script>

HLS in iframe

Reading a stream with the HLS protocol introduces some latency, but is usually easier to setup since it doesn't involve managing additional ports that in WebRTC are used to transmit the stream.

The simplest way to embed a live stream in a web page, using the HLS protocol, consists in adding an <iframe> tag to the body section of the HTML:

html
<iframe src="http://mediamtx-ip:8888/mystream" scrolling="no"></iframe>

The iframe can be controlled by adding query parameters to the URL (example: http://mediamtx-ip:8888/mystream?muted=false). The following parameters are available:

  • controls (boolean): whether to show controls. Default is true.
  • muted (boolean): whether to start the stream muted. Default is true.
  • autoplay (boolean): whether to autoplay the stream. Default is true.
  • playsInline (boolean): whether to play the stream without using the entire window of mobile devices. Default is true.
  • disablepictureinpicture (boolean): whether to disable the ability to open the stream in a dedicated window. Default is false.

The iframe method is fit for most use cases, but it has some limitations:

  • it doesn't allow to pass credentials (username, password or token) from the website to MediaMTX; credentials are asked directly to users.
  • it doesn't allow to directly access the video tag, to extract data from it, or to perform dynamic actions.

HLS with JavaScript

In order to overcome the limitations of the iframe-based method, it is possible to load the stream directly inside a <video> tag in the web page, through the hls.js library.

Be aware that hls.js is not compatible with browsers that do not expose the Media Source Extensions API, in particular old iOS versions (iPad iOS < 13, iPhone iOS < 17).

If you are using a JavaScript bundler, you can import hls.js by adding its npm package as dependency and then importing it:

js
import Hls from "hls.js";

Otherwise, you can use a <script> tag inside the <head> section that points to a CDN:

html
<script defer src="https://cdn.jsdelivr.net/npm/hls.js@1"></script>

Add a <video> tag:

html
<video
  id="myvideo"
  controls
  muted
  autoplay
  playsinline
  width="640"
  height="480"
></video>

After the video tag, add a script that initializes the stream when the page is fully loaded:

html
<script>
  window.addEventListener("load", () => {
    const video = document.getElementById("myvideo");

    const hls = new Hls({
      xhrSetup: function (xhr, url) {
        let user = ""; // fill if needed
        let pass = ""; // fill if needed
        let token = ""; // fill if needed

        if (user !== "") {
          const credentials = btoa(`${user}:${pass}`);
          xhr.setRequestHeader("Authorization", `Basic ${credentials}`);
        } else if (token !== "") {
          xhr.setRequestHeader("Authorization", `Bearer ${token}`);
        }
      },
    });

    hls.on(Hls.Events.MEDIA_ATTACHED, () => {
      hls.loadSource("http://mediamtx-ip:8888/mystream/index.m3u8");
    });

    // when the video is resumed after a manual or forced pause
    // (i.e. when the window is minimized), restore live streaming.
    video.onplay = () => {
      video.currentTime = hls.liveSyncPosition;
    };

    hls.attachMedia(video);
  });
</script>