就像大多数人一样,我对NotebookLM及其从一组文档生成播客的能力感到震惊。然后,我开始思考:“他们是怎么做到的,我可以在哪里获得这种魔法?复制它会有多容易?”
目标:从一篇文章创建一个视频演讲我不想创建播客,但我经常希望可以从我的博客文章生成幻灯片和视频演讲——有些人喜欢一页页地浏览幻灯片,而另一些人则喜欢观看视频,这样可以满足他们的需求。在这篇文章中,我将向你展示如何做到这一点。
本文的完整代码在 GitHub 上 —— 如果你想跟着我一起做。目标是根据这篇文章创建这个视频。
使用本文描述的代码自动生成的视频。由作者生成。
1. 初始化LLM我将使用Google Gemini Flash,因为(a)它是目前最便宜的前沿大型语言模型,(b)它具有多模态功能,可以读取和理解图像,(c)它支持可控生成,这意味着我们可以确保大型语言模型的输出符合所需的结构。
import pdfkit
import os
import google.generativeai as genai
from dotenv import load_dotenv
load_dotenv("../genai_agents/keys.env")
genai.configure(api_key=os.environ["GOOGLE_API_KEY"])
注意,我使用的是 Google 生成式 AI,而不是 Google Cloud Vertex AI。这两个包是不同的。Google 的生成式 AI 支持 Pydantic 对象以实现可控生成;而 Vertex AI 目前仅支持 JSON。
2. 获取文章的PDF版本我使用Python将文章下载为PDF,并上传到Gemini可以读取的临时存储位置:
ARTICLE_URL = "https://lakshmanok.medium...."
pdfkit.from_url(ARTICLE_URL, "article.pdf")
pdf_file = genai.upload_file("article.pdf")
不幸的是,Medium 的某些限制导致 pdfkit 无法获取文章中的图片(可能是因为它们是 webm 格式而不是 png……)。因此,我的幻灯片将仅基于文章的文本,而不包含图片。
3. 创建 JSON 格式的讲义笔记在这里,我希望的数据格式是一系列幻灯片,每张幻灯片包含一个标题、要点和一套讲义内容。整个讲座还包含一个标题和一个署名。
class Slide(BaseModel):
标题: str
关键点: List[str]
讲座笔记: str
class Lecture(BaseModel):
幻灯片: List[Slide]
讲座标题: str
基于文章作者: str
让我们告诉Gemini我们想要它做什么:
lecture_prompt = """
你是一位大学教授,需要为本科生班级准备一堂课。
* 根据以下文章创建一个包含10张幻灯片的讲座。
* 每张幻灯片应包含以下信息:
- 标题:用一句话总结主要观点
- 关键点:包含2到5个要点的列表。使用短语,而不是完整的句子。
- 讲座笔记:用易于理解的语言解释关键点,3到10句话。使用文章中的其他信息扩展这些要点。
* 同时,为讲座创建一个标题并注明原文章作者。
"""
提示非常直接——让Gemini阅读文章,提取关键点并创建讲义笔记。
现在,调用模型,传入PDF文件,并要求它填充所需的结构:
model = genai.GenerativeModel(
"gemini-1.5-flash-001",
system_instruction=[lecture_prompt]
)
generation_config={
"temperature": 0.7,
"response_mime_type": "application/json",
"response_schema": Lecture
}
response = model.generate_content(
[pdf_file],
generation_config=generation_config,
stream=False
)
关于上述代码有几点需要注意:
- 我们将提示作为系统提示传递,因此无需在每次输入新内容时都发送提示。
- 我们指定期望的响应类型为 JSON,并且模式为 Pydantic 对象
- 我们将 PDF 文件发送给模型,并指示它生成响应。我们将等待它完成(无需流式传输)
结果是 JSON,所以将其提取为一个 Python 对象:
lecture = json.loads(response.text)
例如,这是第3张幻灯片的样子:
{'key_points': [
'银层负责清理、结构化和准备数据,以供自助分析使用。',
'数据被反规范化并组织成更易于使用的格式。',
'该层处理类型2的缓慢变化维度。',
'银层的治理责任在于源团队。'
],
'lecture_notes': '银层从铜层获取数据,并将其转换为自助分析的可用格式。这包括清理、结构化和组织数据。该层还处理类型2的缓慢变化维度,这些维度用于跟踪随时间的变化。银层的治理责任在于源团队,通常是负责源系统的数据工程团队。',
'title': '银层:数据转换与准备'
}
4. 转换为 PowerPoint
我们可以使用 Python 包 pptx 创建带有注释和要点的演示文稿。创建幻灯片的代码如下所示:
对于每个slidejson in lecture['slides']:
slide = presentation.slides.add_slide(presentation.slide_layouts[1])
title = slide.shapes.title
title.text = slidejson['title']
# 列表项
textframe = slide.placeholders[1].text_frame
for key_point in slidejson['key_points']:
p = textframe.add_paragraph()
p.text = key_point
p.level = 1
# 备注
notes_frame = slide.notes_slide.notes_text_frame
notes_frame.text = slidejson['lecture_notes']
结果是一个看起来像这样的 PowerPoint 演示文稿:
从关键点和讲义笔记生成的 PowerPoint 文件。作者截图。
不是很花哨,但绝对是演讲编辑的一个很好的起点。
5. 大声读出笔记并保存音频好吧,我们受到了一档播客的启发,那么让我们来看看如何创建一段某人总结文章的音频。
我们已经有了讲义,所以让我们为每张幻灯片创建音频文件。
这里是将一些文本转换为AI语音朗读并保存为mp3文件的代码:
从 google.cloud import texttospeech
def convert_text_audio(text, audio_mp3file):
"""从输入的文本字符串合成语音。"""
tts_client = texttospeech.TextToSpeechClient()
input_text = texttospeech.SynthesisInput(text=text)
voice = texttospeech.VoiceSelectionParams(
language_code="en-US",
name="en-US-Standard-C",
ssml_gender=texttospeech.SsmlVoiceGender.FEMALE,
)
audio_config = texttospeech.AudioConfig(
audio_encoding=texttospeech.AudioEncoding.MP3
)
response = tts_client.synthesize_speech(
request={"input": input_text, "voice": voice, "audio_config": audio_config}
)
# 响应的 audio_content 是二进制格式。
with open(audio_mp3file, "wb") as out:
out.write(response.audio_content)
print(f"{audio_mp3file} 写入完成。")
上面的代码中发生了什么?
- 我们使用了Google Cloud的文本转语音API
- 要求它使用标准的美国女性口音。如果你在做播客,你需要在这里传入一个“说话人映射”,为每个说话人指定一个声音。
- 然后我们给它输入文本,让它生成音频
- 将音频保存为mp3文件。请注意,这必须与音频编码匹配。
现在,通过遍历幻灯片并传入讲义内容来创建音频:
for slideno, slide in enumerate(lecture['slides']):
text = f"接下来是 {slide['title']} \n"
text += slide['lecture_notes'] + "\n\n"
filename = os.path.join(outdir, f"audio_{slideno+1:02}.mp3")
convert_text_audio(text, filename)
filenames.append(filename)
结果是一系列音频文件。如果你想将它们合并,可以使用 pydub:
combined = pydub.AudioSegment.empty()
for audio_file in audio_files:
audio = pydub.AudioSegment.from_file(audio_file)
combined += audio
# 暂停4秒钟
silence = pydub.AudioSegment.silent(duration=4000)
combined += silence
combined.export("lecture.wav", format="wav")
但事实证明我不需要那样做。每个幻灯片对应的一个单独的音频文件,这些是我用来创建视频所需要的。当然,对于播客,你可能希望有一个单一的mp3或wav文件。
6. 创建幻灯片的图片相当令人恼火的是,没有简单的方法可以使用Python将PowerPoint幻灯片渲染为图像。你需要一台安装了Office软件的机器才能做到这一点——这并不是很容易自动化的事情。也许我应该使用Google幻灯片……无论如何,使用Python图像库(PIL)可以简单地渲染图像。
def 文本转图片(output_path, title, keypoints):
image = Image.new("RGB", (1000, 750), "black")
draw = ImageDraw.Draw(image)
标题字体 = ImageFont.truetype("Coval-Black.ttf", size=42)
draw.multiline_text((10, 25), wrap(title, 50), font=标题字体)
文本字体 = ImageFont.truetype("Coval-Light.ttf", size=36)
for ptno, 关键点 in enumerate(keypoints):
draw.multiline_text((10, (ptno+2)*100), wrap(关键点, 60), font=文本字体)
image.save(output_path)
生成的图像效果不佳,但勉强可用(你可以看出现在已经没有人付钱让我写生产代码了):
这些图片与音频片段一起使用,由作者生成。
7. 创建视频现在我们有一系列音频文件和一系列图像文件,我们可以使用一个名为 moviepy 的 Python 包来创建一个视频片段:
clips = []
for slide, audio in zip(slide_files, audio_files):
audio_clip = AudioFileClip(f"article_audio/{audio}")
slide_clip = ImageClip(f"article_slides/{slide}").set_duration(audio_clip.duration)
slide_clip = slide_clip.set_audio(audio_clip)
clips.append(slide_clip)
full_video = concatenate_videoclips(clips)
我们现在可以将其写出来:
full_video.write_videofile("lecture.mp4", fps=24, codec="mpeg4",
temp_audiofile='temp-audio.mp4', remove_temp=True)
最终结果?我们从 article.pdf 自动创建了四个工件:
lecture.json lecture.mp4 lecture.pptx lecture.wav
这里有:
- 一个包含关键点、讲义笔记等的 JSON 文件
- 一个可以修改的 PowerPoint 文件。幻灯片上有关键点,而幻灯片的注释部分则包含“讲义笔记”
- 一个由 AI 语音朗读讲义笔记的音频文件
- 一个包含音频和图像的 mp4 影片(我已上传到 YouTube)。这就是我想要创建的视频演讲。
挺酷的,对吧?
8. 这说明了软件的未来是怎样的我们作为一个社区都在探索这项酷炫的技术(生成式AI)能用来做什么。显然,你可以用它来创建内容,但生成的内容适合用来头脑风暴,而不适合直接使用。尽管技术已经改进了三年,但生成式AI仍然会产生质量不佳的内容和无法直接使用的代码。
这让我们谈到了GenAI开启的一些辅助功能。这些功能结果证明非常有用。本文展示了GenAI的四个功能。
(1) 将非结构化数据转换为结构化数据
《注意力》论文旨在解决翻译问题,结果发现基于Transformer的模型在翻译方面表现非常出色。我们不断发现这类模型的应用场景。不仅仅是日语到英语,还包括Java 11到Java 17,从文本到SQL,从文本到语音,以及在数据库方言之间……现在还包括从文章到音频脚本的转换。这实际上成为了使用GenAI创建播客、讲座、视频等的起点。
我只需要提示LLM从文章中构建一系列幻灯片内容(要点、标题等),它就做到了。它甚至以结构化格式将数据返回给我,便于计算机程序使用。具体来说,GenAI真的擅长将非结构化数据转换为结构化数据。
(2) 代码搜索和编码辅助现在大幅改进
另一个GenAI表现出色的地方在于它可以动态地适应代码样例。我并不每天都编写用于创建演示文稿、文本转语音或moviepy的代码。两年前,我会使用Google搜索,查找Stack Overflow页面,并手动修改代码。现在,Google搜索直接给我提供了可以直接使用的代码:
Google 搜索返回代码示例,适应了我的特定查询。作者截图。
当然,如果我使用的是Python IDE(而不是Jupyter notebook),我就可以完全避免搜索这一步——我可以写一个注释并让代码自动生成。这非常有帮助,可以加快使用通用API进行开发的速度。
(3) GenAI 网页服务坚固且易于使用
让我们不要忘记,我使用了 Google Cloud 文本转语音服务将我的音频脚本转换成了实际的音频文件。文本转语音本身就是一个生成式 AI 模型(也是翻译超能力的一个例子)。Google TTS 服务是在 2018 年(当时)推出的(并且此后可能有所改进)(详情),这是最早投入生产的生成式 AI 服务之一,并通过 API 提供。
在本文中,我使用了两个生成式AI模型——TTS和Gemini,它们作为网络服务提供。我所要做的就是调用它们的API。
(4) 提供终端用户自定义功能比以往任何时候都更容易
我没有这么做,但你可以稍微眯一下眼睛,就能看到事情的发展方向。如果我把演示文稿创建、音频创建和电影创建的代码封装成服务,我可以让一个提示生成调用这些服务的函数调用。并且可以加入一个请求处理代理,让你通过文本改变幻灯片的外观或视频中朗读者的声音。
为您的软件添加开放式自定义功能变得极为简单。
概要受到 NotebookLM 播客功能的启发,我着手构建一个应用程序,将我的文章转换为视频演讲。关键步骤是提示一个大型语言模型生成幻灯片内容,使用另一个生成式 AI 模型将音频脚本转换为音频文件,并利用现有的 Python API 将其组合成一个视频。
本文介绍了GenAI解锁的四种能力:各种类型的翻译、编码辅助、强大的网络服务和最终用户自定义能力。
我非常喜欢能够轻松快速地从我的文章中创建视频讲座。但我更兴奋的是,我们不断在手中这个新工具中发现的潜力。
进一步阅读- 本文的完整代码:https://github.com/lakshmanok/lakblogs/blob/main/genai_seminar/create_lecture.ipynb
- 我转换成视频的文章:https://lakshmanok.medium.com/what-goes-into-bronze-silver-and-gold-layers-of-a-medallion-data-architecture-4b6fdfb405fc
- 生成的视频:https://youtu.be/jKzmj8-1Y9Q
- 结果Sascha Heyer 写了一篇文章,介绍如何使用 GenAI 生成播客,这正是 Notebook LM 的应用场景。他的方法与我的类似,不过他只生成音频,没有视频。有趣的是,他还用自己的声音作为播客的演讲者之一!
- 当然,这是使用本文视频技术生成的视频演讲。理想情况下,我们会从文章中提取代码片段和图片,但这只是一个开始……
共同学习,写下你的评论
评论加载中...
作者其他优质文章