sammeS
Deno2y ago
samme

Streaming video from browser to deno server

Trying to stream video from Chrome to my local Deno server but having trouble understanding how to pipe things up correctly.

When I visit localhost:8000, which hits the /video endpont via the <video> element, the /receive endpoint throws this error:

TypeError: The destination writable stream closed before all the data could be piped to it.
    at readableStreamPipeTo (ext:deno_web/06_streams.js:2784:24)
    at ReadableStream.pipeTo (ext:deno_web/06_streams.js:5340:12)


Here's my setup:

Pasted into Chrome console:
(async () => {
  const video = document.querySelector('video');

  if (!video) {
    return;
  }

  const stream = video.captureStream();

  if (!stream) {
    return;
  }

  console.log('Streaming video...');

  const mediaRecorder = new MediaRecorder(stream);
  mediaRecorder.ondataavailable = async (event) => {
    if (event.data.size > 0) {
      await fetch('http://localhost:8000/receive', {
        method: 'POST',
        body: event.data
      });
    }
  };

  mediaRecorder.start(1000);

  video.onended = () => {
    mediaRecorder.stop();
    console.log('Done streaming video');
  };
})();



Deno server:

/** @jsx h */
import html, { h } from "https://deno.land/x/htm@0.2.3/mod.ts";

const writables = [] as WritableStream[];

Deno.serve({ port: 8000 }, async (request: Request) => {
  if (request.url.endsWith("/receive")) {
    await Promise.all(writables.map(async (writable) => {
      await request.body?.pipeTo(writable)
    }));

    return new Response(null, { status: 200 });
  }

  if (request.url.endsWith("/video")) {
    const headers = new Headers();
    headers.set("Content-Type", "video/mp4");

    const { readable, writable } = new TransformStream();

    writables.push(writable);

    return new Response(readable, { headers });
  }

  return html({
    title: "Stream",
    body: (
      <body>
        <video width="100%" height="100%" src="/video" autoplay controls></video>
      </body>
    ),
  });
});
Was this page helpful?