运维日志您现在的位置是:首页 > 博客日志 > 运维日志

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

<a href='mailto:'>微wx笑</a>的头像微wx笑 2025-02-23运维日志14 0 0关键字: m3u8  mp4  bat  批处理  

这里介绍一个Windows批处理脚本(Windows Batch Script),主要用于处理 .m3u8 ts 视频文件的下载和合并功能。以下是程序的主要功能和逻辑流程:功能概述参数检查与路径处理: 检查

无知人生,ivu4e.com,ivu4e.cn

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


bSX无知

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

功能概述

  1. bSX无知

  2. bSX无知

    参数检查与路径处理bSX无知

    bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

  3. bSX无知

  4. bSX无知

    文件处理逻辑bSX无知

    bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

  5. bSX无知

  6. bSX无知

    文件下载bSX无知

    bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

      下载的文件会保存到当前目录。bSX无知

      bSX无知

    • bSX无知

  7. bSX无知

  8. bSX无知

    文件合并bSX无知

    bSX无知

    • bSX无知

    • bSX无知

      使用 ffmpeg 将下载的文件片段(如 .ts 文件)合并为一个完整的视频文件(如 .mp4 文件)。bSX无知

      bSX无知

    • bSX无知

  9. bSX无知

  10. bSX无知

    清理操作bSX无知

    bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

  11. bSX无知

  12. bSX无知

    错误处理与用户交互bSX无知

    bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

详细逻辑流程

  1. bSX无知

  2. bSX无知

    参数检查bSX无知

    bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

  3. bSX无知

  4. bSX无知

    目录切换bSX无知

    bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

  5. bSX无知

  6. bSX无知

    解析 .m3u8 文件bSX无知

    bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

  7. bSX无知

  8. bSX无知

    文件下载bSX无知

    bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

      下载的文件会保存到当前目录。bSX无知

      bSX无知

    • bSX无知

  9. bSX无知

  10. bSX无知

    文件合并bSX无知

    bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

  11. bSX无知

  12. bSX无知

    清理操作bSX无知

    bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

  13. bSX无知

  14. bSX无知

    错误处理与用户交互bSX无知

    bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

    • bSX无知

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

      bSX无知

    • bSX无知

应用场景

  • bSX无知

  • bSX无知

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

    bSX无知

  • bSX无知

  • bSX无知

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

    bSX无知

  • bSX无知

  • bSX无知

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

    bSX无知

注意事项

  • bSX无知

  • bSX无知

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

    bSX无知

  • bSX无知

  • bSX无知

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

    bSX无知

  • bSX无知

  • bSX无知

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

    bSX无知

完整的程序代码bSX无知

 bSX无知

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
@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

如何使用呢?bSX无知

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


bSX无知

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

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

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

1
2
3
4
Windows Registry Editor Version 5.00
 
[HKEY_CLASSES_ROOT\VLC.m3u8\shell\ts2mp4\command]
@="ts2mp4.bat \"%1\""

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

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

编写该bat文件遇到的坑:bSX无知

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

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


bSX无知

无知人生,ivu4e.com,ivu4e.cn

本文由 微wx笑 创作,采用 署名-非商业性使用-相同方式共享 4.0 许可协议,转载请附上原文出处链接及本声明。
原文链接:https://www.ivu4e.cn/blog/service/2025-02-23/2029.html

很赞哦! (0) 有话说 (0)

文章评论