弄了一晚上终于打包好了,下载地址
[color=]https://github.com/cuifengcn/wechat-video-generate/releases/tag/v0.1
但还是存在一些问题:
1. 文件太大超过蓝奏云100M限制,所以放github了
2. 解压后的大小超过了1G,其中pytorch占800M,playwright占300M
3. 由于某个未知的bug,控制台没有隐藏
感兴趣的小伙伴可以帮忙优化一下,比如把ocr识别改成tesseract,压缩一下打包文件大小。
----分割线----
相信大家有在抖音或视频号刷到过这样的视频
1.png (249.5 KB, 下载次数: 0)
下载附件
2023-1-2 18:42 上传
这样由微信对话合成的视频,因为内容有趣,很多人都喜欢看,播放量都是很恐怖的。
做这样的视频也很赚钱,某位大v的收益
2.png (126.38 KB, 下载次数: 0)
下载附件
2023-1-2 18:43 上传
原理就是利用巨大的播放量,添加商品推广链接,有人通过链接购买商品,你赚取佣金​。
制作这样的视频,一般做法是:
1. 去网上找对话素材
2. 找一个模拟微信对话的工具
3. 使用对话模拟器生成图片
4. 对图片进行剪辑,生成视频
这样下来几个步骤其实挺麻烦的,并且制作每个视频其实都属于是重复劳作。
所以我们今天,教大家制作一个一键生成`微信对话视频`的工具,让你能够省时省力,抢占先机!
### 先看成品
3.png (144.07 KB, 下载次数: 0)
下载附件
2023-1-2 18:44 上传
只需要在界面点点点就能生成视频了,很方便有木有!
### 技术原理
用到的技术有
1. 爬虫——从百度爬取图片
2. ocr识别——识别图片文字
3. 模拟微信对话工具
4. server服务
5. playwright自动化操作
6. 图片处理
7. 音频处理
8. 视频处理
9. 桌面gui
### 思路
1. 根据关键字在百度图片批量下载数据
2. 使用ocr识别图片中的文字
3. 分析文字的位置,区分左右对话
4. ocr精度有限,手工校对文字
5. 启动一个模拟微信对话服务
6. 进行自动化操作,将结果进行截图
7. 将截图、音频进行合成视频
### 根据关键字在百度图片批量下载数据
我们从`https://image.baidu.com/search`搜索图片,提取出每张图片的地址,然后进行下载,主要代码如下(代码为主要部分代码)
[Python] 纯文本查看 复制代码url = (
"https://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj"
"&ct=201326592&is=&fp=result&queryWord=%s&cl=2&lm=-1&ie=utf-8&oe=utf-8"
"&adpicid=&st=-1&z=&ic=&hd=&latest=©right=&word=%s&s=&se=&tab=&width=&height=&face=0"
"&istype=2&qc=&nc=1&fr=&expermode=&force=&pn=%s&rn=%d&gsm=1e&1594447993172="
% (search, search, str(pn), self.__per_page)
)
# 设置header防403
try:
time.sleep(self.time_sleep)
req = urllib.request.Request(url=url, headers=self.headers)
page = urllib.request.urlopen(req)
self.headers["Cookie"] = self.handle_baidu_cookie(
self.headers["Cookie"], page.info().get_all("Set-Cookie")
)
rsp = page.read()
page.close()
except UnicodeDecodeError as e:
self.logger.error(e)
self.logger.error("-----UnicodeDecodeErrorurl:", url)
### 使用ocr识别图片中的文字
使用`cnocr`库,我们就能实现本地ocr识别,而不需要网络,代码如下
[Python] 纯文本查看 复制代码self.model = CnOcr(
det_model_name="ch_PP-OCRv3_det",
)
out = self.model.ocr(
cv2.imdecode(self.read_file(f), -1),
)
for i in out:
i["score"] = float(i["score"])
i["position"] = i["position"].astype(float).tolist()
target_path.joinpath(file_name + ".json").write_text(
json.dumps(out, ensure_ascii=False, indent=4)
)
### 分析文字的位置,区分左右对话
我们基于文字的内容和位置,判断文字是属于
* 标题——距离顶部的位置[Python] 纯文本查看 复制代码res = []
"""去掉标题栏"""
if json_content and "中国" in json_content[0]["text"]:
# 中国联通行,去掉
x = json_content[0]["position"][0][0]
for i in range(1, len(json_content)):
if abs(json_content["position"][0][0] - x) 0
and abs(
json_content["position"][0][1]
- json_content[i - 1]["position"][0][1]
)
当然了,判断无法百分百正确,所以我们后续添加了手工修正
### ocr精度有限,手工校对文字
基于flet库, 实现了ui界面
4.png (97.48 KB, 下载次数: 0)
下载附件
2023-1-2 18:46 上传
### 启动一个模拟微信对话服务
我们启动了一个fastapi服务,用于调用模拟微信对话
[Python] 纯文本查看 复制代码app = FastAPI()
app.mount(
"/static",
StaticFiles(directory=MAIN_PATH.joinpath("weixin_chat", "static")),
name="static",
)
@app.route("/")
def index(*args, **kwargs):
return HTMLResponse(
MAIN_PATH.joinpath(
"weixin_chat",
"index.html",
).read_text(encoding="utf-8")
)
### 进行自动化操作,将结果进行截图
使用`playwright`库,打开浏览器,自动化进行操作,输入每条对话内容后,进行截图,保存到本地。
[Python] 纯文本查看 复制代码browser = playwright.chromium.launch(headless=True)
context = browser.new_context()
page = context.new_page()
page.goto("http://127.0.0.1:36999")
page.wait_for_load_state()
"""生成标题"""
if formatted_jsons[0]["position"] == "title":
page.fill(title, formatted_jsons[0]["text"])
formatted_jsons = formatted_jsons[1:]
else:
titles = ["佳佳", "小小", "♥", "❀", "啊呜", "奔波儿灞与灞波儿奔", "亲亲"]
page.fill(title, random.choice(titles))
time.sleep(0.2)
"""跳转到对话页"""
page.click(
"#vueApp > div > div.edit-content > div.tab > ul > li:nth-child(2) > a"
)
time.sleep(0.2)
page.wait_for_selector(
"#tabContent2 > div > div.dialog-user-items > div:nth-child(1) > div > a.dialog-user-face-a > input[type=file]"
)
"""清空对话"""
page.on("dialog", lambda dialog: dialog.accept())
page.click(clear_conv)
time.sleep(0.2)
"""选取头像"""
photos = self.two_random_photo()
page.set_input_files(my_photo, photos[0])
time.sleep(0.2)
page.set_input_files(second_photo, photos[1])
time.sleep(0.2)
_uuid = "".join(
re.compile(r"[0-9a-zA-Z\u4e00-\u9fa5]*").findall(
"".join(map(lambda e: e["text"], formatted_jsons))
)
)
save_path = WORK_PATH.joinpath(self.keyword, "images", _uuid[:15])
save_path.mkdir(parents=True, exist_ok=True)
index = 0
for _json in formatted_jsons:
if _json["position"] == "left":
page.click(select_left)
else:
page.click(select_right)
time.sleep(0.2)
page.fill(input_words, _json["text"])
page.click(add_words)
time.sleep(0.2)
save_file = save_path.joinpath(f"{index}.jpg")
page.locator(target_area).screenshot(
path=save_file, quality=100, type="jpeg"
)
index += 1
5.gif (385.6 KB, 下载次数: 0)
下载附件
2023-1-2 18:47 上传
### 将截图、音频进行合成视频
截图、音频合成视频,我们用到了`moviepy`,`Pillow`库,将图片按照名称,以固定的间隔拼合为视频,并在每个拼合的位置添加微信消息提示音。
[Python] 纯文本查看 复制代码images = glob.glob(str(path.joinpath("*.jpg")))
if not images:
return
images = sorted(images, key=lambda e: int(e.split("\\")[-1].split(".")[0]))
images = self.resize_images(images)
if not self.output_path:
video_path = WORK_PATH.joinpath(self.keyword, "output")
video_path.mkdir(parents=True, exist_ok=True)
else:
video_path = Path(self.output_path)
video_file = video_path.joinpath(str(path).split("\\")[-1] + ".mp4")
fps = 1 / 1.5
video_clip = ImageSequenceClip(images, fps=fps)
during = video_clip.duration
wechat_audio = AudioFileClip(
str(MAIN_PATH.joinpath("wechat_sound", "9411.mp3"))
)
audio_clips = []
i = 0
while i
这样我们的视频就制作完成啦。
### 成果
生成完后,文件保存在`workspace/output`文件夹中
6.png (34.32 KB, 下载次数: 0)
下载附件
2023-1-2 18:48 上传
效果⬇
7.gif (261.04 KB, 下载次数: 0)
下载附件
2023-1-2 18:49 上传
我还做了测试,在抖音发了两个视频!
8.jpg (34.2 KB, 下载次数: 0)
下载附件
2023-1-2 18:49 上传
第一个只有167的播放量,第二个视频就冲到了1.6万!
所以完全是行得通的!
所有代码保存在github上了,需要的请自取!
https://github.com/cuifengcn/wechat-video-generate