File size: 4,813 Bytes
593b9ab
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
from moviepy.editor import *
from gtts import gTTS
from pydub import AudioSegment
import tempfile
import os

os.environ["IMAGEIO_FFMPEG_EXE"] = "/usr/local/bin/ffmpeg"
# 如果需要,设置 ImageMagick 的路径
# os.environ["IMAGEMAGICK_BINARY"] = "/usr/local/bin/convert"

def gen_audio(subtitles):
# 字幕列表,表示在指定时间段显示对应的字幕
# subtitles = [
#    [[0, 3], "這裡請注意右臂"],
#     [[4, 8], "這裡請注意左臂"],
#     [[9, 12], "這裡請注意左手細節"]
# ]
    subtitles = merge_subtitles(subtitles)
    print("===> Subtitles:")
    for subtitle in subtitles:
        print(subtitle)
    combined_clip = VideoFileClip("tmp/output.mp4")
    # 获取视频总时长
    total_duration = combined_clip.duration

    # 添加字幕的函数
    def add_subtitles(clip, subtitles):
        txt_clips = []
        for start_end, text in subtitles:
            start_time, end_time = start_end
            duration = end_time - start_time
            txt_clip = (TextClip(text, fontsize=clip.w//20, color='white', font='bold.ttf', method='caption', size=(clip.w * 0.9, None))  # 添加 method='caption'
                        .set_duration(duration)  # 设置字幕持续时间
                        .set_position(('center', 4 * clip.h // 5))
                        .set_start(start_time))  # 字幕开始时间
            txt_clips.append(txt_clip)
        
        # 将字幕叠加到视频上
        return CompositeVideoClip([clip, *txt_clips])

    # 将字幕添加到视频中
    video_with_subtitles = add_subtitles(combined_clip, subtitles)

    # 生成语音文件并返回音频剪辑的函数
    def generate_audio(subtitles, total_duration):
        temp_audio_path = tempfile.mkdtemp()  # 创建临时目录存储音频文件
        clips = []

        for i, (start_end, text) in enumerate(subtitles):
            start_time, end_time = start_end
            duration = end_time - start_time

            # 使用 gtts 生成语音
            tts = gTTS(text=text, lang='zh')
            audio_path = os.path.join(temp_audio_path, f'subtitle_{i}.mp3')
            tts.save(audio_path)
            
            # 使用 pydub 加载音频并将其转换为 wav 格式
            audio_segment = AudioSegment.from_mp3(audio_path)

            # 将 pydub 音频转换为 moviepy 可用的 AudioFileClip
            new_audio_path = os.path.join(temp_audio_path, f'subtitle_{i}_adjusted.wav')
            audio_segment.export(new_audio_path, format="wav")

            audio_clip = AudioFileClip(new_audio_path).set_start(start_time).set_duration(min(duration, audio_segment.duration_seconds))
            
            clips.append(audio_clip)
        
        # 合并所有音频剪辑
        final_audio = CompositeAudioClip(clips)
        return final_audio

    # 生成语音
    audio_clip = generate_audio(subtitles, total_duration)

    # 将语音添加到视频
    video_with_audio = video_with_subtitles.set_audio(audio_clip)

    # 导出带语音和字幕的视频
    video_with_audio.write_videofile('tmp/output_with_subtitles.mp4', fps=24)
    return 'tmp/output_with_subtitles.mp4'


def merge_subtitles(subtitles):
    merged_subtitles = []
    i = 0
    n = len(subtitles)
    
    while i < n:
        # 初始化当前字幕的起始时间、结束时间和内容
        current_start, current_end = subtitles[i][0]
        current_content = subtitles[i][1]
        duration = current_end - current_start
        i += 1  # 移动到下一个字幕索引,供后续合并使用

        # 尝试合并后续字幕,直到持续时间至少为3秒
        while duration < 3:
            if i >= n:
                # 已经处理完所有字幕,延长结束时间
                current_end = current_start + 3
                duration = current_end - current_start
                break
            next_start, next_end = subtitles[i][0]
            next_content = subtitles[i][1]
            if next_start == current_end:
                # 与下一个字幕相邻,合并
                current_end = next_end
                current_content += "、" + next_content
                duration = current_end - current_start
                i += 1  # 继续检查下一个字幕
            else:
                # 不相邻,无法合并,延长结束时间
                if duration < 3:
                    current_end = current_start + 3
                    duration = current_end - current_start
                break  # 退出合并循环

        # 添加合并后的字幕到新列表
        current_content = '這裡請注意' + '、'.join(list(set(current_content.split('、'))))
        merged_subtitles.append([[current_start, current_end], current_content])
    
    return merged_subtitles