py配合mkvextractGUI实现mkv视频批量拆分

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视频用来测试,差点原地爆炸

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值