Pythonで動画に字幕を付ける方法! | Pythonで動画編集をする

2021年9月3日金曜日

Python 動画

今回の内容

今回はPythonで字幕をつけたいと思います。
動画編集編は、この記事に他にもあるので、ぜひ見に行ってください!

使うライブラリ

今回はffmpegを使わずにcv2やPillowをつかって編集します。
import sys
import numpy as np
import os
import ffmpeg
from PIL import ImageFont, ImageDraw, Image
from pydub import AudioSegment
import cv2
import subprocess

text = "SubTitle"
file_path = "input.mp4"
save_path = "output.mp4"
toTime = 2
fromTime = 10

#動画の情報を取得する
cap = cv2.VideoCapture(file_path)
fps = cap.get(cv2.CAP_PROP_FPS)
width = int(cap.get(cv2.CAP_PROP_FRAME_WIDTH))
height = int(cap.get(cv2.CAP_PROP_FRAME_HEIGHT))
fourcc = cv2.VideoWriter_fourcc('m', 'p', '4', 'v')
out = cv2.VideoWriter("tmp.mp4" ,fourcc, fps, (width, height))
i = 0

#一コマ一コマ取り出し、Pillowで画像として編集
while True:
    ret, frame = cap.read()
    if ret:
        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        pil_image = Image.fromarray(frame_rgb)
        draw = ImageDraw.Draw(pil_image)
        if i <= fromTime*fps and i >= toTime*fps:
            font = ImageFont.truetype('C:\\Windows\\Fonts\\HGRGE.TTC', 40)
            draw.text((50, 300), text, font=font)
        rgb_image = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
        out.write(rgb_image)
        i=i+1
        print(cap.get(cv2.CAP_PROP_FRAME_COUNT),"/",i)
    else:
        break

cap.release()
out.release()

#このままだと音声がないため、音声と合体する
subprocess.run("ffmpeg -i " + file_path + " audio.wav -c copy")
print("音声への変換完了")
s1 = ffmpeg.input("tmp.mp4")
s2 = ffmpeg.input("audio.wav")
s = ffmpeg.output(s1,s2,save_path, vcodec="copy", acodec="aac")
ffmpeg.run(s)
os.remove("audio.wav")
os.remove("tmp.mp4")
print("全て完了")

解説

#一コマ一コマ取り出し、Pillowで画像として編集
while True:
    ret, frame = cap.read()
    if ret:
        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        pil_image = Image.fromarray(frame_rgb)
        draw = ImageDraw.Draw(pil_image)
        if i <= fromTime*fps and i >= toTime*fps:
            font = ImageFont.truetype('C:\\Windows\\Fonts\\HGRGE.TTC', 40)
            draw.text((50, 300), text, font=font)
        rgb_image = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
        out.write(rgb_image)
        i=i+1
        print(cap.get(cv2.CAP_PROP_FRAME_COUNT),"/",i)
    else:
        break
一コマ一コマ分けるコードの中でも
        frame_rgb = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
        pil_image = Image.fromarray(frame_rgb)
        draw = ImageDraw.Draw(pil_image)
        if i <= fromTime*fps and i >= toTime*fps:
            font = ImageFont.truetype('C:\\Windows\\Fonts\\HGRGE.TTC', 40)
            draw.text((50, 300), text, font=font)
        rgb_image = cv2.cvtColor(np.array(pil_image), cv2.COLOR_RGB2BGR)
        out.write(rgb_image)
この部分です。最初にPillowの画像に変換し、そのあとにその画像を編集します。
draw.textでテキストを挿入できます。
やろうと思えば画像も描画できるので、今度別の記事で紹介したいと思います。
truetypeでフォントも指定できます。


そして、音声とかのコード
#このままだと音声がないため、音声と合体する
subprocess.run("ffmpeg -i " + file_path + " audio.wav -c copy")
print("音声への変換完了")
s1 = ffmpeg.input("tmp.mp4")
s2 = ffmpeg.input("audio.wav")
s = ffmpeg.output(s1,s2,save_path, vcodec="copy", acodec="aac")
ffmpeg.run(s)
os.remove("audio.wav")
os.remove("tmp.mp4")
の部分では最初に動画をwav形式に変換します。(subprocessでやらないとなぜかできない)
そしてから、音声と動画を合体させています。



とりあえずここまで。うまくいかなかったらコメントよろしく!

ページ

QooQ