Skip to content

Instantly share code, notes, and snippets.

@wlib
Created July 14, 2024 02:37
Show Gist options
  • Save wlib/0874b8bfe2efefe6edcfeb7cfd70e925 to your computer and use it in GitHub Desktop.
Save wlib/0874b8bfe2efefe6edcfeb7cfd70e925 to your computer and use it in GitHub Desktop.

Revisions

  1. wlib created this gist Jul 14, 2024.
    68 changes: 68 additions & 0 deletions m3u8-to-ffmpeg-zip.js
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,68 @@
    const sourceUrl = "https://m3u8-0.c-spanvideo.org/clip/clip.5081597.576.tsc.m3u8"

    const source = await fetch(sourceUrl)
    .then(res => res.ok ? res.text() : undefined)
    if (!source)
    throw new Error("it's over")

    const tsBlobs = await Promise.all(
    source
    .split("\n")
    .flatMap(line => {
    const trimmed = line.trim()
    if (trimmed.startsWith("#"))
    return []

    try {
    return [new URL(trimmed, sourceUrl)]
    }
    catch {
    return []
    }
    })
    .filter(url => url.pathname.endsWith(".ts"))
    .map(url =>
    fetch(url).then(res => {
    if (!res.ok)
    throw new Error("Failed to download", url)

    return res.blob()
    })
    )
    )

    const tsByteArrays = await Promise.all(
    tsBlobs.map(async blob => new Uint8Array(await blob.arrayBuffer()))
    )

    const { zip } = await import("https://esm.sh/[email protected]")

    const indexFile = tsBlobs.map((blob, i) => `file 'chunks/${i}.ts'`).join("\n")

    const zipFile = await new Promise(async (resolve, reject) => {
    zip(
    {
    "index.txt": new TextEncoder().encode(indexFile),
    chunks: Object.fromEntries(
    tsByteArrays.map((byteArray, i) => [`${i}.ts`, byteArray])
    )
    },
    { level: 0 },
    (error, data) => {
    if (error)
    reject(error)
    else
    resolve(data)
    }
    )
    })

    const downloadLink = document.createElement("a")
    downloadLink.href = URL.createObjectURL(
    new Blob([zipFile], { type: "application/zip" })
    )
    downloadLink.download = "video-source.zip"
    downloadLink.click()

    console.log("cd Downloads/video-source")
    console.log("ffmpeg -f concat -i index.txt -c copy video.mp4")