1、环境
首先安装mkvtoolnix,对应文件如下:
题外话:
这里面的mmg.exe就是mkvmergeGUI,一开始踩坑了,就是找不到mkvmergeGUI的下载(要么下载的都没有mmg.exe,要么就是最后发觉mmg.exe就是),里面的mkvmerge.exe也不是。
这里主要讲的是mkvextractGUI(其实是因为我mkvmergeGUI没写完,后续mkvmergeGUI肯定是同理的)。装了mkvtoolnix不够,还要下载mkvextractGUI:
然后点开mkvextractGUI.exe,配置好对应mkvtoolnix的路径(mkvmergeGUI倒是不用配置),要是手动实现mkv视频转换的话生成文件的路径也可以配置,如下:
2、程序
程序所在目录结构如下:
所有涉及路径的都不能带中文(包括mkvtoolnix、mkvextractGUI的路径),因为只有cmd中直接输入命令执行带中文才没事。py执行命令,或者cmd/py执行.bat带中文路径都会出错。
after_conversion 转换后存储的目录
before_conversion 转换前mkv视频存放的目录
command.txt 写命令行模板语句,我这里用的是:
"[gMKVExtractGUI]C:\my_download\mkv_split\mkvtoolnix\mkvextract.exe" tracks {%需要提取的mkv目录%} --ui-language en 0:{%转换后的avc目录%} 1:{%转换后的aac目录%}
然后弄了下面两版批量转换程序
1、直接执行版
# mkvtoolnix、gMKVExtractGUI、mkvmerge、程序本身等所有路径都不能有中文(只有cmd窗口输入带中文命令倒是没问题,cmd执行.bat也不行)
import os, shutil, time
import subprocess
from copy import deepcopy
# 使用 gMKVExtractGUI 命令行
def gMKVExtractGUI_command(command_moban):
# gMKVExtractGUI命令行
command_moban = command_moban.replace("[gMKVExtractGUI]", "")
for it in mkv_list:
# 深拷贝
new_command_moban = deepcopy(command_moban)
# 对每个需要转换的mkv视频都创建一个文件夹保存
tra_mkv_dir = f"{tra_dir}\\{it}"
os.mkdir(tra_mkv_dir)
# 需要转换的 mkv 文件
new_command_moban = new_command_moban.replace("{%需要提取的mkv目录%}", f'"{mkv_dir}\\{it}"')
# 文件名
file_name = ".".join(it.split(".")[:-1])
# 需要转换后的文件拓展名
if "avc" in new_command_moban:
# 两种形式都要
if "aac" in new_command_moban:
new_command_moban = new_command_moban.replace("{%转换后的avc目录%}", f'"{tra_mkv_dir}\\{file_name}.avc"')
command = new_command_moban.replace("{%转换后的aac目录%}", f'"{tra_mkv_dir}\\{file_name}.aac"')
# 只要.avc
else:
command = new_command_moban.replace("{%转换后的avc目录%}", f'"{tra_mkv_dir}\\{file_name}.avc"')
elif "aac" in new_command_moban:
# 两种形式都要
if "avc" in new_command_moban:
new_command_moban = new_command_moban.replace("{%转换后的avc目录%}", f'"{tra_mkv_dir}\\{file_name}.avc"')
command = new_command_moban.replace("{%转换后的aac目录%}", f'"{tra_mkv_dir}\\{file_name}.aac"')
# 只要.aac
else:
command = new_command_moban.replace("{%转换后的aac目录%}", f'"{tra_mkv_dir}\\{file_name}.aac"')
subprocess.Popen(command).wait()
# 使用 mkvmergeGuI 命令行
def mkvmergeGuI_command(command_moban):
#整理中...
pass
# 创建不多于10条命令行语句
def create_command():
with open(f"{exe_dir}\\command.txt", "r", encoding='utf-8') as f:
command_moban = f.read()
if "[gMKVExtractGUI]" in command_moban:
gMKVExtractGUI_command(command_moban)
# 待补充
# elif "[mkvmergeGuI]" in command_moban:
# mkvmergeGuI_command(command_moban)
if __name__ == '__main__':
# 程序所在目录
exe_dir = os.getcwd()
# 前处理
mkv_dir = f"{exe_dir}\\before_conversion"
mkv_list = os.listdir(mkv_dir)
tra_dir = f"{exe_dir}\\after_conversion"
# 为防止报错,提前将该文件夹清空( os.rmdir 无法删除非空文件夹,且无法删除文件,改用 shutil.rmtree)
tra_list = os.listdir(tra_dir)
if len(tra_list) != 0:
for it in tra_list:
shutil.rmtree(f"{tra_dir}\\{it}")
t1 = time.time()
create_command()
t2 = time.time()
print(f"总共用时 {t2-t1} s")
2、创建.bat再执行的
一开始想的就这版,后来想了想直接执行语句试试,发觉也可以,就不用这个额外消耗的了,而且这版大概比上面的慢了3%左右。但是总不能直接删了,一起上传当个纪念吧(
# 程序批量生成 .bat 格式 window 批处理文件,每个 .bat 包含不多于10条的 mkv 视频转换命令语句。
# 程序执行 .bat 文件,执行完毕自动删除 .bat 文件
# mkvtoolnix、gMKVExtractGUI、mkvmerge、程序本身等所有路径都不能有中文,否则程序执行.bat会出错(只有cmd窗口输入带中文命令倒是没问题,cmd执行.bat也不行)
import os, shutil, time
import subprocess
from copy import deepcopy
# 使用 gMKVExtractGUI 命令行
def gMKVExtractGUI_command(command_moban):
# gMKVExtractGUI命令行
command_moban = command_moban.replace("[gMKVExtractGUI]", "")
# 计数器
count = 0
command_list = []
for it in mkv_list:
# 深拷贝
new_command_moban = deepcopy(command_moban)
# 对每个需要转换的mkv视频都创建一个文件夹保存
tra_mkv_dir = f"{tra_dir}\\{it}"
os.mkdir(tra_mkv_dir)
# 需要转换的 mkv 文件
new_command_moban = new_command_moban.replace("{%需要提取的mkv目录%}", f'"{mkv_dir}\\{it}"')
# 文件名
file_name = ".".join(it.split(".")[:-1])
# 需要转换后的文件拓展名
if "avc" in new_command_moban:
# 两种形式都要
if "aac" in new_command_moban:
new_command_moban = new_command_moban.replace("{%转换后的avc目录%}", f'"{tra_mkv_dir}\\{file_name}.avc"')
command = new_command_moban.replace("{%转换后的aac目录%}", f'"{tra_mkv_dir}\\{file_name}.aac"')
# 西药.avc
else:
command = new_command_moban.replace("{%转换后的avc目录%}", f'"{tra_mkv_dir}\\{file_name}.avc"')
elif "aac" in new_command_moban:
# 两种形式都要
if "avc" in new_command_moban:
new_command_moban = new_command_moban.replace("{%转换后的avc目录%}", f'"{tra_mkv_dir}\\{file_name}.avc"')
command = new_command_moban.replace("{%转换后的aac目录%}", f'"{tra_mkv_dir}\\{file_name}.aac"')
# 只要.aac
else:
command = new_command_moban.replace("{%转换后的aac目录%}", f'"{tra_mkv_dir}\\{file_name}.aac"')
command_list.append(command)
count += 1
# 当需要转换数量达到整 10 ,或者循环完毕,yield 出去
if ((count % 10) == 0) or (it == mkv_list[-1]):
yield command_list
# 重置列表
command_list.clear()
# 使用 mkvmergeGuI 命令行
def mkvmergeGuI_command(command_moban):
#整理中...
pass
# 创建不多于10条命令行语句
def create_command():
with open(f"{exe_dir}\\command.txt", "r", encoding='utf-8') as f:
command_moban = f.read()
if "[gMKVExtractGUI]" in command_moban:
# 获取到一个不多于10条命令行语句的生成器
command_list = gMKVExtractGUI_command(command_moban)
bat_tra(command_list)
# 待补充
# elif "[mkvmergeGuI]" in command_moban:
# # 获取到一个不多于10条命令行语句的生成器
# command = mkvmergeGuI_command(command_moban)
# 创建 .bat 格式 window批处理文件、执行
def bat_tra(command_list):
num = 1
for it in command_list:
command = "\n".join(it)
with open(f"{exe_dir}\\File_Transfer_Station\\{num}.bat", "w", encoding='utf-8') as f:
f.write(command)
# 执行命令
sub = subprocess.Popen(f"{exe_dir}\\File_Transfer_Station\\{num}.bat")
sub.wait()
num += 1
if __name__ == '__main__':
# 程序所在目录
exe_dir = os.getcwd()
# 创建”File_Transfer_Station“,用于存储.bat文件
exe_dir_list = os.listdir()
if "File_Transfer_Station" not in exe_dir_list:
os.mkdir(f"{exe_dir}\\File_Transfer_Station")
else:
# 为防止误删原有“文件中转站”内容,程序中断退出
raise Exception('已存在"File_Transfer_Station"文件夹')
# 前处理
mkv_dir = f"{exe_dir}\\before_conversion"
mkv_list = os.listdir(mkv_dir)
tra_dir = f"{exe_dir}\\after_conversion"
# 为防止报错,提前将该文件夹清空( os.rmdir 无法删除非空文件夹,且无法删除文件,改用 shutil.rmtree)
tra_list = os.listdir(tra_dir)
if len(tra_list) != 0:
for it in tra_list:
shutil.rmtree(f"{tra_dir}\\{it}")
t1 = time.time()
create_command()
t2 = time.time()
print(f"总共用时 {t2-t1} s")
# 程序执行完毕,自动删除中转站文件夹(含里面的.bat文件)
shutil.rmtree(f"{exe_dir}\\File_Transfer_Station")
命令行的来源:
1、mkvextractGUI的
使用gMKVExtractGUI批量提取MKV音轨和字幕-百度经验
这也是为什么一开始想的也是批量创建.bat,执行然后再程序自动删除……
2、mkvmergeGui的
直接就有个“复制命令行”
附一句,这批量生成mkv视频用来测试,差点原地爆炸