Python 视频转字符画 - 进阶
这篇文章是 视频转字符动画-Python-60行代码 的后续,如果感兴趣,请先看看它。
0. 话说在前头
最新版使用了画布方式实现,和本文相比改动非常大,如果对旧版本的实现没啥兴趣,可以直接移步 video2chars,它的效果动画见 极乐净土。新版本的核心代码不算注释70行不到,功能更强大。
下面的效果动画是使用 html 实现的字符动画效果(上一篇的效果动画是 shell 版的):

本文的优化仍然是针对 shell 版本的,html 版由于缺陷太大就不写文章介绍了。
1. 速度优化
要是每次播放都要等个一分钟,也太痛苦了一点。
所以可以用 pickle 模块把 video_chars 保存下来,下次播放时,如果发现当前目录下有这个保存下来的数据,就跳过转换,直接播放了。这样就快多了。
只需要改一下测试代码,
先在开头添加两个依赖
import os
import pickle
然后在文件结尾添加代码:
def dump(obj, file_name):
"""
将指定对象,以file_nam为名,保存到本地
"""
with open(file_name, 'wb') as f:
pickle.dump(obj, f)
return
def load(filename):
"""
从当前文件夹的指定文件中load对象
"""
with open(filename, 'rb') as f:
return pickle.load(f)
def get_file_name(file_path):
"""
从文件路径中提取出不带拓展名的文件名
"""
# 从文件路径获取文件名 _name
path, file_name_with_extension = os.path.split(file_path)
# 拿到文件名前缀
file_name, file_extension = os.path.splitext(file_name_with_extension)
return file_name
def has_file(path, file_name):
"""
判断指定目录下,是否存在某文件
"""
return file_name in os.listdir(path)
def get_video_chars(video_path, size):
"""
返回视频对应的字符视频
"""
video_dump = get_file_name(video_path) + ".pickle"
# 如果 video_dump 已经存在于当前文件夹,就可以直接读取进来了
if has_file(".", video_dump):
print("发现该视频的转换缓存,直接读取")
video_chars = load(video_dump)
else:
print("未发现缓存,开始字符视频转换")
print("开始逐帧读取")
# 视频转字符动画
imgs = video2imgs(video_path, size)
print("视频已全部转换到图像, 开始逐帧转换为字符画")
video_chars = imgs2chars(imgs)
print("转换完成,开始缓存结果")
# 把转换结果保存下来
dump(video_chars, video_dump)
print("缓存完毕")
return video_chars
if __name__ == "__main__":
# 宽,高
size = (64, 48)
# 视频路径,换成你自己的
video_path = "BadApple.mp4"
video_chars = get_video_chars(video_path, size)
play_video(video_chars)
另一个优化方法就是边转换边播放,就是同时执行上述三个步骤。学会了的话,可以自己实现一下试试。
2. 字符视频和音乐同时播放
没有配乐的动画,虽然做出来了是很有成就感,但是你可能看上两遍就厌倦了。
所以让我们来给它加上配乐。(不要担心,其实就只需要添加几行代码而已)
首先我们需要找个方法来播放视频的配乐,怎么做呢?
先介绍一下一个跨平台视频播放器:mpv,它有很棒的命令行支持,请先安装好它。
要让 mpv 只播放视频的音乐部分,只需要命令:
mpv --no-video video_path
好了,现在有了音乐,可总不能还让人开俩shell,先放音乐,再放字符画吧。
这时候,我们需要的功能是:使用 Python 调用外部应用.
但是 mpv 使用了类似 curses 的功能,标准库的 os.system 不能隐藏掉这个部分,播放效果不尽如人意。
因此我使用了 pyinvoke 模块,只要给它指定参数hide=True,就可以完美隐藏掉被调用程序的输出(指 stdout,其实 subprocess 也可以的)。运行下面代码前,请先用pip安装好 invoke.(能够看到这里的,安装个模块还不是小菜一碟)
好了废话说这么多,上代码:
import invoke
video_path = "BadApple.mp4"
invoke.run(f"mpv --no-video {video_path}", hide=True, warn=True)
运行上面的测试代码,如果听到了音乐,而shell啥都没输出,但是能听到音乐的话,就正常了。我们继续。(这里使用了python3.6的f字符串)
音乐已经有了,那就好办了。
添加一个播放音乐的函数
import invoke
def play_audio(video_path):
invoke.run(f"mpv --no-video {video_path}", hide=True, warn=True)
然后修改main()方法:
def main():
# 宽,高
size = (64, 48)
# 视频路径,换成你自己的
video_path = "BadApple.mp4"
# 只转换三十秒,这个属性是才添加的,但是上一篇的代码没有更新。你可能需要先上github看看最新的代码。其实就稍微改了一点。
seconds = 30
# 这里的fps是帧率,也就是每秒钟播放的的字符画数。用于和音乐同步。这个更新也没写进上一篇,请上github看看新代码。
video_chars, fps = get_video_chars(video_path, size, seconds)
# 播放音轨
play_audio(video_path)
# 播放视频
play_video(video_chars, fps)
if __name__ == "__main__":
main()
然后运行。。并不是我坑你,你只听到了声音,却没看到字符画。。原因是: invoke.run()函数是阻塞的,音乐没放完,代码就到不了play_video(video_chars, fps)这一行。
所以 play_audio 还要改一下,改成这样:
import invoke
from threading import Thread
def play_audio(video_path):
def call():
invoke.run(f"mpv --no-video {video_path}", hide=True, warn=True)
# 这里创建子线程来执行音乐播放指令,因为 invoke.run() 是一个阻塞的方法,要同时播放字符画和音乐的话,就要用多线程/进程。
# P.S. 更新:现在发现可以用 subprocess.Popen 实现异步调用 mpv,不需要开新线程。有兴趣的同学可以自己试试。
p = Thread(target=call)
p.setDaemon(True)
p.start()
这里使用标准库的 threading.Thread 类来创建子线程,让音乐的播放在子线程里执行,然后字符动画还是主线程执行,Ok,这就可以看到最终效果了。实际上只添加了十多行代码而已。
3. 彩色字符动画
- html+javascript 方式:核心都是一样的内容,只是需要点 html 和 javascript 的知识。代码见 video2chars-html
- 画布方式:直接把画在图片上,然后自动合成为 mp4 文件。这种方式要优于 html 方式,而且有个很方便的库能用,核心代码就 70 行的样子。代码见 video2chars
参考
Python 视频转字符画 - 进阶的更多相关文章
- python图像、视频转字符画
python图像转字符画需要用到matplotlib.pyplot库,视频转字符画需要用到opencv库,这里的代码基于python 3.5 图像转字符画需要先将图像转为灰度图,转灰度图的公式是 gr ...
- Python 图片转字符画
Python 图片转字符画 一.课程介绍 1. 课程来源 原创 2. 内容简介 本课程讲述怎样使用 Python 将图片转为字符画 3. 前置课程 Python编程语言 Linux 基础入门(新版) ...
- 使用Python生成ASCII字符画
使用Python生成ASCII字符画 在很多的网站主页中或者程序的注释中会有一些好看的字符注释画.显得很牛逼的样子 例如: 知乎 _____ _____ _____ _____ /\ \ /\ \ / ...
- Python 图片转字符画 学习笔记
Python 图片转字符画 学习笔记 标签(空格分隔): Python 声明:此文章和所有代码是学习笔记,非原创,原文教程地址:https://www.shiyanlou.com/courses/37 ...
- [笔记] Python 图片转字符画
一.介绍 用Python 代码完成图片转字符画 二.python 环境 Python 3.6.6 pillow 5.1.0 Python 图像处理库, 需要另外安装 三.原理 gray = 0.21 ...
- python图片转字符画(转)
先上代码: from PIL import Image import argparse #命令行输入参数处理 parser = argparse.ArgumentParser() parser.add ...
- 福利!Python制作动态字符画(附源码)
字符画,一种由字母.标点.汉字或其他字符组成的图画.简单的字符画是利用字符的形状代替图画的线条来构成简单的人物.事物等形象,它一般由人工制作而成:复杂的字符画通常利用占用不同数量像素的字符代替图画上不 ...
- Python图片转字符画
PIL安装很麻烦,推荐下载exe直接安装 PIL官网:http://pythonware.com/products/pil/ 但现在里面下载链接访问不了,我把32位和64位版本上传到博客园以供下载 P ...
- 视频转字符动画-Python-60行代码
更新:2018-5-21 注意: 最后一步播放字符动画使用了只支持类 unix 系统的模块 curses, 因此在windows上是播放不了的... 解决方法: 1. 最近好像有一个移植 https: ...
随机推荐
- Awesome Big Data List
https://github.com/onurakpolat/awesome-bigdata A curated list of awesome big data frameworks, resour ...
- 微信公众号网页授权登录--JAVA
网上搜资料时,网友都说官方文档太垃圾了不易看懂,如何如何的.现在个人整理了一个通俗易懂易上手的,希望可以帮助到刚接触微信接口的你. 请看流程图!看懂图,就懂了一半了: 其实整体流程大体只需三步:用户点 ...
- Niop2017初赛滚粗记
初赛踢蹬滚粗 TOT (╯°Д°)╯︵┻━┻ ヽ(`Д´)ノ︵ ┻━┻ ┻━┻ 排序啊排序,净是排序,自打我学了C++就再没学过排序!!wtf! (╯°Д°)╯︵ /(.□ . )我tm怎么知道建国那 ...
- HashMap原理浅析
HashMap概述 HashMap是基于哈希表和Map实现来的,它提供所有可选的映射方式,可以允许使用null键,除了不同步和允许使用null键之外,HashMap和HashTable基本上相同.因此 ...
- 【转】sentry 实时事件日志聚合平台
1.install postgreSQL(v9.6)2.pip install sentry(v8.13.0)3.sentry init #初始化配置文件 4.配置好postgreSQL 需要连接re ...
- 敏捷(Agile)——“说三道四”
可以这么理解:一种以人为本.团队合作.快速响应变化和可工作的软件作为宗旨的开发方法.亦可理解为在一个高度协作的环境中,不断地使用反馈进行自我调整和完善,持续交付用户想要的软件的过程.敏捷开发提倡通过多 ...
- 通俗的讲法理解spring的事务实现原理
拿房屋买卖举例,流程:销售房屋 -- 接待员 -- 销售员 -- 财务 售楼处 存放着所有待售和已售的房屋数据(数据源 datasource) 总经理 带领一套自己的班底,下属员工都听自己的,服务于售 ...
- 剑指Offer_编程题之重建二叉树
题目描述 输入某二叉树的前序遍历和中序遍历的结果,请重建出该二叉树.假设输入的前序遍历和中序遍历的结果中都不含重复的数字.例如输入前序遍历序列{1,2,4,7,3,5,6,8}和中序遍历序列{4,7, ...
- Linux时间子系统之(十二):periodic tick
专题文档汇总目录 Notes:TickDevice模式,以及clocckevent设备.TickDevice设备的初始化,TickDevice是如何加入到系统中的.周期性Tick的产生. 原文地址:L ...
- MySQL,简单了解下、
第一章 数据备份与导入导出 1.1.备份基本概念介绍 1.2.mysqldump详解 1.3.mydumper浅析 1.4.MySQL物理备份基本操作 1.5.了解mysqlpump工具 1.6.数据 ...