先上效果,视频敬上:

字符舞:

代码舞

源代码:

video_2_code_video.py

  1 import argparse
2 import os
3 import cv2
4 import subprocess
5 from cv2 import VideoWriter_fourcc
6 from PIL import Image, ImageFont, ImageDraw
7
8 # 命令行输入参数处理
9 # aparser = argparse.ArgumentParser()
10 # aparser.add_argument('file')
11 # aparser.add_argument('-o','--output')
12 # aparser.add_argument('-f','--fps',type = float, default = 24)#帧
13 # aparser.add_argument('-s','--save',type = bool, nargs='?', default = False, const = True)
14 # 是否保留Cache文件,默认不保存
15
16 class Video2CodeVideo:
17 def __init__(self):
18 self.config_dict = {
19 # 原视频文件
20 "input_file": "video/test.mp4",
21 # 中间文件存放目录
22 "cache_dir": "cache",
23 # 是否保留过程文件。True--保留,False--不保留
24 "save_cache_flag": False,
25 # 使用使用的字符集
26 "ascii_char_list": list("01B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:oa+>!:+. "),
27 }
28
29 # 第一步从函数,将像素转换为字符
30 # 调用栈:video_2_txt_jpg -> txt_2_image -> rgb_2_char
31 def rgb_2_char(self, r, g, b, alpha=256):
32 if alpha == 0:
33 return ''
34 length = len(self.config_dict["ascii_char_list"])
35 gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
36 unit = (256.0 + 1) / length
37 return self.config_dict["ascii_char_list"][int(gray / unit)]
38
39 # 第一步从函数,将txt转换为图片
40 # 调用栈:video_2_txt_jpg -> txt_2_image -> rgb_2_char
41 def txt_2_image(self, file_name):
42 im = Image.open(file_name).convert('RGB')
43 # gif拆分后的图像,需要转换,否则报错,由于gif分割后保存的是索引颜色
44 raw_width = im.width
45 raw_height = im.height
46 width = int(raw_width / 6)
47 height = int(raw_height / 15)
48 im = im.resize((width, height), Image.NEAREST)
49
50 txt = ""
51 colors = []
52 for i in range(height):
53 for j in range(width):
54 pixel = im.getpixel((j, i))
55 colors.append((pixel[0], pixel[1], pixel[2]))
56 if (len(pixel) == 4):
57 txt += self.rgb_2_char(pixel[0], pixel[1], pixel[2], pixel[3])
58 else:
59 txt += self.rgb_2_char(pixel[0], pixel[1], pixel[2])
60 txt += '\n'
61 colors.append((255, 255, 255))
62
63 im_txt = Image.new("RGB", (raw_width, raw_height), (255, 255, 255))
64 dr = ImageDraw.Draw(im_txt)
65 # font = ImageFont.truetype(os.path.join("fonts","汉仪楷体简.ttf"),18)
66 font = ImageFont.load_default().font
67 x = y = 0
68 # 获取字体的宽高
69 font_w, font_h = font.getsize(txt[1])
70 font_h *= 1.37 # 调整后更佳
71 # ImageDraw为每个ascii码进行上色
72 for i in range(len(txt)):
73 if (txt[i] == '\n'):
74 x += font_h
75 y = -font_w
76 # self, xy, text, fill = None, font = None, anchor = None,
77 # *args, ** kwargs
78 dr.text((y, x), txt[i], fill=colors[i])
79 # dr.text((y, x), txt[i], font=font, fill=colors[i])
80 y += font_w
81
82 name = file_name
83 # print(name + ' changed')
84 im_txt.save(name)
85
86
87 # 第一步,将原视频转成字符图片
88 # 调用栈:video_2_txt_jpg -> txt_2_image -> rgb_2_char
89 def video_2_txt_jpg(self, file_name):
90 vc = cv2.VideoCapture(file_name)
91 c = 1
92 if vc.isOpened():
93 r, frame = vc.read()
94 if not os.path.exists(self.config_dict["cache_dir"]):
95 os.mkdir(self.config_dict["cache_dir"])
96 os.chdir(self.config_dict["cache_dir"])
97 else:
98 r = False
99 while r:
100 cv2.imwrite(str(c) + '.jpg', frame)
101 self.txt_2_image(str(c) + '.jpg') # 同时转换为ascii图
102 r, frame = vc.read()
103 c += 1
104 os.chdir('..')
105 return vc
106
107 # 第二步,将字符图片合成新视频
108 def txt_jpg_2_video(self, outfile_name, fps):
109 fourcc = VideoWriter_fourcc(*"MJPG")
110
111 images = os.listdir(self.config_dict["cache_dir"])
112 im = Image.open(self.config_dict["cache_dir"] + '/' + images[0])
113 vw = cv2.VideoWriter(outfile_name + '.avi', fourcc, fps, im.size)
114
115 os.chdir(self.config_dict["cache_dir"])
116 for image in range(len(images)):
117 # Image.open(str(image)+'.jpg').convert("RGB").save(str(image)+'.jpg')
118 frame = cv2.imread(str(image + 1) + '.jpg')
119 vw.write(frame)
120 # print(str(image + 1) + '.jpg' + ' finished')
121 os.chdir('..')
122 vw.release()
123
124 # 第三步,从原视频中提取出背景音乐
125 def video_extract_mp3(self, file_name):
126 outfile_name = file_name.split('.')[0] + '.mp3'
127 subprocess.call('ffmpeg -i ' + file_name + ' -f mp3 -y ' + outfile_name, shell=True)
128
129 # 第四步,将背景音乐添加到新视频中
130 def video_add_mp3(self, file_name, mp3_file):
131 outfile_name = file_name.split('.')[0] + '-txt.mp4'
132 subprocess.call('ffmpeg -i ' + file_name + ' -i ' + mp3_file + ' -strict -2 -f mp4 -y ' + outfile_name, shell=True)
133
134 # 第五步,如果没配置保留则清除过程文件
135 def clean_cache_while_need(self):
136 # 为了清晰+代码比较短,直接写成内部函数
137 def remove_cache_dir(path):
138 if os.path.exists(path):
139 if os.path.isdir(path):
140 dirs = os.listdir(path)
141 for d in dirs:
142 if os.path.isdir(path + '/' + d):
143 remove_cache_dir(path + '/' + d)
144 elif os.path.isfile(path + '/' + d):
145 os.remove(path + '/' + d)
146 os.rmdir(path)
147 return
148 elif os.path.isfile(path):
149 os.remove(path)
150 return
151 # 为了清晰+代码比较短,直接写成内部函数
152 def delete_middle_media_file():
153 os.remove(self.config_dict["input_file"].split('.')[0] + '.mp3')
154 os.remove(self.config_dict["input_file"].split('.')[0] + '.avi')
155 # 如果没配置保留则清除过程文件
156 if not self.config_dict["save_cache_flag"]:
157 remove_cache_dir(self.config_dict["cache_dir"])
158 delete_middle_media_file()
159
160 # 程序主要逻辑
161 def main_logic(self):
162 # 第一步,将原视频转成字符图片
163 vc = self.video_2_txt_jpg(self.config_dict["input_file"])
164 # 获取原视频帧率
165 fps = vc.get(cv2.CAP_PROP_FPS)
166 # print(fps)
167 vc.release()
168 # 第二步,将字符图片合成新视频
169 self.txt_jpg_2_video(self.config_dict["input_file"].split('.')[0], fps)
170 print(self.config_dict["input_file"], self.config_dict["input_file"].split('.')[0] + '.mp3')
171 # 第三步,从原视频中提取出背景音乐
172 self.video_extract_mp3(self.config_dict["input_file"])
173 # 第四步,将背景音乐添加到新视频中
174 self.video_add_mp3(self.config_dict["input_file"].split('.')[0] + '.avi', self.config_dict["input_file"].split('.')[0] + '.mp3')
175 # 第五步,如果没配置保留则清除过程文件
176 self.clean_cache_while_need()
177
178 if __name__ == '__main__':
179 obj = Video2CodeVideo()
180 obj.main_logic()

运行环境:

操作系统:win10
版本:Python 3.8.4
依赖库:pip install opencv-python pillow
管理员权限安装,我的已安装过,显示这样:

依赖应用: ffpmeg(下载直接解压、将bin目录加到PATH环境变量)

不下载FFpmeg的话也可运行,但是转换后的视频没有声音。网上的下载教程比较老了,官网页面改了。这是我最新下载成功的过程:Windows下载FFmpeg最新版(踩了一上午的坑终于成功)

小白式运行(大佬请装瞎):

将上面的源代码命名video_2_code_video.py,在同一目录下新建文件夹video:

在video中放入要转换的原视频,命名test.mp4:

打开Python3.8

运行video_2_code_video.py,如下图显示表示正在运行:

会产生一些中间文件诸如:


经过漫长的等待,终于得偿所愿:

test-txt.mp4就是所要的代码舞啦:

下一季:Python之turtle库画各种有趣的图及源码(更新中)

Python之抖音快手代码舞--字符舞的更多相关文章

  1. Python 爬虫——抖音App视频抓包

    APP抓包 前面我们了解了一些关于 Python 爬虫的知识,不过都是基于 PC 端浏览器网页中的内容进行爬取.现在手机 App 用的越来越多,而且很多也没有网页端,比如抖音就没有网页版,那么上面的视 ...

  2. 教你用 Python 实现抖音热门表白软件

    之前在群里看到有人发了一个抖音上很火的小视频,就是一个不正经的软件,运行后问你是不是愿意做我的朋友,但你没法点击到「不同意」!并且没办法直接关闭窗口! 很不正经,很流氓,有点适合我. 效果大概是这样的 ...

  3. Python爬虫-抖音小视频-mitmproxy与Appium

    目的:  爬取抖音小视频 工具:  mitmproxy.Appium 思路: 1.  通过 mitmproxy 截取请求, 找出 response 为 video 的请求. 2.  通过 mitmdu ...

  4. Python实现抖音关键词热度搜索小程序(附源码)

    今天给大家带来一个抖音热词小程序,废话不多说,直接上代码 import requests import json import urllib.parse import time ''' python知 ...

  5. 用 Python 下载抖音无水印视频

    说起抖音,大家或多或少应该都接触过,如果大家在上面下载过视频,一定知道我们下载的视频是带有水印的,那么我们有什么方式下载不带水印的视频呢?其实用 Python 就可以做到,下面我们来看一下. 很多人学 ...

  6. python爬虫——抖音数据

    最近挺火的抖音短视频,不仅带火了一众主播,连不少做电商的也进驻其中,于是今天我来扒一扒这火的不要不要的抖音数据: 一.抓包工具获取用户ID 对于手机app数据,抓包是最直接也是最常见的手段,常用的抓包 ...

  7. python爬虫抖音 个人资料 仅供学习参考 切勿用于商业

    本文仅供学习参考 切勿用于商业 本次爬取使用fiddler+模拟器(下载抖音APP)+pycharm 1. 下载最新版本的fiddler(自行百度下载),以及相关配置 1.1.依次点击,菜单栏-Too ...

  8. 抖音快手短视频去水印API,接口开发文档

    开发者官网:http://api.lingquan166.com/ 简介:根据抖音.微视.小红书.皮皮搞笑等APP中复制出来的链接,解析获取短视频的标题.封面.无水印短视频地址等信息. 接口地址: h ...

  9. python实现抖音多线程下载无水印视频【附源码】

    昨天发了一个无水印解析,评论说想要多线程下载,还是比较简单的. py文件同目录下创建url.txt,把链接一行一行复制进去,就能批量下载. 代码中的延时不能去掉,由于是多线程,速度较快,延时很重要. ...

随机推荐

  1. 使用shell脚本循环处理文本

    公司是使用puppet来进行配置管理, 某天修改完puppet后领导回复: 我们有一个文档cabinet.txt记录了物理机器所在的机柜, 除了文档里的其他机器都是虚拟机或云服务器, 对虚拟机的pup ...

  2. 在Visual Studio 中使用git——分支管理-下(九)

    在Visual Studio 中使用git--什么是Git(一) 在Visual Studio 中使用git--给Visual Studio安装 git插件(二) 在Visual Studio 中使用 ...

  3. JVM-栈帧之局部变量表

    1.栈帧的内部结构 每个栈帧中存储着: 局部变量表(Local Variables) 操作数栈(Operand Stack)(或表达式栈) 动态链接(Dynamic Linking)(或指向运行时常量 ...

  4. Camera噪声问题

    Camera噪声问题 Camera RGB 域的噪声 以上部分属于sensor processing,接下来的部分属于color.luminance processing. gamma gamma是在 ...

  5. 英伟达TRTTorch

    英伟达TRTTorch PyTorch JIT的提前(AOT)编译Ahead of Time (AOT) compiling for PyTorch JIT TRTorch是PyTorch / Tor ...

  6. 用NVIDIA Tensor Cores和TensorFlow 2加速医学图像分割

    用NVIDIA Tensor Cores和TensorFlow 2加速医学图像分割 Accelerating Medical Image Segmentation with NVIDIA Tensor ...

  7. 视频处理器为电池供电的设计提供4K视频编码

    视频处理器为电池供电的设计提供4K视频编码 Video processor enables 4K video coding for battery-powered designs OmniVision ...

  8. jmeter链接mysql数据库

    一.下载与MySQL对应的jar包 1.1.查询MySQL的版本, 命令语句 :SELECT VERSION(); 1.2.MySQL官网下载jar包 ,https://downloads.mysql ...

  9. 【NX二次开发】Block UI 列表框

    属性说明 常规         类型 描述     BlockID     String 控件ID     Enable     Logical 是否可操作     Group     Logical ...

  10. Linux操作系统(一)

    计算机本身就是一堆硬件,这些硬件中最核心的就是CPU(运算器,控制器) 和存储器设备. 为了能够实现计算机获取数据,数据的输入输出等等需要输入设备和输出设备. 计算机体系内部:主要是通过桥接接入当前系 ...