使用python为视频添加字幕

问题描述 投票:0回答:2

我有一段人们说话的视频。我还有一份成绩单。我将单词分成句子,这样我就可以在屏幕上一次显示一个句子,就像电影中的普通字幕一样。为此,我创建了一个 csv,其中每个帧都有一行,并且每行都包含该句子时间块内的完整句子。这样,我循环遍历所有帧,并将该句子的文本放在该句子内的每个帧上。我在 OpenCV 中做的。

样本成绩单 csv:

frame     sentence
0           hello
1           hello
2           how are you
3           how are you
4           how are you
5           how are you
6           how are you
7           how are you 
8           fine
...

csv的长度与视频中的帧数相同。要绘制字幕,我这样做:

import cv2
import pandas as pd

df = pd.read_csv('data.csv')
video = cv2.VideoCapture('vid.mp4')
num_frames = video.get(cv2.CAP_PROP_FRAME_COUNT)

assert len(df) == num_frames

for i in list(range(0, num_frames)):
    ret, frame = video.read()
    cv2.putText(frame, str(df.sentence), (0,50),cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 3, cv2.LINE_AA, True)

    # additional standard cv2 code below...

这可行,但现在我没有任何音频。我知道 OpenCV 不适用于任何音频,但是还有其他解决方法吗?这种方法在我的管道中效果很好,因此我希望能够将这些帧写入新视频,但保留音频,同时使用尽可能少的附加库。

编辑

使用建议的 moviepy 解决方案后,我得到一个没有音频的带字幕视频,并出现以下错误:

Moviepy - Building video vidout.mp4.
MoviePy - Writing audio in vidoutTEMP_MPY_wvf_snd.mp3
MoviePy - Done.                                                                                      
Moviepy - Writing video vidout.mp4

t: 100%|████████████████████████████████████████████▉| 23069/23084 [07:26<00:00, 66.35it/s, now=None]Traceback (most recent call last):
  File "/Users/asi/anaconda3/lib/python3.7/site-packages/moviepy/Clip.py", line 472, in iter_frames
    frame = self.get_frame(t)
  File "<decorator-gen-11>", line 2, in get_frame
  File "/Users/asi/anaconda3/lib/python3.7/site-packages/moviepy/decorators.py", line 89, in wrapper
    return f(*new_a, **new_kw)
  File "/Users/asi/anaconda3/lib/python3.7/site-packages/moviepy/Clip.py", line 93, in get_frame
    return self.make_frame(t)
  File "/Users/asi/anaconda3/lib/python3.7/site-packages/moviepy/Clip.py", line 136, in <lambda>
    newclip = self.set_make_frame(lambda t: fun(self.get_frame, t))
  File "/Users/asi/anaconda3/lib/python3.7/site-packages/moviepy/video/VideoClip.py", line 490, in <lambda>
    return self.fl(lambda gf, t: image_func(gf(t)), apply_to)
  File "make_demo.py", line 65, in pipeline
    cv2.putText(frame, str(next(dfi)[1].word), (0, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 3, cv2.LINE_AA, True)
StopIteration

The above exception was the direct cause of the following exception:

Traceback (most recent call last):
  File "make_demo.py", line 72, in <module>
    out_video.write_videofile("vidout.mp4", audio=True)
  File "<decorator-gen-55>", line 2, in write_videofile
  File "/Users/asi/anaconda3/lib/python3.7/site-packages/moviepy/decorators.py", line 54, in requires_duration
    return f(clip, *a, **k)
  File "<decorator-gen-54>", line 2, in write_videofile
  File "/Users/asi/anaconda3/lib/python3.7/site-packages/moviepy/decorators.py", line 135, in use_clip_fps_by_default
    return f(clip, *new_a, **new_kw)
  File "<decorator-gen-53>", line 2, in write_videofile
  File "/Users/asi/anaconda3/lib/python3.7/site-packages/moviepy/decorators.py", line 22, in convert_masks_to_RGB
    return f(clip, *a, **k)
  File "/Users/asi/anaconda3/lib/python3.7/site-packages/moviepy/video/VideoClip.py", line 307, in write_videofile
    logger=logger)
  File "/Users/asi/anaconda3/lib/python3.7/site-packages/moviepy/video/io/ffmpeg_writer.py", line 221, in ffmpeg_write_video
    fps=fps, dtype="uint8"):
RuntimeError: generator raised StopIteration

python video video-processing opencv
2个回答
5
投票

如果可以添加一个额外的库,您可以使用具有音频支持的

moviepy

import cv2
import pandas as pd
from moviepy.editor import VideoFileClip

def pipeline(frame):
    try:
        cv2.putText(frame, str(next(dfi)[1].sentence), (0, 50), cv2.FONT_HERSHEY_SIMPLEX, 1, (0, 0, 0), 3, cv2.LINE_AA, True)
    except StopIteration:
        pass
    # additional frame manipulation
    return frame

dfi = pd.read_csv('data.csv').iterrows()
video = VideoFileClip("vid.mp4")
out_video = video.fl_image(pipeline)
out_video.write_videofile("vidout.mp4", audio=True)

0
投票

我这里有一个替代方案,在新行中使用字幕文本 subtitles.txt 文件代替。在此示例中,替换 “/path/to/input_folder” 为包含您的文件夹的路径 video.mp4 和 subtitle.txt 文件。同样,替换 “/path/to/output_folder”为输出视频所需的路径。 该脚本将创建一个带有指定字幕的新视频 输出文件夹。

from moviepy.editor import VideoFileClip, TextClip, CompositeVideoClip

def create_video(input_folder, output_folder):
    # Load the video clip
    video_path = os.path.join(input_folder, "video.mp4")
    video_clip = VideoFileClip(video_path)

    # Load subtitles from the subtitles.txt file
    subtitles_path = os.path.join(input_folder, "subtitles.txt")
    with open(subtitles_path, "r", encoding="utf-8") as subtitles_file:
        subtitles_lines = subtitles_file.readlines()

    # Create TextClip for each subtitle
    subtitle_clips = []
    for i, line in enumerate(subtitles_lines):
        caption_clip = TextClip(line.strip(), fontsize=24, color="yellow", bg_color="transparent")
        caption_clip = caption_clip.set_pos(("center", "bottom"))
        caption_clip = caption_clip.set_duration(video_clip.duration / len(subtitles_lines))
        caption_clip = caption_clip.set_start(i * (video_clip.duration / len(subtitles_lines)))
        subtitle_clips.append(caption_clip)

    # Combine all caption clips into a single CompositeVideoClip
    subtitles = CompositeVideoClip(subtitle_clips)

    # Overlay subtitles at the bottom of the video
    final_clip = CompositeVideoClip([video_clip, subtitles.set_pos(("center", "bottom"))])

    # Write the final video
    output_path = os.path.join(output_folder, "output_video.mp4")
    final_clip.write_videofile(output_path, codec="libx264", audio_codec="aac", fps=24)

# Example usage:
input_folder = "/path/to/input_folder"
output_folder = "/path/to/output_folder"
create_video(input_folder, output_folder)
© www.soinside.com 2019 - 2024. All rights reserved.