Skip to content

A solution for non-seekable video files.  #136

@Jb-Za

Description

@Jb-Za

My use-case required me to have, mp4 files, at 60fps, and for the video to be seek-able. To my understanding the resulting videos are non-seekable due to the fact that they are originally from a stream, and thus do not have any metadata. The solution that I found is to force metadata into the file.

This is rather slow, and the better option would be to have the encoder (somehow) add the metadata during the recording process.

A disclaimer: I don't know much about the inner workings of chromium recording/streaming, this is simply just a solution that I found that may help someone out.

const { launch, getStream } = require("puppeteer-stream");
const fs = require("fs");
const { executablePath } = require("puppeteer");
const ffmpeg = require("fluent-ffmpeg");

const webmFile = __dirname + "/test.webm";

async function test() {
  const browser = await launch({
    defaultViewport: {
      width: 1920,
      height: 1080,
    },
    headless: false,
    executablePath: executablePath(),
  });

  const page = await browser.newPage();
  await page.goto("https://www.youtube.com/watch?v=dQw4w9WgXcQ");
  const stream = await getStream(page, { audio: true, video: true, videoConstraints: { mandatory: {  minFrameRate: 58, maxFrameRate: 60 }} });
  console.log("recording");

  const file = fs.createWriteStream(webmFile);
  stream.pipe(file);

  setTimeout(async () => {
    await stream.destroy();
    file.close();
    browser.close();

    const outputMP4File = __dirname + "/test.mp4";
    const videoMetadata = await getVideoMetadata(webmFile);

    ffmpeg()
      .input(webmFile)
      .outputOptions([
        `-metadata title="${videoMetadata.title}"`,
        `-metadata artist="${videoMetadata.artist}"`,
        "-r 60",
        "-b:v 8000k",
      ])
      .output(outputMP4File)
      .on("end", () => {
        console.log("Metadata added and WebM converted to MP4 successfully.");
      })
      .on("error", (err) => {
        console.error(
          "Error while adding metadata and converting WebM to MP4:",
          err
        );
      })
      .run();
  }, 1000 * 10);
}

async function getVideoMetadata(inputFile) {
  return new Promise((resolve, reject) => {
    ffmpeg.ffprobe(inputFile, (err, metadata) => {
      if (err) {
        reject(err);
      } else {
        const { title, artist } = metadata.format.tags;
        resolve({ title, artist });
      }
    });
  });
}

test();

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions