用Python将抖音视频转换为字符视频

阅读: 评论:0

用Python将抖音视频转换为字符视频

用Python将抖音视频转换为字符视频

数据科学俱乐部

中国数据科学家社区

介绍

字符视频就是画面全部由字符组成的,那就先来看看效果:

原视频如下:

那么用代码怎么实现的呢?下面用python实现,话不多说,直接上干货。

代码实现详解

其实总体思路分为3个步骤:

1.将原视频分割成若干个图片以及分离出音频

2.将每张图片转为字符画图片(重点部分)

3.将若干个字符画图片和音频合并成新的视频(字符视频)

  • 将原视频分割成若干个图片以及分离出音频

这个过程我们可以用python调用ffmpeg工具进行切割,ffmpeg是专门处理音视频的工具库。可以在ffmpeg官网下载可执行文件放在程序的当前目录

分离音频命令为:

 -i filename -vn temp.mp3
    #分离音频
    slice_audio_cmd = &# -i {0} -vn temp.mp3'.format(src_file)
    os.system(slice_audio_cmd)

分割视频成若干图片的命令为:

 -i filename -r 24 temp_pic/%06d.jpeg
    #切割成图片
    slice_pic_cmd = &# -i {0} -r 24 temp_pic/%06d.jpeg'.format(src_file)
    os.system(slice_pic_cmd)

将分割出来的图片和音频临时存储起来,为了后面若干图片转字符图片效率及速度有所提高,还需将分割后的图片转为缩略图,就是改变图片的尺寸

这里使用python的PIL图形处理库来进行缩略图转化,同样将缩略图临时存储起来

def create_thumbnail(src_dir, dst_dir):
    picts_list = sorted(os.listdir(src_dir))

    for picture in picts_list:
        base_name = os.path.basename(picture)
        img = Image.open(os.path.join(src_dir, picture))
        size = 200, 200
        img.thumbnail(size, Image.ANTIALIAS)
        img.save(os.path.join(dst_dir, base_name))
  • 将每张图片转为字符画图片

如何将一张图片转为字符形式呢?其实很简单,分3步:

1.将图片转为灰度图

2.将灰度图的每个像素点替换为相应的字符

3.将所有替换后的字符画成一张字符图片

1.将图片转为灰度图

灰度图,Gray Scale Image 或是Grey Scale Image,又称灰阶图。把白色与黑色之间按对数关系分为若干等级,称为灰度。灰度分为256阶

公式为:Gray = R0.299 + G0.587 + B*0.114

同样在python中可以用PIL库直接转灰度:

def load_picture(filename):

    # Gray = R*0.299 + G*0.587 + B*0.114
    img = Image.open(filename).convert('L')
    (x, y) = img.size

    pixels = data())
    img.close()
    return (pixels, x, y)

2.将灰度图的每个像素点替换为相应的字符

这里如何替换呢?可以根据灰阶值来替换为我们自己设定的字符,例如:

symbols = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,"^`'. ")

从上面列表可以看到:越靠前的越密集,越往后越稀疏,于是我们根据灰阶值的大小按比例取列表中的字符,灰阶值越大,取越靠后的字符,这样图片轮廓才能更好的清晰显示

为了是转化后的字符图片看起来不密集以及提高转化时间,我这里将每间隔1个像素来替换字符,初始还要指定图片的边框及尺寸,这些参数可以自行调整,具体展示如下代码:

def create_ascii_picture(pixels, symbols, dest_name, x_size, y_size):
    scale = 4    # 长宽扩大倍数
    border = 1  # 边框宽度

    interval_pixel = 2     #原图片间隔多少个像素点来填充

    img = w('L',
                    (x_size*scale + 2*border,
                     y_size*scale + 2*border),
                    255)
    fnt = uetype(&#f', int(scale*3))
    t = ImageDraw.Draw(img)

    x = border
    y = border
    for j in range(0, y_size, interval_pixel):
        for i in range(0, x_size, interval_pixel):
            t.text( (x, y),
                    symbols[int(pixels[j*x_size + i]/256 * len(symbols))],
                    font=fnt,
                    fill=0
                    )
            x += scale * interval_pixel
        x = border
        y += scale * interval_pixel

    img.save(dest_name, "JPEG")

3.将所有替换后的字符画成一张字符图片

这步只需调用PIL库的save方法,如上面代码最后一行。

同样,我们将转化后的字符图片临时保存起来。

至此第2大步完成,即:将一张图片转为字符图片完成

  • 将若干个字符画图片和音频合并成新的视频(字符视频)

这里也是使用ffmpeg工具进行合成,命令为:

ffmpeg -threads 2 -start_number 000001 -r 24 -i 路径名/%06d.jpeg -i temp.mp3 -vcodec mpeg4 生成的文件名
    merge_ascii_video_cmd = 'ffmpeg -threads 2 -start_number 000001 -r 24 -i {0}/%06d.jpeg -i temp.mp3 -vcodec mpeg4 {1}'.format('temp_ascii', dst_name)
    os.system(merge_ascii_video_cmd)

这一步完成后,字符视频已经生成了。最后还需删除一些临时的文件及文件夹。

完整代码展示

from PIL import Image, ImageDraw, ImageFont
import os, sys
import shutil

symbols = list("$@B%8&WM#*oahkbdpqwmZO0QLCJUYXzcvunxrjft/|()1{}[]?-_+~<>i!lI;:,"^`'. ")

def ascii_art_convert(src_dir, dest_dir):
    print('开始生成...')
    picts_list = sorted(os.listdir(src_dir))
    len_picts = len(picts_list)

    i = 0

    for picture in picts_list:
        (pixels, x_size, y_size) = load_picture(os.path.join(src_dir, picture))

        #生成字符画图片
        create_ascii_picture(pixels, symbols, os.path.join(dest_dir, picture), x_size, y_size)

        print('正在生成中... {0}/{1}'.format(i, len_picts))
        i += 1

def create_thumbnail(src_dir, dst_dir):
    picts_list = sorted(os.listdir(src_dir))

    for picture in picts_list:
        base_name = os.path.basename(picture)
        img = Image.open(os.path.join(src_dir, picture))
        size = 200, 200
        img.thumbnail(size, Image.ANTIALIAS)
        img.save(os.path.join(dst_dir, base_name))


def load_picture(filename):

    # Gray = R*0.299 + G*0.587 + B*0.114
    img = Image.open(filename).convert('L')
    (x, y) = img.size

    pixels = data())
    img.close()
    return (pixels, x, y)


def create_ascii_picture(pixels, symbols, dest_name, x_size, y_size):
    scale = 4    # 长宽扩大倍数
    border = 1  # 边框宽度

    interval_pixel = 2     #原图片间隔多少个像素点来填充

    img = w('L',
                    (x_size*scale + 2*border,
                     y_size*scale + 2*border),
                    255)
    fnt = uetype(&#f', int(scale*3))
    t = ImageDraw.Draw(img)

    x = border
    y = border
    for j in range(0, y_size, interval_pixel):
        for i in range(0, x_size, interval_pixel):
            t.text( (x, y),
                    symbols[int(pixels[j*x_size + i]/256 * len(symbols))],
                    font=fnt,
                    fill=0
                    )
            x += scale * interval_pixel
        x = border
        y += scale * interval_pixel

    img.save(dest_name, "JPEG")


def start_convert(src_file):

    if not ists('temp_pic'):
        os.mkdir('temp_pic')

    if not ists('temp_thum'):
        os.mkdir('temp_thum')

    if not ists('temp_ascii'):
        os.mkdir('temp_ascii')


    #分离音频
    slice_audio_cmd = &# -i {0} -vn temp.mp3'.format(src_file)
    os.system(slice_audio_cmd)


    #切割成图片
    slice_pic_cmd = &# -i {0} -r 24 temp_pic/%06d.jpeg'.format(src_file)
    os.system(slice_pic_cmd)

    #生成缩略图
    create_thumbnail('temp_pic', 'temp_thum')

    #生成字符画
    ascii_art_convert('temp_thum', 'temp_ascii')


    #合成字符视频
    dst_name = os.path.join(os.path.dirname(src_file), 'ascii_' + os.path.basename(src_file))
    merge_ascii_video_cmd = 'ffmpeg -threads 2 -start_number 000001 -r 24 -i {0}/%06d.jpeg -i temp.mp3 -vcodec mpeg4 {1}'.format('temp_ascii', dst_name)
    os.system(merge_ascii_video_cmd)

    print('生成完成!')


    if ists('temp_pic'):
        ('temp_pic')

    if ists('temp_thum'):
        ('temp_thum')

    if ists('temp_ascii'):
        ('temp_ascii')

    if ists('temp.mp3'):
        os.remove('temp.mp3')


if __name__ == '__main__':

    src_file = sys.argv[1]
    start_convert(src_file)


点击这里参与Python编程学习

本文作者

zarten,互联网一线工作者。

地址:zhihu/people/zarten


投稿邮箱:pythonpost@163

欢迎点击申请Python中文社区新专栏作者计划


Python中文社区作为一个去中心化的全球技术社区,以成为全球20万Python中文开发者的精神部落为愿景,目前覆盖各大主流媒体和协作平台,与阿里、腾讯、百度、微软、亚马逊、开源中国、CSDN等业界知名公司和技术社区建立了广泛的联系,拥有来自十多个国家和地区数万名登记会员,会员来自以公安部、工信部、清华大学、北京大学、北京邮电大学、中国人民银行、中科院、中金、华为、BAT、谷歌、微软等为代表的政府机关、科研单位、金融机构以及海内外知名公司,全平台近20万开发者关注。

▼ 点击下方阅读原文免费成为社区会员

本文发布于:2024-02-01 03:07:49,感谢您对本站的认可!

本文链接:https://www.4u4v.net/it/170672807133432.html

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。

标签:转换为   音视频   字符   视频   Python
留言与评论(共有 0 条评论)
   
验证码:

Copyright ©2019-2022 Comsenz Inc.Powered by ©

网站地图1 网站地图2 网站地图3 网站地图4 网站地图5 网站地图6 网站地图7 网站地图8 网站地图9 网站地图10 网站地图11 网站地图12 网站地图13 网站地图14 网站地图15 网站地图16 网站地图17 网站地图18 网站地图19 网站地图20 网站地图21 网站地图22/a> 网站地图23