重庆分公司,新征程启航
为企业提供网站建设、域名注册、服务器等服务
本篇文章给大家分享的是有关利用ffmpeg+Python实现MP4格式音频与视频的合并的方法,小编觉得挺实用的,因此分享给大家学习,希望大家阅读完这篇文章后可以有所收获,话不多说,跟着小编一起来看看吧。
创新互联10多年成都定制网站服务;为您提供网站建设,网站制作,网页设计及高端网站定制服务,成都定制网站及推广,对成都门帘等多个方面拥有多年的网站设计经验的网站建设公司。此电脑--属性--高级系统设置--环境变量
在系统变量(也就是下面那一半)处找到新建,按如下所示的方法填写
再将%FFMPEG_HOME%
以及%FFMPEG_HOME%\bin
写入系统变量的Path中
然后一路确定即可
win+R,cmd
输入ffmpeg -version
对于我将B站PC端缓存的音频mp4和视频mp4文件合并的需求,需要用到的命令为:ffmpeg.exe -i audio1.mp4 -i video.mp4 -acodec copy -vcodec copy output.mp4
可以把mp4的文件设置成绝对路径,这样就可以转换指定路径的文件以及保存到指定路径了,比如这样:ffmpeg.exe -i "E:\哔哩哔哩视频\ss27993\77413703\1\audio1.mp4" -i "E:\哔哩哔哩视频\ss27993\77413703\1\video.mp4" -acodec copy -vcodec copy "E:\B站导出视频\Dr.STONE石纪元\第22话宝物.mp4
通过PC端缓存的未合并的视频和音频,全都是命名为video.mp4和audio.mp4
PS:有些兄弟是导出的手机端缓存的视频和音频,是m4s格式的,方法也一样
但光有这条命令还不够,需要自己手动一个个操作,太麻烦了
因此我还需要使用Python来自动帮我完成工作
虽然Python可以实现自动化,减少时间的浪费,但最快的还是以后记得缓存时勾选自动合并
PC端缓存的视频保存的文件结构有很多种,我只是根据我碰到的情况写的,但大同小异,修改起来也不麻烦,只是再加个if和else罢了
缓存的番剧是这种结构:
上面举的例子是Dr.stone石纪元,我缓存的鬼灭之刃也是如此
特点是在一个以视频ID号名称的文件夹(ss27993)后,跟着许多子文件夹(57983089等),然后在这些子文件夹中又有一个或多个子文件夹(比如1),然后缓存的视频保存在这个文件夹里,里面有一个info文件(就是json格式),还有audio1.mp4和video.mp4。
PS:
还有一个xml文件,是弹幕信息,暂时我不知道怎么处理
除了番剧,一般的视频缓存的结构是这样的
不难看出,这比番剧要少一个层级
文件信息主要由info文件和dvi文件来记录
这两种文件都可以直接以json文件来处理,也就是,首先open函数打开文件,然后用json.load转成字典。。。
然后我还发现了一个特点是,视频和音频所在的目录下是info文件,而它的上一层目录下是dvi文件
虽然文件格式基本是一致的,但是里面的键-值关系却不一致,单集视频的名称在番剧中对应的是键Description
,在其他视频中对应的是PartName
视频总的名称保存在外层的目录下的info文件或dvi文件中,番剧中对应的键是SeasonTitle
,在其他视频中对应的是Title
具体问题具体分析,首先由于我实践得较少,这样的总结不一定对,然后以后也许也会有新的格式、新的变化
以下是我的Python代码,你可以先试试能不能用,用不了的话,可以在理解的基础上修改。理解不了的话可以看我的后面的解释,以及代码中的注释,对于运行过程中一些变量的值,我都把它放在注释中了,方便你理解。
# -*- coding = utf-8 -*- # @time:2020/10/17/017 23:09 # Author:cyx # @File:main.py.py # @Software:PyCharm # 从.info文件中获得了Title信息,但是如果其中有某些特殊字符,保存时可能出现问题 def get_correct_title(title): error_set = ['/', '\\', ':', '*', '?', '"', '|', '<', '>', '\b', ' ', '.'] correct_title = title # print(title) for c in correct_title: if c in error_set: correct_title = correct_title.replace(c, '') return correct_title def popen(cmd): # https://blog.csdn.net/qq_41451161/article/details/82901235 try: popen = subprocess.Popen(cmd, stdout=subprocess.PIPE) popen.wait() lines = popen.stdout.readlines() return [line.decode('gbk') for line in lines] except BaseException as e: return -1 if __name__ == '__main__': import os import json import subprocess # ffmpeg -i video.m4s -i audio.m4s -c:v copy -c:a aac -strict experimental output.mp4 # ffmpeg.exe -i audio1.mp4 -i video.mp4 -acodec copy -vcodec copy output.mp4 AVhao = input("请输入视频AV号:") superPath = "E:\\哔哩哔哩视频" + "\\" + AVhao partDirs = [] # 保存每P视频所在的文件夹路径 paths = os.listdir(superPath) # 获取当前路径下所有的文件(包括文件夹)名称 # paths = ['8','9'] # 有时候,会莫名其妙的少了几个视频,可以通过重载来重新加载缺失的视频 # print(paths) # paths # ['27993.info', '57983089', '58612211', '59811008', '60862133', '61898240', '62925012', '64005445', '65020725', '66013155', '66808912', '67587875', '68398229', '69175748', '70021307', '70873680', '71617211', '73379440', '74051851', '74974157', '75746600', '76619409', '77413703', '78266594', '79070874', 'cover.jpg', 'desktop.ini'] # 获取每P视频所在的文件夹路径 savePos = '' seq = [] # 鉴于有些up主命名时毫无规律,导出后无法正常排序,只能手动排序了 # 根据AV号名文件夹下的子文件夹的名称进行排序,但是番剧的话不是这样排序,不过番剧单集的名称很规范,不需要这样 for p in paths: if '.' not in p: seq.append(p) if 'info' in p: # print(p) # p: # 27993.info info = superPath + "\\" + p with open(info, 'r', encoding='utf-8') as load_f: load_dict = json.load(load_f) projectTitle = load_dict['SeasonTitle'] projectTitle = get_correct_title(projectTitle) savePos = 'E:\\B站导出视频\\' + projectTitle print('savePos: ', savePos) if 'dvi' in p: # print(p) # P: # 328738595.dvi dvi = superPath + "\\" + p with open(dvi, 'r', encoding='utf-8') as load_f: load_dict = json.load(load_f) projectTitle = load_dict['Title'] projectTitle = get_correct_title(projectTitle) savePos = 'E:\\B站导出视频\\' + projectTitle print('savePos: ', savePos) # 防止文件存在时再次生成该文件夹出现错误 try: os.mkdir(savePos) break except: pass subDir = superPath + "\\" + p if os.path.isdir(subDir): # print(subDir) # 所有子文件夹的路径保存在partDirs中 partDirs.append(subDir) # print("partDirs: ",partDirs) # partDirs: ['E:\\哔哩哔哩视频\\ss27993\\57983089', 'E:\\哔哩哔哩视频\\ss27993\\58612211', 'E:\\哔哩哔哩视频\\ss27993\\59811008', 'E:\\哔哩哔哩视频\\ss27993\\60862133', 'E:\\哔哩哔哩视频\\ss27993\\61898240', 'E:\\哔哩哔哩视频\\ss27993\\62925012', 'E:\\哔哩哔哩视频\\ss27993\\64005445', 'E:\\哔哩哔哩视频\\ss27993\\65020725', 'E:\\哔哩哔哩视频\\ss27993\\66013155', 'E:\\哔哩哔哩视频\\ss27993\\66808912', 'E:\\哔哩哔哩视频\\ss27993\\67587875', 'E:\\哔哩哔哩视频\\ss27993\\68398229', 'E:\\哔哩哔哩视频\\ss27993\\69175748', 'E:\\哔哩哔哩视频\\ss27993\\70021307', 'E:\\哔哩哔哩视频\\ss27993\\70873680', 'E:\\哔哩哔哩视频\\ss27993\\71617211', 'E:\\哔哩哔哩视频\\ss27993\\73379440', 'E:\\哔哩哔哩视频\\ss27993\\74051851', 'E:\\哔哩哔哩视频\\ss27993\\74974157', 'E:\\哔哩哔哩视频\\ss27993\\75746600', 'E:\\哔哩哔哩视频\\ss27993\\76619409', 'E:\\哔哩哔哩视频\\ss27993\\77413703', 'E:\\哔哩哔哩视频\\ss27993\\78266594', 'E:\\哔哩哔哩视频\\ss27993\\79070874'] videoPos = '' i = 0 for p in partDirs: # print(p) # 列出子文件夹中的所有文件 sublist = os.listdir(p) # 检查info文件是否在当前子文件夹中 for file in sublist: # print(file) # file: # 1 # 57983089. # dvi # cover.jpg # desktop.ini if 'info' in file: infoPos = p + "\\" + file videoPos = p else: subsubDir = p + "\\" + file if os.path.isdir(subsubDir): # print(subsubDir) # subsubDir: E:\哔哩哔哩视频\ss27993\57983089\1 subsubList = os.listdir(subsubDir) for subsubFile in subsubList: if 'info' in subsubFile: infoPos = subsubDir + "\\" + subsubFile videoPos = subsubDir break with open(infoPos, 'r', encoding='utf-8') as load_f: load_dict = json.load(load_f) if 'ss' in AVhao: videoTitle = load_dict['Description'] else: videoTitle = load_dict['PartName'] videoTitle = get_correct_title(videoTitle) print('videoTitle: ', videoTitle) videoDir = videoPos + "\\" + 'video.mp4' audioDir = videoPos + "\\" + 'audio1.mp4' # print('videoDir: ', videoDir) # print('audioDir: ', audioDir) # videoDir: E:\哔哩哔哩视频\ss27993\74051851\1\video.mp4 # audioDir: E:\哔哩哔哩视频\ss27993\74051851\1\audio1.mp4 if 'ss' in AVhao: outDir = savePos + "\\" + videoTitle + '.mp4' else: outDir = savePos + "\\" + seq[i] + '_' + videoTitle + '.mp4' i += 1 # 对于那些命名很规范的视频,可以不用自己再排序,进行一下重载,不规范的视频再把这句注释掉就好 outDir = savePos + "\\" + videoTitle + '.mp4' # command = 'cd ' + superPath + '\\64 && ' # && 多名命令 # command = 'cd ' + 'E:\\ProgramFiles\\ffmpeg' + ' && ' command = 'E:\\FFmpeg\\bin\\ffmpeg.exe -i ' + '"' + audioDir + '"' ' -i ' + '"' + videoDir + '"'+ ' -acodec copy -vcodec copy ' + '"' + outDir + '"' # print("保存地址",outDir) # 保存地址 E:\B站导出视频\[Lynda视频]音频录制录音技巧教程(中英双语字幕)全集130课时AudioRecordingTechniques混音录音棚音乐工作室歌曲调音\98录制独奏萨克斯演奏技巧二.mp4 # print(command) # command = 'E:\\FFmpeg\\bin\\ffmpeg.exe -i "E:\哔哩哔哩视频\ss27993\77413703\1\audio1.mp4" -i "E:\哔哩哔哩视频\ss27993\77413703\1\video.mp4" -acodec copy -vcodec copy "E:\B站导出视频\Dr.STONE石纪元\第22话宝物.mp4' # os.system(command) popen(command) # ffmpeg.exe -i audio1.mp4 -i video.mp4 -acodec copy -vcodec copy output.mp4 break