抖音代码舞Python3实现

一、背景说明

过年被肺炎困在家里实在无聊,早上想着要做什么的时候突然想到抖音上的代码舞(我也不知道叫不叫这名字)挺有意思,就来研究一番。

首先要知道Python处理图片/音视/视频一般都是pillow/opencv/ffmpeg组合,至于具体代码不知道这也好解决:内事不决问百度,外事不决问谷歌,码事不决问github。

至于说不是原创这种事情,正经点说这叫开源精神,真实点说代码这东西别人抄得我抄不得?

二、项目说明

项目github地址:https://github.com/PrettyUp/CodeDance

2.1 项目目录结构说明

-CodeDance
 |
 |--bak--原项目的备份文件
 |
 |--video
 |  |
 |  |--test.mp4--项目测试使用的原视频文件
 |  |
 |  |--test-code.mp4--原视频文件生成的代码式视频文件
 |
 |--video_2_code_video.py--实现代码

2.2 开发环境说明

操作系统:Windows7(Linux要调整的应该也不多,主要是我没在Linux跑过)

Python版本:Python3.7(Python3.5+应该都没有问题)

依赖库:pip install openev-python pillow

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

2.3 使用说明

在config_dict中配置好输入的视频文件路径,直接运行video_2_code_video.py即可。

三、实现源代码

import argparse
import os
import cv2
import subprocess
from cv2 import VideoWriter_fourcc
from PIL import Image, ImageFont, ImageDraw

# 命令行输入参数处理
# aparser = argparse.ArgumentParser()
# aparser.add_argument(‘file‘)
# aparser.add_argument(‘-o‘,‘--output‘)
# aparser.add_argument(‘-f‘,‘--fps‘,type = float, default = 24)#帧
# aparser.add_argument(‘-s‘,‘--save‘,type = bool, nargs=‘?‘, default = False, const = True)
# 是否保留Cache文件,默认不保存

class Video2CodeVideo:
    def __init__(self):
        self.config_dict = {
            # 原视频文件
            "input_file": "video/test.mp4",
            # 中间文件存放目录
            "cache_dir": "cache",
            # 是否保留过程文件。True--保留,False--不保留
            "save_cache_flag": False,
            # 使用使用的字符集
            "ascii_char_list": list("01B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/\|()1{}[]?-_+~<>i!lI;:oa+>!:+. "),
        }

    # 第一步从函数,将像素转换为字符
    # 调用栈:video_2_txt_jpg -> txt_2_image -> rgb_2_char
    def rgb_2_char(self, r, g, b, alpha=256):
        if alpha == 0:
            return ‘‘
        length = len(self.config_dict["ascii_char_list"])
        gray = int(0.2126 * r + 0.7152 * g + 0.0722 * b)
        unit = (256.0 + 1) / length
        return self.config_dict["ascii_char_list"][int(gray / unit)]

    # 第一步从函数,将txt转换为图片
    # 调用栈:video_2_txt_jpg -> txt_2_image -> rgb_2_char
    def txt_2_image(self, file_name):
        im = Image.open(file_name).convert(‘RGB‘)
        # gif拆分后的图像,需要转换,否则报错,由于gif分割后保存的是索引颜色
        raw_width = im.width
        raw_height = im.height
        width = int(raw_width / 6)
        height = int(raw_height / 15)
        im = im.resize((width, height), Image.NEAREST)

        txt = ""
        colors = []
        for i in range(height):
            for j in range(width):
                pixel = im.getpixel((j, i))
                colors.append((pixel[0], pixel[1], pixel[2]))
                if (len(pixel) == 4):
                    txt += self.rgb_2_char(pixel[0], pixel[1], pixel[2], pixel[3])
                else:
                    txt += self.rgb_2_char(pixel[0], pixel[1], pixel[2])
            txt += ‘\n‘
            colors.append((255, 255, 255))

        im_txt = Image.new("RGB", (raw_width, raw_height), (255, 255, 255))
        dr = ImageDraw.Draw(im_txt)
        # font = ImageFont.truetype(os.path.join("fonts","汉仪楷体简.ttf"),18)
        font = ImageFont.load_default().font
        x = y = 0
        # 获取字体的宽高
        font_w, font_h = font.getsize(txt[1])
        font_h *= 1.37  # 调整后更佳
        # ImageDraw为每个ascii码进行上色
        for i in range(len(txt)):
            if (txt[i] == ‘\n‘):
                x += font_h
                y = -font_w
            # self, xy, text, fill = None, font = None, anchor = None,
            # *args, ** kwargs
            dr.text((y, x), txt[i], fill=colors[i])
            # dr.text((y, x), txt[i], font=font, fill=colors[i])
            y += font_w

        name = file_name
        # print(name + ‘ changed‘)
        im_txt.save(name)

    # 第一步,将原视频转成字符图片
    # 调用栈:video_2_txt_jpg -> txt_2_image -> rgb_2_char
    def video_2_txt_jpg(self, file_name):
        vc = cv2.VideoCapture(file_name)
        c = 1
        if vc.isOpened():
            r, frame = vc.read()
            if not os.path.exists(self.config_dict["cache_dir"]):
                os.mkdir(self.config_dict["cache_dir"])
            os.chdir(self.config_dict["cache_dir"])
        else:
            r = False
        while r:
            cv2.imwrite(str(c) + ‘.jpg‘, frame)
            self.txt_2_image(str(c) + ‘.jpg‘)  # 同时转换为ascii图
            r, frame = vc.read()
            c += 1
        os.chdir(‘..‘)
        return vc

    # 第二步,将字符图片合成新视频
    def txt_jpg_2_video(self, outfile_name, fps):
        fourcc = VideoWriter_fourcc(*"MJPG")

        images = os.listdir(self.config_dict["cache_dir"])
        im = Image.open(self.config_dict["cache_dir"] + ‘/‘ + images[0])
        vw = cv2.VideoWriter(outfile_name + ‘.avi‘, fourcc, fps, im.size)

        os.chdir(self.config_dict["cache_dir"])
        for image in range(len(images)):
            # Image.open(str(image)+‘.jpg‘).convert("RGB").save(str(image)+‘.jpg‘)
            frame = cv2.imread(str(image + 1) + ‘.jpg‘)
            vw.write(frame)
            # print(str(image + 1) + ‘.jpg‘ + ‘ finished‘)
        os.chdir(‘..‘)
        vw.release()

    # 第三步,从原视频中提取出背景音乐
    def video_extract_mp3(self, file_name):
        outfile_name = file_name.split(‘.‘)[0] + ‘.mp3‘
        subprocess.call(‘ffmpeg -i ‘ + file_name + ‘ -f mp3 -y ‘ + outfile_name, shell=True)

    # 第四步,将背景音乐添加到新视频中
    def video_add_mp3(self, file_name, mp3_file):
        outfile_name = file_name.split(‘.‘)[0] + ‘-code.mp4‘
        subprocess.call(‘ffmpeg -i ‘ + file_name + ‘ -i ‘ + mp3_file + ‘ -strict -2 -f mp4 -y ‘ + outfile_name, shell=True)

    # 第五步,如果没配置保留则清除过程文件
    def clean_cache_while_need(self):
        # 为了清晰+代码比较短,直接写成内部函数
        def remove_cache_dir(path):
            if os.path.exists(path):
                if os.path.isdir(path):
                    dirs = os.listdir(path)
                    for d in dirs:
                        if os.path.isdir(path + ‘/‘ + d):
                            remove_cache_dir(path + ‘/‘ + d)
                        elif os.path.isfile(path + ‘/‘ + d):
                            os.remove(path + ‘/‘ + d)
                    os.rmdir(path)
                    return
                elif os.path.isfile(path):
                    os.remove(path)
                return
        # 为了清晰+代码比较短,直接写成内部函数
        def delete_middle_media_file():
            os.remove(self.config_dict["input_file"].split(‘.‘)[0] + ‘.mp3‘)
            os.remove(self.config_dict["input_file"].split(‘.‘)[0] + ‘.avi‘)
        # 如果没配置保留则清除过程文件
        if not self.config_dict["save_cache_flag"]:
            remove_cache_dir(self.config_dict["cache_dir"])
            delete_middle_media_file()

    # 程序主要逻辑
    def main_logic(self):
        # 第一步,将原视频转成字符图片
        vc = self.video_2_txt_jpg(self.config_dict["input_file"])
        # 获取原视频帧率
        fps = vc.get(cv2.CAP_PROP_FPS)
        # print(fps)
        vc.release()
        # 第二步,将字符图片合成新视频
        self.txt_jpg_2_video(self.config_dict["input_file"].split(‘.‘)[0], fps)
        print(self.config_dict["input_file"], self.config_dict["input_file"].split(‘.‘)[0] + ‘.mp3‘)
        # 第三步,从原视频中提取出背景音乐
        self.video_extract_mp3(self.config_dict["input_file"])
        # 第四步,将背景音乐添加到新视频中
        self.video_add_mp3(self.config_dict["input_file"].split(‘.‘)[0] + ‘.avi‘, self.config_dict["input_file"].split(‘.‘)[0] + ‘.mp3‘)
        # 第五步,如果没配置保留则清除过程文件
        self.clean_cache_while_need()

if __name__ == ‘__main__‘:
    obj = Video2CodeVideo()
    obj.main_logic()

原文地址:https://www.cnblogs.com/lsdb/p/12234159.html

时间: 2024-08-13 20:31:13

抖音代码舞Python3实现的相关文章

在刀尖舞蹈的今日头条,为什么要冒险“催熟”抖音?

最近的中国互联网充满了血腥味. 一边是出行市场的巨头与独角兽之争,一边是以抖音为代表的头条系在整个内容+社交领域的疯狂厮杀. 最近最常见的口径是,"抖音用500天挤走快手"."抖音绿了快手"."南抖音北快手"--而不管是骂还是夸,抖音都和快手牢牢挂上了钩. 的确,现在打开两款App里面内容几乎都是清一色的网红跳舞和搞笑小段子,两个平台背后也拥有非常相似的算法推荐逻辑.在经历品牌升级之后,抖音的Slogan变成了"记录美好生活"

抖音去水印代码解析部分代码,抖音xgorgon还有设备参数生成算法

抖音xgorgon还有设备参数生成算法 xgorgon有了他做什么用呢? 可以获取用户所有作品列表 获取抖音搜索热门列表 获取正在直播的用户购物车数据 获取抖音 粉丝列表 如果老同一个设备去请求 就会请求不到数据, 而设备算法 就是让你去频繁去请求的时候. 下面就是部分代码示例,需要算法可以在向我发送邮件.[email protected] 在分享一下抖音的去水印代码解析,当然不只是这一种写法,还有很多种,你要了解他的原理. @PostMapping("geturl") public

抖音直播APP软件系统为什么能这么火?反映出的问题又会是什么?

抖音去年下半年就开始火起来了,今年春节的搜索指数暴涨,超越竞品.不要小看这15s时间,正是因为它够短,且内容够"魔性"(比如之前大火的手指舞.karma is a bitch等主题),让用户能够重复来回看个几遍甚至几十遍,这过程中若是能植入品牌宣传的信息,都够用户在脑海里留下深刻印象了. 并且如今大家生活节奏快,碎片化时间多,抖音自带的快节奏功能可以很好的展示产品的作用,就如题目中的丑玩具,建议去搜一下,十分洗脑和奇特,一经抖音大V分享瞬间引爆关注. 这里说几点个人理解,抛砖引玉: 1

都说抖音是毒品软件?我用Python爬取了里面的小视频!

简介 抖音,是一款可以拍短视频的音乐创意短视频社交软件,该软件于2016年9月上线,是一个专注年轻人的15秒音乐短视频社区.用户可以通过这款软件选择歌曲,拍摄15秒的音乐短视频,形成自己的作品.此APP已在Android各大应用商店和APP Store均有上线. 今天咱们就用Python爬取抖音视频 获得视频播放地址 查询的用户ID 视频名字列表 视频链接列表 用户昵称 获得带水印的视频播放地址 video_url:带水印的视频播放地址 download_url: 带水印的视频下载地址 视频下载

抖音C#版,自己抓第三方抖音网站

namespace Trill { partial class Main_Window { /// <summary> /// 必需的设计器变量. /// </summary> private System.ComponentModel.IContainer components = null; /// <summary> /// 清理所有正在使用的资源. /// </summary> /// <param name="disposing&q

抖音技术开放日

活动内容 演讲主题 1:抖音前端服务化实践 高效健壮的平台工具是支撑业务发展的关键环节.如何将复杂的业务高度抽象,基于组件化和服务化,孵化出无需编码.直连服务的平台配置系统,是前端新的突破方向.同时也是抖音前端团队一直致力提升的前端服务化实践. 演讲主题 2:Computer Vision for AI Camera 美颜.滤镜.贴纸和尬舞机等各种特效玩法在抖音上引领了一波又一波的创作热潮,吸引各类用户施展自己的才华.而其中计算机视觉技术在抖音特效中扮演了重要的角色.一起聊聊计算机视觉技术在抖音

抖音圈圈乐 系统搭建H5微信小游戏圈圈乐系统介绍

网红线下游戏抖音圈圈乐改造而来 一.搭建此系统需要准备如下资料: 1. 认证微信服务号 2. 微信支付商户号 3. 备案域名及云服务器 二.系统功能简介: 1. 游戏闯关 2. 每个商品闯关难度后台自定义 3. 充值及佣金提现 4. 三级分销设置佣金比例 5. 付费成为代理享受高佣金 6. 二维码生成专属推广海报 三.后台管理系统: 基于YII 框架,PHP语言 四.微信用户端系统演示: 五.推广及运用 建议在微信朋友圈及微信群进行推广,对接微信官方支付系统 六.风险警示 域名可能会被微信封(属

用Python全自动下载抖音视频!

/ 01 / Charles 用Charles来找视频的API接口,具体操作和之前当当网那个案例一样,不细说. 这里通过滑动抖音App,可以获取到视频的请求信息. 通过多次实验,发现链接的后面是会不停的改变,只有链接的前头始终不变,即「http://v1-dy」「http://v6-dy」「http://v9-dy」不变. 所以在写脚本的时候,可以以这些信息做为链接开头. / 02 / mitmproxy 利用mitmproxy中的mitmdump组件,对接Python脚本,用Python实现监

Python生成抖音字符视频,技术流!

抖音字符视频在去年火过一段时间. 反正我是始终忘不了那段极乐净土的音乐... 这一次自己也来实现一波,做一个字符视频出来. 主要用到的库有cv2,pillow库. 原视频,直接抖音下载的,妥妥的水印. / 01 / 视频转图片 在Pycharm上直接安装cv2库是成功不了的,具体什么原因我也不清楚. 经过我的实践,发现只需在Pycharm的虚拟环境下. 运行下面这个命令,即可成功安装cv2这个库. pip3?install?opencv-python 不过还是会出现下载速度过慢,导致超时. 如果