我可以使用网络将 m3u8 文件的所有片段下载为一个 mp4 文件吗(无 ffmpeg)

问题描述 投票:0回答:2

是否可以使用 javascript 或 php 下载一个文件中的所有

m3u8

我搜索这个但找不到任何东西;

javascript php m3u8
2个回答
15
投票

TL/DR: 我使用以下代码从 m3u8 链接下载所有 mpeg-ts 块文件,然后以编程方式将它们中的每一个转换为 .mp4。

我最终得到了许多小的 .mp4 文件,我可以将它们添加到 vlc 播放列表中并播放,但我无法使用 JavaScript 以编程方式将所有这些 mp4 文件连接到一个 mp4 文件中。

我听说将所有这些 ts 文件合并到一个 mp4 文件中的最后一部分可以使用 mux.js 完成,但我自己还没有这样做过。

长版:

我最终做的是使用 m3u8_to_mpegts 将 m3u8 文件指向的每个 MPEG_TS 文件下载到目录中。

var TsFetcher = require('m3u8_to_mpegts');

TsFetcher({
    uri: "http://api.new.livestream.com/accounts/15210385/events/4353996/videos/113444715.m3u8",
       cwd: "destinationDirectory",
       preferLowQuality: true,
   }, 
   function(){
        console.log("Download of chunk files complete");
        convertTSFilesToMp4();
   }
);

然后我使用 mpegts_to_mp4

将这些 .ts 文件转换为 .mp4 文件
var concat = require('concatenate-files');


// Read all files and run 
function getFiles(currentDirPath, callback) {
    var fs = require('fs'),
        path = require('path');
    fs.readdir(currentDirPath, function (err, files) {
        if (err) {
            throw new Error(err);
        }

        var fileIt = files.length;
        files.forEach(function (name) {
            fileIt--;
            // console.log(fileIt+" files remaining");
            var filePath = path.join(currentDirPath, name);
            var stat = fs.statSync(filePath);
            if (stat.isFile()) {
                callback(filePath, (fileIt==0));
            }
        });
    });
}




var mpegts_to_mp4 = require('mpegts_to_mp4');
var toConvertIt=0, doneConvertingIt = 0;

function convertTSFilesToMp4(){ 
    getFiles("destinationDirectory/bandwidth-198000", 
        function onFileDiscovered(filePath, noMoreFiles){   //onFileDiscovered runs for each file we discover in the destination directory
            var filenameParts = filePath.split("/"); // if on Windows execute .split("\\");, thanks Chayemor!
            var filename = filenameParts[2];
            if(filename.split(".")[1]=="ts"){   //if its a ts file
                console.log(filename);  

                mpegts_to_mp4(filePath, toConvertIt+'dest.mp4', function (err) {
                    // ... handle success/error ...
                    if(err){
                        console.log("Error: "+err);
                    }
                    doneConvertingIt++
                    console.log("Finished converting file "+toConvertIt);
                    if(doneConvertingIt==toConvertIt){
                        console.log("Done converting vids.");
                    }
                });
                toConvertIt++;
            }
        });
}

注意:如果您想使用给定代码,请更改以下内容:

  • uri 很明显
  • 您希望保存 ts 文件的(cwd)位置(我的是destinationDirectory)
  • preferLowQuality 如果您喜欢它会找到的最高质量,请将其设置为 false
  • 下载 ts 文件后您从中读取它们的位置(我的是destinationDirectory/bandwidth-198000)

我希望这段代码对将来的人有所帮助。 特别感谢 Tenacex 在这方面帮助我。


-1
投票

以下将从网络“按原样”下载所有内容。 这会获取所有可变比特率文件,假设某个地方有同一文件的多种编码。 然后,您可以使用 ffmpeg 将所有内容组合在一起并进行编码。

import sys
import os
import requests

OUTPUT_FOLDER = 'output'  # default output folder name


HEADERS = {
    "User-Agent": "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:57.0)"
    " Gecko/20100101 Firefox/57.0",
    "Accept": "*/*",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br",
    "DNT": "1",
    "Connection": "keep-alive",
    "Pragma": "no-cache",
    "Cache-Control": "no-cache"
}


def downloadM3u8(m3u8url, headers=HEADERS, depth=0):
    """ recursively download m3u8 files"""
    if not os.path.isdir(OUTPUT_FOLDER):
        os.mkdir(OUTPUT_FOLDER)
    base_url = '/'.join(m3u8url.split('/')[0:-1]) + '/' # get the base url
    print('processing: {}'.format(m3u8url))
    m3u8 = requests.get(m3u8url, headers=HEADERS) # get the m3u8 file
    folder = m3u8url.split('/')[-2] # get the filename
    parent_folder = None
    if depth > 0:
        parent_folder = m3u8url.split('/')[-3]
    filename = m3u8url.split('/')[-1].split('?')[0] # get the filename
    path_parts = list(filter(lambda x : x is not None, [
        OUTPUT_FOLDER,
        parent_folder,
        folder,
    ]))

    target_path = os.path.join(*path_parts, filename)

    if not os.path.isdir(os.path.join(*path_parts)):
        os.mkdir(os.path.join(*path_parts))
    with open(target_path, 'wb') as f:
        print('writing file to {}'.format(target_path))
        f.write(m3u8.content)
    ts_urls = extractTsUrls(m3u8) # get all the .ts urls
    print('ts_urls', ts_urls)
    # list the .ts files if they exist in the dir
    # list contents of the directory
    ts_target_dir = os.path.join(*path_parts)
    ts_files = set(filter(lambda x: '.ts' in x, os.listdir(ts_target_dir)))
    print('all ts files existing: {}'.format(ts_files))
    if len(ts_files) > 0:
        ts_urls = list(filter(lambda x: x.split('?')[0] not in ts_files, ts_urls))
    for ts in ts_urls:
        ts_url = base_url + ts
        print('downloading: {}'.format(ts_url))
        ts_filename = ts.split('?')[0]
        ts_file = requests.get(ts_url, headers=HEADERS)
        with open(os.path.join(*path_parts, ts_filename), 'wb') as f:
            f.write(ts_file.content)
    child_urls = extractM3u8Urls(m3u8) # get all the urls in the m3u8 file
    all_urls = []
    print('child_urls', child_urls)
    for child in child_urls:
        new_url = base_url + child
        all_urls.append(new_url)
        subchildren = downloadM3u8(new_url, headers=HEADERS, depth=depth + 1)
        print('subchildren', subchildren)
        all_urls.extend(subchildren)
    return all_urls

def extractTsUrls(m3):
    """ get a list of .ts urls from the m3u8 file """
    lines = m3.text.split('\n')
    urls = []
    for line in lines:
        if '.ts' in line:
            urls.append(line)
    return urls

def extractM3u8Urls(m3):
    """ get a list of m3u8 urls from the m3u8 file """
    lines = m3.text.split('\n')
    urls = []
    for line in lines:
        if '.m3u8' in line:
            urls.append(line)
    return urls

if __name__ == "__main__":
    downloadM3u8(sys.argv[0], headers=HEADERS)
    print('done')

© www.soinside.com 2019 - 2024. All rights reserved.