从.m3u8到.mp4:使用批处理脚本完成视频处理的完整指南

这里介绍一个Windows批处理脚本(Windows Batch Script),主要用于处理 .m3u8 ts 视频文件的下载和合并功能。

以下是程序的主要功能和逻辑流程:

功能概述

  1. 参数检查与路径处理

    • 检查是否传递了文件或文件夹路径作为参数。

    • 判断传递的路径是文件还是文件夹,并根据路径切换到相应的目录。

  2. 文件处理逻辑

    • 如果目标目录中存在 .m3u8 文件(如 index.m3u8 或以当前目录名命名的 .m3u8 文件),程序会解析该文件。

    • 根据 .m3u8 文件中的内容,提取有效的文件链接(如 .ts 文件的 URL)。

  3. 文件下载

    • 使用 aria2c 工具批量下载 .m3u8 文件中列出的文件(如 .ts 文件)。

    • 下载的文件会保存到当前目录。

  4. 文件合并

    • 使用 ffmpeg 将下载的文件片段(如 .ts 文件)合并为一个完整的视频文件(如 .mp4 文件)。
  5. 清理操作

    • 提供选项删除下载的片段文件、临时文件(如 newindex.m3u8links.list 等)。

    • 根据用户选择,保留或删除这些文件。

  6. 错误处理与用户交互

    • 检查目标文件是否已存在,并提示用户是否需要重新生成。

    • 如果 .m3u8 文件或目标文件已存在,程序会询问用户是否覆盖。

    • 如果下载或合并过程中出现错误,程序会提示用户。

详细逻辑流程

  1. 参数检查

    • 如果未传递参数,程序提示用户并退出。

    • 如果传递了参数,程序会判断路径是文件还是文件夹。

  2. 目录切换

    • 如果路径是文件夹,程序切换到该文件夹。

    • 如果路径是文件,程序切换到文件所在的目录。

  3. 解析 .m3u8 文件

    • 程序会尝试解析 index.m3u8 或以当前目录名命名的 .m3u8 文件。

    • 提取文件链接(如 .ts 文件的 URL)并保存到 links.list 文件中。

    • 如果 .m3u8 文件中包含加密信息(如 AES-128 密钥链接),程序会提取并处理这些链接。

  4. 文件下载

    • 使用 aria2c 根据 links.list 文件中的链接批量下载文件。

    • 下载的文件会保存到当前目录。

  5. 文件合并

    • 使用 ffmpeg 将下载的文件片段(如 .ts 文件)合并为一个 .mp4 文件。

    • 提供多种 ffmpeg 命令选项,用户可以根据需要选择合适的命令。

  6. 清理操作

    • 提供选项删除下载的片段文件、临时文件(如 newindex.m3u8links.list 等)。

    • 用户可以选择保留或删除这些文件。

  7. 错误处理与用户交互

    • 如果目标文件已存在,程序会提示用户是否重新生成。

    • 如果 .m3u8 文件或目标文件已存在,程序会询问用户是否覆盖。

    • 如果下载或合并过程中出现错误,程序会提示用户。

应用场景

  • 该脚本主要用于处理视频片段的下载和合并,通常用于处理 .m3u8 格式的视频文件(如在线视频、直播回放等)。

  • 用户可以通过传递文件或文件夹路径作为参数,让脚本自动完成下载和合并操作。

  • 脚本提供了用户交互功能,允许用户根据需要选择是否覆盖文件或删除临时文件。

注意事项

  • 程序依赖于外部工具 aria2cffmpeg,需要确保这些工具已安装并配置在系统路径中。

  • 程序的逻辑较为复杂,涉及文件路径处理、文件下载、文件合并等多个步骤,需要谨慎使用。

  • 用户在运行脚本时需要确保传递的参数正确,否则可能导致程序无法正常运行。

完整的程序代码

@echo off
echo 正在处理文件:%~1
rem ~可以确保获取到的参数不包含多余的引号
rem 判断是否传递了参数
if "%~1"=="" (
    echo 未传递任何参数,请提供文件或文件夹路径。
    exit /b 1
)

rem 获取参数的属性
set "attribute=%~a1"
set "fpath=%~1"

rem 判断是否为文件夹
if "%attribute:~0,1%"=="d" (
    echo "%~1 是一个文件夹目录。"
    rem 这里可以添加处理文件夹的逻辑
    rem set "fpath=%~1"
) else if "%attribute:~0,1%"=="-" (
    echo "%~1 是一个文件路径。"
    rem 这里可以添加处理文件的逻辑
    set "fpath=%~dp1"
) else (
    echo "无法识别 %~1 是文件还是文件夹。"
    exit /b 1
)

echo 切换目录到 "%fpath%"
pushd "%fpath%"
if errorlevel 1 (
    echo "Error: Directory %~1 not found."
    pause
    exit /b
)
for %%i in (.) do set "curr=%%~ni"
echo "使用最后一级目录 %curr% 作为文件名"

rem 判断文件是否存在,如果存在询问用户是否删除重新生成
setlocal enableextensions enabledelayedexpansion

rem 检查 index.m3u8 文件是否存在
rem set "m3u8=index.m3u8"
set "m3u8=%curr%.m3u8"
if not exist "!m3u8!" (
    set "m3u8=index.m3u8"
)
echo "!m3u8!"

rem if exist "%curr%.mp4" (del /f "%curr%.mp4")
rem 定义目标文件路径,你可以根据实际情况修改

set "target_file=%curr%.mp4"

rem 检查目标文件是否存在
if exist "%target_file%" (

    :ask_user
    set /p "choice=目标文件 %target_file% 已存在,是否重新生成?(Y/N)(回车=是): "
    :: 检测用户输入
    if /i "!choice!"=="" (
        set "choice=Y" :: 如果用户直接回车,则设置默认值为 Y
    )
    if /i "!choice!"=="Y" (
        rem 用户选择重新生成,删除原有文件
        del /f "%target_file%"
        echo "已删除原有文件 %target_file%。"
    ) else if /i "!choice!"=="N" (
        echo 你选择不重新生成,程序将退出。
        goto ask_user3
        pause
        exit /b
    ) else (
        echo 无效的输入,请输入 Y 或 N。
        goto ask_user
    )
)


rem 如果 newindex.m3u8 文件存在则直接合并文件
if exist "newindex.m3u8" (
    :ask_user2
    set /p "choice=目标文件 newindex.m3u8 已存在,是否重新生成?(Y/N)(回车=是): "
    echo !choice!
    :: 检测用户输入
    if /i "!choice!"=="" (
        set "choice=Y" :: 如果用户直接回车,则设置默认值为 Y
    )
    if /i "!choice!"=="Y" (
        rem 用户选择重新生成,删除原有文件
        del /f newindex.m3u8
        del /f links.list
        echo 已删除原有文件 newindex.m3u8。
    ) else if /i "!choice!"=="N" (
        echo 你选择不重新生成,直接跳转到合并过程。
        goto ffmpeg_merge
    ) else (
        echo 无效的输入,请输入 Y 或 N。
        goto ask_user2
    )
)

set /a b=0
set /a fn=0
rem 遍历 index.m3u8 文件的每一行
for /f "usebackq delims=" %%a in ("!m3u8!") do (
    rem 去除可能的引号
    set "url=%%a"
    set "url=!url:"=!"
    
    rem 判断 url 是否为有效的文件链接(简单判断是否以 http 或 https 开头)
    if "!url:~0,4!"=="http" (
        rem 提取文件名
        for %%f in ("!url!") do set "filename=%%~nxf"
        if exist "!filename!" (
            rem 判断文件大小 for /f %%i in ('dir /b %%a') do if 0 lss %%~zi (echo file %%a >> newindex.m3u8)
            echo !filename! 文件已存在!
        ) else (
            echo !url! >> links.list
        )
        echo !filename! >> newindex.m3u8
    ) else (
        if "!b!"=="0" (
            if "!url:~0,30!"=="#EXT-X-KEY:METHOD=AES-128,URI=" (
                echo "!url!"
                set "uri=!url:~30!"
                set "uri=!uri:"=!"
                echo "uri=!uri!"
                if "!uri:~0,4!"=="http" (
                    if not exist "!uri!" (
                        echo !uri! >> links.list
                    )
                    set /a b+=1
                    echo #EXT-X-KEY:METHOD=AES-128,URI=key.key >> newindex.m3u8
                    rem 输出提取到的 URI
                    echo 提取到的 URI 是: !uri!
                    
                )
            )
            
            if "!b!"=="0" (
                rem echo !url! 不是有效的文件链接,跳过
                echo !url! >> newindex.m3u8
            )
        ) else (
            rem echo !url! 不是有效的文件链接,跳过
            echo .
            echo !url! >> newindex.m3u8
        )
    )
    set /a fn+=1
)

rem 设置包含下载链接的文本文件路径
set "links_file=links.list"
rem 设置下载文件保存的目录
set "download_dir=%cd%"
if exist "%links_file%" (
    rem 调用 aria2c 批量下载文件
    aria2c -i "%links_file%" -d "%download_dir%" -x 16 -s 8 -j 10 -c
    echo 调用 aria2c 批量下载完成!
)

:ffmpeg_merge
rem 如果 key.key 文件不存在,ffmpeg 不会报错,会继续执行
echo ffmpeg merge begin

ffmpeg -protocol_whitelist "file,crypto" -allowed_extensions ALL -threads auto -i "newindex.m3u8" -c copy -bsf:a aac_adtstoasc "%curr%.mp4"
rem ffmpeg -protocol_whitelist "file,crypto" -allowed_extensions ALL -i "newindex.m3u8" -c copy -bsf:a aac_adtstoasc "output.mp4"
rem ffmpeg -protocol_whitelist "file,crypto" -allowed_extensions ALL -threads auto -i "newindex.m3u8" -c copy "%curr%.mp4"
rem ffmpeg -protocol_whitelist "file,crypto" -allowed_extensions ALL -i "newindex.m3u8" -c:v libx264 -c:a aac "%curr%.mp4"
rem ffmpeg -f concat -safe 0 -protocol_whitelist "file,concat" -i newindex.m3u8 -c copy %curr%.mp4
if errorlevel 1 (
    echo Error: ffmpeg failed to merge files.
) else (
    echo "%curr%.mp4 合并成功!"
    :ask_user3
    set /p "choice=是否删除下载的切片文件?(Y/N)(回车=Y): "
    echo "!choice!"
    :: 检测用户输入
    if /i "!choice!"=="" (
        set "choice=Y" :: 如果用户直接回车,则设置默认值为 Y
    )
    if /i "!choice!"=="Y" (
        rem 用户选择重新生成,删除原有文件
        
        echo "!m3u8!"
        del /f *.ts
        rem 遍历 index.m3u8 文件的每一行
        for /f "usebackq delims=" %%a in ("!m3u8!") do (
            rem 去除可能的引号
            set "url=%%a"
            set "url=!url:"=!"
            rem 判断 url 是否为有效的文件链接(简单判断是否以 http 或 https 开头)
            if "!url:~0,4!"=="http" (
                rem 提取文件名
                for %%f in ("!url!") do set "filename=%%~nxf"
                echo !filename!
                if exist "!filename!" (
                    del /f "!filename!"
                )
            )
        )
        if exist "newindex.m3u8" (
            del /f newindex.m3u8
        )
        if exist "links.list" (
            del /f links.list
        )
        if exist "index.html" (
            del /f index.html
        )
        if exist "index.m3u8" (
            del /f index.m3u8
        )
        if exist "index.1.html" (
            del /f index.1.html
        )
        if exist "url.txt" (
            del /f url.txt
        )
        if exist "!m3u8!" (
            del /f "!m3u8!"
        )
        
    ) else if /i "!choice!"=="N" (
        echo 你选择不删除,程序即将退出!
        exit /b 0
    ) else (
        echo 无效的输入,请输入 Y 或 N。
        goto ask_user3
    )
)

endlocal
pause

如何使用呢?

将以上内容保存为 "ts2mp4.bat",放在系统目录下,比如:C:\Windows,这样你就可以在任何一个目录调用它了;

首先你得知道如何拿到视频的 .m3u8 文件的URL地址 ,下载到本地;

然后就可以使用上面的bat下载ts切片并合并为 mp4视频文件了,例如: ts2mp4 index.m3u8

你也可以将以下内容导入注册表:

Windows Registry Editor Version 5.00

[HKEY_CLASSES_ROOT\VLC.m3u8\shell\ts2mp4\command]
@="ts2mp4.bat \"%1\""

这样在 .m3u8 文件上点击鼠标右键时,就可以通过右键菜单的形成调用 ts2mp4 了;

该程序目前还存在一个问题 :如果 .m3u8 文件中的ts切片url地址是相对的,不是完整的url的话,无法实现下载;

编写该bat文件遇到的坑:

echo 后面输出的内容中有变量(并且变量中包含特殊字符,比如小括号)的情况必须使用双引号将输出内容括起来,否则即使程序没有执行到那一行,而是执行到那个程序块的话也是会报错停止执行,这给查找问题发生的位置带来不小的麻烦

bat的字符查找功能比较弱,要要找字符串的话实现起来比较麻烦;

相关推荐
lifire_H1 小时前
Canvas在视频应用中的技术解析
前端·javascript·音视频
LittleNyima2 小时前
【代码解读】阿里最新开源视频生成模型 Wan 2.1 实现解析
人工智能·stable diffusion·aigc·音视频
why***4 小时前
一键提取人声 、伴奏 免费人声、伴奏 音频分离软件分享——UVR5下载安装教程
音视频·uv
TLeung653674 小时前
非常好用的视频翻译软件,pyVideoTrans(将国外视频翻译为自己所用的软件),附带下载方法。
音视频
FeiCat Henry4 小时前
KGG转MP3工具|非KGM文件|解密音频
科技·算法·音视频·软件工程·视频编解码
寻道码路4 小时前
深度剖析 Video-RAG:厦门大学和罗切斯特大学联合推出的一种用于长视频理解的检索增强生成技术
人工智能·语言模型·开源·aigc·音视频·ai编程
LOLA44444 小时前
10种方法教你又小又清晰地压缩视频
音视频
linkcoco4 小时前
记录h5使用navigator.mediaDevices.getUserMedia录制音视频
前端·javascript·vue·音视频·js
Antonio9155 小时前
【音视频】音视频录制、播放原理
音视频
京河小蚁6 小时前
解决Moodo调节心情模块-大声喊出来无法测量出音频分贝
微信小程序·音视频·ai编程·cursor