Python批量合并处理B站视频

  最近想学习后端,又不想花钱,怎么办呢?于是在手机端B站(哔哩哔哩)上面找到了满意的免费视频教程,但是手机端看起来很不方便啊。于是,我通过在手机端缓存下来后,导入到了电脑端,但是我后面了发现两个问题:

  1.本来一集视频按理说一段吧,但是B站下载下来的视频并不是完整的一段,而是被分成了多段blv格式的视频,所以需要想办法把它们拼接成完整的一段视频!

  

  2.视频数量太大,不可能一个一个去修改,得想办法批量处理!(我这里有120个视频文件夹,下图所示,没显示完)

  

  基于上述两个问题,必须用一种方法快速解决!网上百度查了一些资料,觉得可行性很大,于是准备自己动手写代码来实现这一功能。人生苦短,我学Python!哈哈,就是Python没错了,话不多说,直接上自己用python写的批量合并并转换B站视频格式的源代码(已做详细的注释说明):

#批量合并特定文件夹下的视频文件,然后输出到指定文件夹下
# 主要是需要moviepy这个库
from moviepy.editor import *
import os
from natsort import natsorted
import json

# psutil是一个跨平台库能够轻松实现获取系统运行的进程和系统利用率(包括CPU、内存、磁盘、网络等)信息。它主要用来做系统监控,性能分析,进程管理。它实现了同等命令行工具提供的功能,如ps、top、lsof、netstat、ifconfig、who、df、kill、free、nice、ionice、iostat、iotop、uptime、pidof、tty、taskset、pmap等。目前支持32位和64位的Linux、Windows、OS X、FreeBSD和Sun Solaris等操作系统.
import psutil

# 杀死moviepy产生的特定进程
def killProcess():
    # 处理python程序在运行中出现的异常和错误
    try:
        # pids方法查看系统全部进程
        pids = psutil.pids()
        for pid in pids:
            # Process方法查看单个进程
            p = psutil.Process(pid)
            # print('pid-%s,pname-%s' % (pid, p.name()))
            # 进程名
            if p.name() == 'ffmpeg-win64-v4.1.exe':
                # 关闭任务 /f是强制执行,/im对应程序名
                cmd = 'taskkill /f /im ffmpeg-win64-v4.1.exe  2>nul 1>null'
                # python调用Shell脚本执行cmd命令
                os.system(cmd)
    except:
        pass

if __name__ == '__main__':
    #循环体
    for i in range(120):
        #提取对应视频标题的json文件路径
        myjsondirs = './video/{}/entry.json'.format(i + 1)
        #定义拼接完成后视频的标题
        vdtitle = ''
        with open(myjsondirs, 'r', encoding='UTF-8') as load_f:
            # loads方法将json格式数据转换为字典(读取文本用此法)
            load_dict = json.load(load_f)
            vdtitle = load_dict['page_data']['part']
        #视频文件夹路径
        mydirs = './video/{}/lua.flv.bili2api.80'.format(i+1)
        # 定义拼接视频的数组
        L = []
        # 访问 video 文件夹
        # root指的是当前正在遍历的这个文件夹的本身的地址,dirs是一个 list,内容是该文件夹中所有的目录的名字(不包括子目录),files同样是 list,内容是该文件夹中所有的文件(不包括子目录)
        for root, dirs, files in os.walk(mydirs):
            # 按文件名排序
            # files.sort()
            # 自然排序法
            files = natsorted(files)
            # print(files)
            # 遍历所有文件
            for file in files:
                # os.path.splitext(“文件路径”)    分离文件名与扩展名:默认返回(fname, fextension)元组,可做分片操作
                # 如果后缀名为 .blv
                if os.path.splitext(file)[1] == '.blv':
                    # 拼接成完整路径
                    filePath = os.path.join(root, file)
                    # print(filePath)
                    # 读取视频到内存
                    myvideo = VideoFileClip(filePath)
                    # 下面两行代码最好要有,主要是为了释放内存,否则处理大批量的视频会内存溢出!
                    myvideo.reader.close()
                    myvideo.audio.reader.close_proc()
                    # # 添加到数组
                    L.append(myvideo)
        # 对多个视频在时长上进行拼接
        final_clip = concatenate_videoclips(L)
        targetdir = './target/{}.mp4'.format(vdtitle)
        # 法一:生成目标视频文件方法
        # final_clip.to_videofile(targetdir, fps=24, remove_temp=False)
        #法二:最常规的生成目标视频文件方法
        # final_clip.write_videofile(targetdir,fps=24,audio=False,remove_temp=False)  #这里的audio设置为False,这样就不会额外再生成音频文件了
        print("{}---{}---拼接成功!".format(i + 1, vdtitle))
        killProcess()

注意:以上代码倒数第3行做了注释,实际运行时,要把这行注释取消,才能正常拼接视频。这里暂时这么做的原因是因为moviepy拼接视频特别慢,自己电脑配置也不行,所以只是这里暂时不拼接,只是看个效果。最终拼接效果,我会在文末放出来,我想等我今晚睡觉时运行一下,明早应该就能把这120个视频拼接完成吧!

运行结果:显然可以看到是可以拼接成功的!

过程中遇到的一些问题:

  其实我个人觉得写代码,遇到问题才是最有意思的,当把这一个一个的问题都解决掉,这种感觉才是真的nice!显然我自己在处理合并B站视频时遇到了一些问题,这里记录下来,方便自己也方便他人查阅学习!

问题1:报错 OSError: [WinError 6] 句柄无效。

解决办法:这里是因为在myvideo后没有加下面两行代码:

video.reader.close()
video.audio.reader.close_proc()

 原因:我想主要是为了释放内存吧,否则处理大批量的视频会内存溢出!

问题2:真正拼接视频时,发现还是会报错 OSError: [WinError 6] 句柄无效!(这是另一种情形)

解决办法:调用自定义函数killProcess()杀死moviepy产生的特定进程!

原因:这是因为调用了moviepy的concatenate_videoclips函数,没有及时杀死进程!如果不加杀死进程的程序,循环一次,在任务管理器就会新产生一个ffmpeg-win64-v4.1.exe的进程,这个进程数量过多,windows任务管理器并不会自动杀死这些进程,而运行的python程序就会报错!所以我在程序里添加了杀死ffmpeg-win64-v4.1.exe进程的程序,这样拼接完成一个视频,就调用函数强行杀死ffmpeg-win64-v4.1.exe进程,保证pycharm里面的ffmpeg-win64-v4.1.exe进程不会无限增长下去导致程序报错!

问题3:报错 psutil._exceptions.NoSuchProcess: psutil.NoSuchProcess no process found with pid 5764 

解决办法:添加try...except 处理,使python程序能够处理在运行中出现的异常和错误。

原因:没有发现指定的进程引起的程序报错!

注意:命令 cmd = 'taskkill /f /im ffmpeg-win64-v4.1.exe 2>nul 1>null',这里的2>nul:表示不输出错误信息   1>nul:表示不输出成功的信息

--------------------喜欢就点个赞呗,嘻嘻嘻----------------------

猜你喜欢

转载自www.cnblogs.com/FHC1994/p/10760809.html