【python+you_get+moviepy】获取鬼畜视频并提取音频--别让播放器限制了你对音乐的热爱

一、前言

1.1 需求来源

很多人喜欢听音乐,但现在音乐的形式也越来越丰富,比如抖音上的短视频、B站的鬼畜视频里面不乏优秀的音源,这些作品即使不看视频只听声音也是一种享受,而在各大音乐平台上却很难找到这些音源,更不用说一些小众的音频了。
那么,我们该如何根据视频链接获取音频呢

1.2 准备工作

 python:3.11.3(≥3.7)
 you-get 库:0.4.1650
 moviepy 库:1.0.3

1.3 思路解析

you-get 是一个很火的视频提取项目,支持从众多的网页链接中提取视频文件;moviepy 是一个 python 音视频处理的常用库,类似于 ffmpeg ,但安装使用更方便快捷,可以把 MP4 文件转化为 MP3 文件。
如果想加入歌词,之后还可以在文件夹下加入同名 lrc 文件。

1.4 算法流程设计

 1). 编写视频下载函数,并使用进程池实现同步下载
 2). 记录下载前后文件夹的变化,识别 flv 文件并转化为 MP4 格式
 3). 编写视频转音频函数,并通过进程池实现同步转化

二、代码解析

2.1 安装 you-get

在文件中运行:

os.system("pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ you-get")

也可以在 cmd 窗口输入命令行:

pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/ you-get

第一次安装:
ou-get首次安装

非首次安装:
you-get非首次安装
首次安装之后可以把此段代码注释掉。

2.2 进程池实现下载视频

根据链接下载视频文件,并指定保存路径:

def downloadMp4(filePath, url):
    os.system(f"you-get -o {
      
      filePath} {
      
      url}")
    print(f"{
      
      url} 下载完成")

使用进程池,利用电脑资源加速多个视频的下载:

def manyDownload(filePath, mp4Urls):
    p = Pool(4)
    for url in mp4Urls:
        p.apply_async(downloadMp4, args=(filePath, url,))
    p.close()
    p.join()

2.3 识别 flv 文件并转化为 MP4 格式

在视频前后要分别记录文件夹的文件列表,否则可能会提取出之前保存的视频文件:

files_before = os.listdir(filePath)
...
files_after = os.listdir(filePath)

定义识别函数并更改格式,返回新增的 MP4 格式的文件名列表:

def getMp4List(files_before, files_after):
    flvList = []
    mp4List = []
    # 找到刚下载的 flv 文件
    for file in files_after:
        if file not in files_before:
            if file.split('.')[-1] in ['flv', 'mp4']:
                flvList.append(file)
    # 将 flv 后缀改为 mp4
    for file in flvList:
        if file.split('.')[-1] == 'flv':
            new_name = file[:-3] + "mp4"
            os.rename(f"{
      
      filePath}{
      
      file}", f"{
      
      filePath}{
      
      new_name}")
            mp4List.append(new_name)
        elif file.split('.')[-1] == 'mp4':
            mp4List.append(file)
    return mp4List

2.4 进程池实现多个视频文件同时转化为音频

视频转音频函数:

# 从视频文件中提取音频
def getMp3(filePath, mp4File):
    video = VideoFileClip(f"{
      
      filePath}{
      
      mp4File}")
    audio = video.audio
    mp3File = mp4File[:-1] + "3"
    audio.write_audiofile(f"{
      
      filePath}{
      
      mp3File}")
    print(f"{
      
      mp3File}音频提取完成!")

进程池实现同步加速:

# 利用进程池同时从视频中提取音频
def manyTransfer(filePath, mp4List):
    p = Pool(4)
    for mp4File in mp4List:
        p.apply_async(getMp3, args=(filePath, mp4File,))
    p.close()
    p.join()

三、运行截图

同步下载视频:
同步下载视频
注意这里是同步的,只是显示有问题,当第二个文件下载好的时候,第一个文件也已经下载好了。
同步转化为音频:
同步转化为音频
此时查看文件夹:
文件夹情况

四、完整代码

4.1 重量级

带进程池,适合大量视频下载转换的场景:

import os
from moviepy.editor import *
from multiprocessing import Pool


# 根据链接下载视频文件
def downloadMp4(filePath, url):
    os.system(f"you-get -o {
      
      filePath} {
      
      url}")
    print(f"{
      
      url} 下载完成")


# 使用进程池,利用电脑资源加速多个视频的下载
def manyDownload(filePath, mp4Urls):
    p = Pool(4)
    for url in mp4Urls:
        p.apply_async(downloadMp4, args=(filePath, url,))
    p.close()
    p.join()


# 获取新增的 flv 文件,并转化为 MP4 格式
def getMp4List(files_before, files_after):
    flvList = []
    mp4List = []
    # 找到刚下载的 flv 文件
    for file in files_after:
        if file not in files_before:
            if file.split('.')[-1] in ['flv', 'mp4']:
                flvList.append(file)
    # 将 flv 后缀改为 mp4
    for file in flvList:
        if file.split('.')[-1] == 'flv':
            new_name = file[:-3] + "mp4"
            os.rename(f"{
      
      filePath}{
      
      file}", f"{
      
      filePath}{
      
      new_name}")
            mp4List.append(new_name)
        elif file.split('.')[-1] == 'mp4':
            mp4List.append(file)
    return mp4List


# 从视频文件中提取音频
def getMp3(filePath, mp4File):
    video = VideoFileClip(f"{
      
      filePath}{
      
      mp4File}")
    audio = video.audio
    mp3File = mp4File[:-1] + "3"
    audio.write_audiofile(f"{
      
      filePath}{
      
      mp3File}")
    print(f"{
      
      mp3File}音频提取完成!")


# 利用进程池同时从视频中提取音频
def manyTransfer(filePath, mp4List):
    p = Pool(4)
    for mp4File in mp4List:
        p.apply_async(getMp3, args=(filePath, mp4File,))
    p.close()
    p.join()


if __name__ == "__main__":
    filePath = "D:/Music/"  # 注意,最后“/”要有,否则会导致后续路径错误
    files_before = os.listdir(filePath)  # 获取运行前的文件列表,用于跟下载后的做对比
    # 复制鬼畜《念诗之王》、《敢杀我的马》的视频链接,也可以只有一个视频链接
    mp4Urls = ["https://www.bilibili.com/video/BV1bW411n7fY/?spm_id_from=333.337.search-card.all.click",
               "https://www.bilibili.com/video/BV1yt4y1Q7SS/?spm_id_from=333.337.search-card.all.click"]

    # 第一次运行时安装下面的you-get库,非首次运行时可注释掉;也可以通过命令行安装;还可以通过 PyCharm 或 Anaconda 安装
    os.system("pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/  you-get")

    # 利用进程池同时下载多个视频
    manyDownload(filePath, mp4Urls)

    # 对比文件夹变化,获取 flv 文件,并改为 MP4 格式
    files_after = os.listdir(filePath)
    mp4List = getMp4List(files_before, files_after)

    # 利用进程池同时从视频中提取音频
    manyTransfer(filePath, mp4List)

4.2 轻量级

不带进程池,适合单个视频下载转换:

import os
from moviepy.editor import *
from multiprocessing import Pool


# 根据链接下载视频文件
def downloadMp4(filePath, url):
    os.system(f"you-get -o {
      
      filePath} {
      
      url}")
    print(f"{
      
      url} 下载完成")


# 获取新增的 flv 文件,并转化为 MP4 格式
def getMp4List(files_before, files_after):
    flvList = []
    mp4List = []
    # 找到刚下载的 flv 文件
    for file in files_after:
        if file not in files_before:
            if file.split('.')[-1] in ['flv', 'mp4']:
                flvList.append(file)
    # 将 flv 后缀改为 mp4
    for file in flvList:
        if file.split('.')[-1] == 'flv':
            new_name = file[:-3] + "mp4"
            os.rename(f"{
      
      filePath}{
      
      file}", f"{
      
      filePath}{
      
      new_name}")
            mp4List.append(new_name)
        elif file.split('.')[-1] == 'mp4':
            mp4List.append(file)
    return mp4List


# 从视频文件中提取音频
def getMp3(filePath, mp4File):
    video = VideoFileClip(f"{
      
      filePath}{
      
      mp4File}")
    audio = video.audio
    mp3File = mp4File[:-1] + "3"
    audio.write_audiofile(f"{
      
      filePath}{
      
      mp3File}")
    print(f"{
      
      mp3File}音频提取完成!")


if __name__ == "__main__":
    filePath = "D:/Music/"  # 注意,最后“/”要有,否则会导致后续路径错误
    files_before = os.listdir(filePath)  # 获取运行前的文件列表,用于跟下载后的做对比
    # 复制鬼畜《念诗之王》、《敢杀我的马》的视频链接,也可以只有一个视频链接
    mp4Urls = ["https://www.bilibili.com/video/BV1bW411n7fY/?spm_id_from=333.337.search-card.all.click",
               "https://www.bilibili.com/video/BV1yt4y1Q7SS/?spm_id_from=333.337.search-card.all.click"]

    # 第一次运行时安装下面的you-get库,非首次运行时可注释掉;也可以通过命令行安装;还可以通过 PyCharm 或 Anaconda 安装
    os.system("pip install -i https://pypi.tuna.tsinghua.edu.cn/simple/  you-get")

    # 利用进程池同时下载多个视频
    for url in mp4Urls:
        downloadMp4(filePath, url)

    # 对比文件夹变化,获取 flv 文件,并改为 MP4 格式
    files_after = os.listdir(filePath)
    mp4List = getMp4List(files_before, files_after)

    # 利用进程池同时从视频中提取音频
    for mp4 in mp4List:
        getMp3(filePath, mp4)

PS:请勿将此方法用于商业行为,在法律准许的范围内合理使用互联网资源!更多 python 有趣应用,敬请关注后续更新~

猜你喜欢

转载自blog.csdn.net/weixin_44844635/article/details/131345293