影片中加入文字
这篇文章会介绍使用 Python 的 moviepy 第三方函数库读取影片,搭配 Pillow 函数库在影片中加入中文与英文字,最后还会将加入文字的影片转换成 gif 动画,做出有趣的梗图效果 ( 因为 moviepy 内建方法 TextClip 还要额外安装 ImageMagick,所以使用 Pillow 加入文字 )。
快速导览:
本篇使用的 Python 版本为 3.7.12,所有范例可使用 Google Colab 实作,不用安装任何软件 ( 参考:使用 Google Colab )
安装 moviepy 和 Pillow
输入下列指令安装 moviepy,根据个人环境使用 pip 或 pip3。
!pip install moviepy
输入下列指令安装 Pillow,根据个人环境使用 pip 或 pip3,如果使用 Colab 或 Anaconda Jupyter,已经内建 Pillow 函数库。
!pip install Pillow
由于影片转档会使用 ffmpeg,因此也要安装 ffmpeg ( 影片存档常见错误“TypeError: must be real number, not NoneType”往往都是 ffmpeg 没有安装导致 ),根据个人环境使用 pip 或 pip3,Anaconda Jupyter 可以使用 conda install。
!pip install ffmpeg
使用 Pillow 产生文字字卡
加载 PIL 的 Image、ImageFont 和 ImageDraw 模组,按照下列步骤建立背景透明的文字字卡:
- 使用 Image.new 建立色彩模式为 RGBA,尺寸 360x180 的空白图片。
- 使用 ImageFont.truetype 设定文字的字型和尺寸 ( 字型使用 Google Font 的 NotoSansTC-Regular )。
- 使用 ImageDraw.Draw 建立绘图对象。
- 使用 text 方法在图片中写入文字 ( 参数说明:ImageDraw.text )。
import os
os.chdir('/content/drive/MyDrive/Colab Notebooks') # 使用 Colab 要換路徑使用
from PIL import Image, ImageFont, ImageDraw
img = Image.new('RGBA', (360, 180)) # 建立色彩模式為 RGBA,尺寸 360x180 的空白圖片
font = ImageFont.truetype('NotoSansTC-Regular.otf', 40) # 設定字型與尺寸
draw = ImageDraw.Draw(img) # 準備在圖片上繪圖
# 將文字畫入圖片
draw.text((10,120),'OXXO.STUDIO',fill=(255,255,255),font=font,stroke_width=2,stroke_fill='red')
draw.text(xy=(50,0), text='大家好\n哈哈', align='center', fill=(255,255,255), font=font, stroke_width=2, stroke_fill='blue')
img.save('ok.png') # 儲存為 png
合成影片与文字
使用 moviepy 读取影片后,按照下列步骤将文字加入影片中:
- 使用 resize 将影片尺寸调整为字卡的大小 ( 也可以在产生字卡图片时,做成和影片同样大小,就不需这个步骤 )。
- 使用 subclip 剪辑出两秒的长度 ( 看个人需求,范例使用两秒 )。
- 使用 ImageClip 和 set_duration 将静态图片建立为长度两秒的影片对象 ( transparent=True 设定背景透明 )。
- 使用 CompositeVideoClip 将两段影片混合。
import os
os.chdir('/content/drive/MyDrive/Colab Notebooks') # 使用 Colab 要換路徑使用
from moviepy.editor import *
from PIL import Image, ImageFont, ImageDraw
img = Image.new('RGBA', (360, 180))
font = ImageFont.truetype('NotoSansTC-Regular.otf', 40)
draw = ImageDraw.Draw(img)
draw.text((10,120), 'OXXO.STUDIO', fill=(255,255,255), font=font, stroke_width=2, stroke_fill='red')
draw.text(xy=(50,0), text='大家好\n哈哈', align='center', fill=(255,255,255), font=font, stroke_width=2, stroke_fill='blue')
img.save('ok.png')
video = VideoFileClip("baby_shark.mp4") # 讀取影片
clip = video.resize((360,180)).subclip(10,12) # 縮小影片尺寸,剪輯出 10~12 秒的片段
text_clip = ImageClip("ok.png", transparent=True).set_duration(2) # 讀取圖片,將圖片變成長度兩秒的影片
output = CompositeVideoClip([clip, text_clip]) # 混合影片
output.write_videofile("output.mp4",temp_audiofile="temp-audio.m4a", remove_temp=True, codec="libx264", audio_codec="aac")
print('ok')
影片中加入文字,转换成 gif 动画
了解影片加入文字的原理后,参考“影片转换为 git 动画”、“剪辑影片”文章,就能将一段影片分割成多段影片,分别加入对应的文字,制做出有趣的梗图 gif 动画 ( 详细说明写在程序码内,影片来源:无间道梁朝伟超神演技 )。
import os
os.chdir('/content/drive/MyDrive/Colab Notebooks') # 使用 Colab 要換路徑使用
from moviepy.editor import *
from PIL import Image, ImageFont, ImageDraw
img_empty = Image.new('RGBA', (360, 180)) # 產生 RGBA 空圖片
font = ImageFont.truetype('NotoSansTC-Regular.otf', 24) # 設定文字字體和大小
video = VideoFileClip("oxxostudio.mp4").resize((360,180)) # 讀取影片,改變尺寸
output_list = [] # 記錄最後要組合的影片片段
# 建立文字字卡函式
def text_clip(xy, text, name):
img = img_empty.copy() # 複製空圖片
draw = ImageDraw.Draw(img) # 建立繪圖物件,並寫入文字
draw.text(xy, text, fill=(255,255,255), font=font, stroke_width=2, stroke_fill='black')
img.save(name) # 儲存
# 建立影片和文字合併的函式
def text_in_video(t, text_img):
clip = video.subclip(t[0],t[1]) # 剪輯影片到指定長度
text = ImageClip(text_img, transparent=True).set_duration(t[1]-t[0]) # 讀取字卡,調整為影片長度
combine_clip = CompositeVideoClip([clip, text]) # 合併影片和文字
output_list.append(combine_clip) # 添加到影片片段裡
# 文字串列,包含座標和內容
text_list = [
[(100,140),'你到底要怎樣?'],
[(90,140),'給我 CDPRO2 呀!'],
[(60,140),'但是 CDPRO2 過時啦!']
]
# 影片串列,包含要切取的時間片段
video_list = [
[13,16],
[21,24],
[38,41]
]
# 使用 for 迴圈,產生文字字卡
for i in range(len(text_list)):
text_clip(text_list[i][0], text_list[i][1], f'text_{i}.png')
# 使用 for 迴圈,合併字卡和影片
for i in range(len(video_list)):
text_in_video(video_list[i], f'text_{i}.png')
output = concatenate_videoclips(output_list) # 合併所有影片片段
output.write_gif("output.gif", fps=6, colors=32) # 轉換成 gif 動畫
print('ok')
微信扫码关注
抖音扫码关注