使用OpenAI的Whisper模型转录YouTube视频
本文是一系列三篇博客文章中的第一篇,逐步解释了如何构建AI助手来总结YouTube视频的过程。我们从详细的说明开始,介绍如何使用OpenAI的声音转文本模型Whisper来捕获YouTube视频的转录。在下一篇文章中,我们将介绍使用Langchain进行文本摘要的基本原理,并详细介绍如何基于Falcon-7b-instruct,一个开源的经过指令调优的LLM,实现摘要管道的详细说明。在最后一篇文章中,我们将看到如何使用Gradio和Hugging Face Spaces演示解决方案原型。在这些文章中,我们评估了每个步骤实现的不同架构选择。
介绍
想象一下:你正在寻找包含你热衷的特定主题信息的视频。一个快速的YouTube搜索会让你的屏幕上充满了迷人的缩略图和引人入胜的视频标题。大多数人会本能地开始浏览,寻找那个最吸引人的点击宝藏。然而,你有多少次在浏览视频时希望它包含对你迫切问题的答案?如果你像我一样,这种情况经常发生,并且这种体验不仅浪费时间,而且非常令人恼火!
受到这种频繁的挫败感的激发,我踏上了创建自己的个人AI助手的旅程。这个智能伴侣会审查视频内容,并高效地总结其主要思想和论点,最终为我节省时间和理智!
在创建这个工具时,我使用了Falcon大型语言模型。这里有一个有趣的类比:就像猎鹰优雅地在高空飞翔,同时拥有对任何感兴趣的对象进行放大的能力一样,我们用Falcon提供的工具让用户以总览的方式查看内容,轻松地通过全面的完整转录进行深入探索!:)
你可能会问:“但已经有在线服务来实现这个功能了,对吗?”你完全正确!然而:
- 它们通常有使用率限制,可能会导致额外的费用。
- 我发现自己希望对生成的摘要有更多的控制权,没有办法根据我的特定需求设置参数。
- 正如谚语所说,“快乐在于旅程!”
所以,我自己动手开发了一个应用程序,它以YouTube视频的URL作为输入,并提供简洁的摘要。很酷,对吧?
解决方案蓝图
引擎盖下的动力组件执行以下任务:
- 如果有可能,从YouTube获取转录。否则,使用声音转文本模型(OpenAI的Whisper)在Hugging Face上进行转录。
- 使用Langchain和针对遵循指令的大型语言模型(Falcon-7b-instruct)在Hugging Face上,采用映射-约简的方法对转录进行摘要。
- 使用Gradio提供一个美观的用户界面,让用户与模型无缝交互,生成并与视频本身一起查看和审查摘要。
在实施每一步时,我尝试了各种不同的架构方案。例如,我以两种方式实施了每一步:在本地推理 vs 在云端推理。或者,当涉及到应用的托管时,我尝试了在本地托管 vs 在云端托管在Hugging Face Spaces上。
如果其中任何一点引起了你的好奇心,请跟随我一起学习和交流吧。
在进入下一节之前,我建议你快速看一下托管在Hugging Face Spaces上的原型。随意试试,并在评论中告诉我你的第一印象。
第一步:获取YouTube视频的转录文本
在我们能够对视频进行摘要之前,我们需要将其转录为文本格式。虽然许多YouTube视频都有转录,但你可能会遇到一些没有转录的视频。如果有转录存在,我们只需使用youtube_transcript_api和pytube简单地下载转录:
from youtube_transcript_api import YouTubeTranscriptApi
import pytube
# 从YouTube获取转录
def get_yt_transcript(url):
text = ''
vid_id = pytube.extract.video_id(url)
temp = YouTubeTranscriptApi.get_transcript(vid_id)
for t in temp:
text+=t['text']+' '
return text
这段代码只是从URL中获取YouTube视频ID,并使用YouTubeTranscriptApi获取转录对象。转录对象是一个包含转录文本、开始时间和在视频上显示的持续时间的字典列表。这里我们只需要文本属性。
但是如果YouTube没有视频的转录呢?现在事情变得更有趣了……
使用Whisper转录
为此,我使用了著名的Whisper模型,这是来自OpenAI的开源语音转文字模型。目前,只要它能满足我们的需求,我们不需要过多关注模型的内部工作原理。虽然有很多在线资源可供参考,如果评论中有兴趣,我会在单独的博客文章中介绍它们。
在使用Whisper模型之前,我们需要将视频的音频下载到本地目录中,只需几行代码即可完成:
from pytube import YouTube
yt = YouTube(str(url))
audio = yt.streams.filter(only_audio = True).first()
out_file = audio.download(filename="audio.wav",output_path="./docs/youtube/")
现在,我们可以直接使用Whisper接受音频文件作为输入并进行转录了。我们首先创建一个从HuggingFace下载模型的Transformers Pipeline对象:
import transformers
whisper_asr = transformers.pipeline(
"automatic-speech-recognition", model="openai/whisper-large", device_map= 'auto',)
Whisper有各种不同的大小,从小型(拥有3900万个参数)到大型(拥有15.5亿个参数)。我使用了whisper-large,以获得最高质量的结果。一旦加载并开始评分,在峰值时,它占用了我16GB GPU内存的12GB,这还可以接受。但是如果适用于你的用例,你可以选择使用更小的版本。
然后,我们需要设置模型的配置参数,包括语言和任务:
whisper_asr.model.config.forced_decoder_ids = (
whisper_asr.tokenizer.get_decoder_prompt_ids(
language="en",
task="transcribe"
))
在这种情况下,我将流水线限制为只转录英文视频。但是,你也可以使用相同的模型转录其他几十种语言。为此,你需要在配置转录流水线之前确定视频的语言。我将这留给有兴趣的读者作为练习。
最后,我们为推断调用模型:
temp = whisper_asr(out_file,chunk_length_s=20)text = temp ['text']
但是chunk_length_s参数是什么意思?Whisper模型被设计用于分析最大长度为30秒的音频文件。因此,在将文件提供给模型之前,需要将其分割成块。 chunk_length_s参数控制这些块的长度。
将其整合到一起,代码如下:
from pytube import YouTubeimport transformersimport torch# transcribes the videodef transcribe_yt_vid(url): # download YouTube video's audio save_dir="./docs/youtube/" yt = YouTube(str(url)) audio = yt.streams.filter(only_audio = True).first() out_file = audio.download(filename="audio.wav", output_path = save_dir) # defining an automatic-speech-recognition pipeline using `openai/whisper-large` whisper_asr = transformers.pipeline( "automatic-speech-recognition", model="openai/whisper-large", device_map= 'auto', ) # setting model config parameters whisper_asr.model.config.forced_decoder_ids = ( whisper_asr.tokenizer.get_decoder_prompt_ids( language="en", task="transcribe" ) ) # invoking the Whisper model temp = whisper_asr(out_file,chunk_length_s=20) text = temp['text'] # we can do this at the end to release GPU memory del(whisper_asr) torch.cuda.empty_cache() return text
好了,太棒了!但是等等!如果我在本地没有足够的计算能力,想要将推断请求发送到云端怎么办?
使用HuggingFace Hub API进行推断
好消息是,HuggingFace通过HuggingFace Hub API支持在云端进行推断。
以下是使用方法:
from HuggingFace_hub import InferenceClient# Initialize client for the Whisper modelclient = InferenceClient(model="openai/whisper-large", token="xxxxxxxxxxx")
只需要传递一个令牌参数,该令牌可以免费从HuggingFace获得。
但是,我遇到了一个问题!推断API对结果进行了截断,我无法从在线资源中找到是否这是预期行为,还是可能是使用免费服务的限制。无论哪种情况,解决方法是在将音频片段通过推断API发送之前将音频分割成块。可以使用librosa将音频文件加载为numpy数组,然后使用长度不会被API截断的块长度(比如20秒)将其分割成块,最后将每个块保存到文件,然后发送给API进行推断:
import librosaimport soundfile as sfx, sr = librosa.load(out_file, sr=None)t=20 # 音频片段长度(秒)# 这将x作为numpy数组音频文件,sr作为原始采样率# 由于API调用截断响应,音频需要拆分成20秒的块 text = ''for i in range(0, (len(x)//(t * sr)) +1): y = x[t * sr * i: t * sr *(i+1)] split_path = save_dir+"audio_split.wav" sf.write(split_path, y, sr) text += client.automatic_speech_recognition(split_path)
通过这种解决方法,我能够在API上转录较长的视频。但要注意的是,免费订阅会限制推断速率。这意味着如果短时间内多次调用API,可能会出错。好消息是,限制每小时重置一次,所以您不必等太长时间,就可以再次测试代码。但这也意味着您可能无法将此解决方法用于太长的视频!
最终的结果可能如下所示:
from pytube import YouTubefrom huggingface_hub import InferenceClient# transcribes the video using the Hugging Face Hub APIdef transcribe_yt_vid_api(url): # download YouTube video's audio yt = YouTube(str(url)) audio = yt.streams.filter(only_audio = True).first() out_file = audio.download(filename="audio.wav", output_path = save_dir) # Initialize client for the Whisper model client = InferenceClient(model="openai/whisper-large", token=os.environ["HUGGINGFACEHUB_API_TOKEN"]) import librosa import soundfile as sf text = '' t=20 # audio chunk length in seconds x, sr = librosa.load(out_file, sr=None) # This gives x as audio file in numpy array and sr as original sampling rate # The audio needs to be split in 20 second chunks since the API call truncates the response for i in range(0, (len(x)//(t * sr)) +1): y = x[t * sr * i: t * sr *(i+1)] split_path = save_dir+"audio_split.wav" sf.write(split_path, y, sr) text += client.automatic_speech_recognition(split_path) return text
将所有内容放在一起
现在将这两种方法放在一个函数中,我们可以这样做:
def transcribe_youtube_video(url, force_transcribe=False, use_api=False): yt = YouTube(str(url)) text = '' # 从YouTube获取字幕(如果有) try: text = get_yt_transcript(url) except: print('字幕不可用,正在进行转录...') pass # 如果YouTube没有提供字幕,或者您想强制进行转录的话,进行视频转录 if text == '' or force_transcribe: if use_api: text = transcribe_yt_vid_api(url) else: text = transcribe_yt_vid(url) return yt.title, text
结论
让我们回顾一下我们在本文中讨论过的内容。我们创建了三个不同的函数,用于获取YouTube视频的转录:第一个直接从YouTube下载,第二个在本地使用OpenAI的Whisper模型转录,第三个通过Hugging Face Hub API进行转录。值得注意的是,在生产环境中部署会更加复杂。根据推理吞吐量和所需资源的数量,模型可能会被推送到一个端点。Hugging Face提供了推理端点服务,在专用和自动伸缩的基础设施上部署模型。关于这个问题,我们将在另一个时间进行讨论。
在下一篇文章中,我将向您介绍使用Langchain和Falcon-7b-instruct在HuggingFace上获取转录并进行摘要的步骤。