全文一览
一、前言
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
第一次安装:
非首次安装:
首次安装之后可以把此段代码注释掉。
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)