将bilibili缓存的m4s音视频文件合并(基于ffmpeg/含xml弹幕转ass/附exe程序)

将bilibili缓存的m4s音视频文件合并(基于ffmpeg/含xml弹幕转ass/附exe程序)

全水平向:萌新大佬都可食用
B站上视频资源很多,无论你是看番还是学习,它都能很大程度上满足你。可如果想下载B站上的视频方便随时观看 或是为了防止b站上的视频被删而保存到自己的设备上,又该如何操作呢?
首先下载b站上的视频官方的途径只有手机端的缓存(直接点app视频播放页面下的缓存按钮,或点击右上角“…”调出菜单再从里面点缓存)。我也比较推荐直接在手机端缓存后再复制到电脑或别的地方,毕竟官方渠道,稳定且下载速度快,操作简单。

###更新版本v1.3###
1.全新GUI;
2.所有资源文件都打包进exe中,且体积进一步缩小;
3.新增通用模式和兼容模式
4.exe及源码都在网盘链接里,快来一起学习吧
#################

那么现在切入主题…(现成程序的下载链接请往下翻)
现在(2020年)直接从b站缓存的视频都是video.m4s+audio.m4s音视频分开的形式,同时缓存的弹幕文件也是xml格式(仅部分视频软件可以读取显示),于是我的想法就是利用现在性能最好的通用音视频编码器ffmpeg实现快速合并,弹幕格式转换就用GitHub上一大佬@m13253 之前发布的的danmaku2ass源码。
xml转ass的python源码danmaku2ass.py:danmaku2ass.py

网上关于利用ffmpeg合并视频的方法都要求使用者电脑安装了ffmpeg,直接利用cmd输入指令。这样既不便于新人操作也不便于移植,这里我直接把安装的ffmpeg复制出来,删掉一些用不上的组件后内嵌到软件里;
大小只有186MB,而且可移植,让合并软件在未安装ffmpeg的电脑上也能正常运行:将bilibili缓存的m4s音视频文件合并(基于ffmpeg/含xml弹幕转ass/附exe程序)_第1张图片

然后用python(我用的是较新的版本python3.8.1,v3以上都可)写主程序代码,实现对内嵌ffmpeg和danmaku2ass文件的调用,主程序代码如下:
1.程序只使用os,json,time 3个模组

import os
import json
import time

2.获取文件路径,检测danmaku2ass文件

if __name__ == '__main__':
    path = "..\\"
    save_path = "..\\bili_merge"
    # 与用户交互获取对象路径
    print("---自动扫描 程序文件夹 所在目录下的可合并文件(输入‘1’)\n---手动输入 需扫描文件夹 的路径(输入‘2’)\n---退出程序(输入除1,2外的任何字符):")
    a = input("---")
    if a == '1':pass
    elif a == '2':
        path = input("请在这里输入 缓存视频所在文件夹 的路径:").replace("/","\\\\")
        save_path = f"{path}\\bili_merge"
    else:os._exit(0)
    source1_path = os.path.abspath("./ffmpeg/tools/ffmpeg/bin/ffmpeg.exe")
    source2_path = "./danmaku2ass.py"
    # 检测danmaku2ass.py文件是否在指定路径
    try:
        import danmaku2ass
        switch = 1
        print("danmaku2ass.py文件检测成功,自动开启弹幕转换","\n")
    except ModuleNotFoundError:
        print("未检测到弹幕转换资源文件!","\n")
        switch = 0

3.利用os.walk()函数获取所以文件的路径

    # 所有目录名和需要转换的文件名
    all_title = []
    all_video = []
    all_audio = []
    all_danma = []
    # a:所在根目录,b:根目录下所有文件夹(列表形式),c:根目录下所有文件(列表形式)
    for k, (a, b, c) in enumerate(os.walk(path)):
        # 因为os.walk()是树检索,所以3类文件会一一对应
        for i in c:
            if i == 'entry.json':
                title_path = os.path.join(a, i)
                all_title.append(title_path)
            elif i == "video.m4s":
                video_path = os.path.join(a, i)
                all_video.append(video_path)
            elif i == "audio.m4s":
                audio_path = os.path.join(a, i)
                all_audio.append(audio_path)
            elif i == "danmaku.xml":
                danma_path = os.path.join(a, i)
                all_danma.append(danma_path)

4.显示提示信息,创建bili_merge文件夹,准备开始转码

    num = len(all_title)
    if num == 0:
        print("未找到可合并文件,请检查路径或文件格式。")
        time.sleep(30)
        os._exit(0)
    os.makedirs(f"{save_path}", exist_ok=True)
    print("共检测到 %s 个待合并文件\n合并进程已开始,请耐心等待~~~"%num,"\n")

5.按照之前获取的文件路径循环。读取entry文件对文件进行命名和分组;os.system()调用shell脚本带参执行内嵌的ffmpeg.exe进行音视频合并;调用danmaku2ass.Danmaku2ASS()函数进行xml转ass(这里的参数我已经调试过,如有其他需求可以自行修改)

    failed = 0
    tabel = str.maketrans("","",'''\/:*?"<>| ''')
    # 一个个打开对应路径文件
    for i, j in enumerate(all_title):
        #解析entry.json文件
        with open(j, encoding='utf-8') as data:
            title_ = json.load(data)
            # 目录名
            title1 = title_["title"].translate(tabel)
            # 视频名
            try:
                title2 = title_.get("ep","N/A")
                if title2 == "N/A":title2 = title_["page_data"]["part"].translate(tabel)
                else:
                    try:
                        index = int(title2['index'])
                        title2 = f"EP{index}_"+title2["index_title"].translate(tabel)
                    except ValueError:
                        title2 = title2['index']
            except KeyError:
                title2 = title1
            print(f"输出目录:{title1}")
            print(f"输出文件:{title2}.mp4......")
            _path = f"{save_path}\\{title1}"
            os.makedirs(_path, exist_ok=True)
            cmd1 = f'{source1_path} -i {all_video[i]} -i {all_audio[i]} -c copy \"{_path}/{title2}.mp4'
            # python调用Shell脚本执行cmd命令
            os.system(cmd1)
            # 调用danmaku2ass内建函数将xml弹幕文件转换成ass格式(弹幕参数在这里调)
            if switch==1:
                os.makedirs(f"{_path}/danmuAss", exist_ok=True)
                danmaku2ass.Danmaku2ASS(f"{all_danma[i]}","Bilibili",f"{_path}/danmuAss/{title2}.ass",1080,720,\
                                        reserve_blank=480,font_size=23.0, text_opacity=0.6, duration_marquee=12.0, duration_still=6.0)
                #备用代码1#cmd2 = f'python {source2_path} {all_danma[i]} -o {_path}/danmuAss/{title2}.ass -s 1080x720 -a 0.5 -fs 22 -dm 12 -ds 6 -p 480'
                #备用代码2#os.popen(cmd2)
            #检测视频文件是否成功合并并输出
            if f"{title2}.mp4" in os.listdir(_path):
                print("*" * 15, f"已完成{i+1-failed}个文件", "*" * 15,"\n")
            else:
                print("*" * 15, "合并失败或终止", "*" * 15,"\n")
                failed += 1

6.打印完成提示,并于30s后自动关闭窗口

    print("当前任务已完成!")
    time.sleep(30)
    os._exit(0)

代码在Windows和Unix运行没有问题,其他操作系统目前还不清楚,水平高的可以针对其他系统自己改写

将程序打包成exe,没有运行环境要求
打包用的pyinstaller,很方便(利用windows powershell下的chocolatey安装,具体使用方法自行百度)

下面是我打包好可以直接使用的软件:
★★★百度网盘下载链接(提取码:cxit)★★★

▪操作图示(我是直接把程序文件夹与视频缓存文件夹放在一个目录下,这样程序会自动添加待合并视频; 你也可以选择手动输入扫描路径):
将bilibili缓存的m4s音视频文件合并(基于ffmpeg/含xml弹幕转ass/附exe程序)_第2张图片
将bilibili缓存的m4s音视频文件合并(基于ffmpeg/含xml弹幕转ass/附exe程序)_第3张图片
将bilibili缓存的m4s音视频文件合并(基于ffmpeg/含xml弹幕转ass/附exe程序)_第4张图片

▪软件展示(还没有添加用户图形页面,所以软件运行页面就是一个shell:
将bilibili缓存的m4s音视频文件合并(基于ffmpeg/含xml弹幕转ass/附exe程序)_第5张图片
将bilibili缓存的m4s音视频文件合并(基于ffmpeg/含xml弹幕转ass/附exe程序)_第6张图片
将bilibili缓存的m4s音视频文件合并(基于ffmpeg/含xml弹幕转ass/附exe程序)_第7张图片
第一次打包程序发文章,如果上面有错误或者程序不能正常运行请及时通过软件说明里的qq联系我或直接在这里留言。另外软件我也会定期更新,敬请关注。

更新于2020/7/25

你可能感兴趣的:(bilibili,缓存视频合并,m4s)