deeme commited on
Commit
cb9e1cc
·
verified ·
1 Parent(s): 6a725e3

Upload app.py

Browse files
Files changed (1) hide show
  1. app.py +49 -34
app.py CHANGED
@@ -104,26 +104,50 @@ def get_audio_duration(audio_path):
104
  logger.error(f"Error getting audio duration: {e}")
105
  return 5.0 # 默认5秒
106
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
107
  # 创建caption字幕文件(底部显示)
108
  def create_caption_subtitle_file(project_dir, captions, panel_start_times, panel_durations):
109
  try:
110
- subtitle_file = os.path.join(project_dir, "captions.ass")
111
-
112
  with open(subtitle_file, "w", encoding="utf-8") as f:
113
- subtitle_index = 1
114
-
115
- # 处理每个面板的旁白字幕
116
- for i, caption in enumerate(captions):
117
- # 获取当前面板的开始时间和持续时间
118
- start_time = panel_start_times[i]
119
- duration = panel_durations[i]
120
- end_time = start_time + duration
121
-
122
- # 字幕显示整个面板的时长
123
- f.write(f"{subtitle_index}\n")
124
- f.write(f"{format_time(start_time)} --> {format_time(end_time)}\n")
125
- f.write(f"{caption}\n\n")
126
- subtitle_index += 1
127
 
128
  return subtitle_file
129
  except Exception as e:
@@ -133,23 +157,14 @@ def create_caption_subtitle_file(project_dir, captions, panel_start_times, panel
133
  # 创建speech字幕文件(顶部显示)
134
  def create_speech_subtitle_file(project_dir, speeches, panel_start_times, panel_durations):
135
  try:
136
- subtitle_file = os.path.join(project_dir, "speeches.ass")
137
-
138
  with open(subtitle_file, "w", encoding="utf-8") as f:
139
- subtitle_index = 1
140
-
141
- # 处理每个面板的对话字幕
142
- for i, speech in enumerate(speeches):
143
- # 获取当前面板的开始时间和持续时间
144
- start_time = panel_start_times[i]
145
- duration = panel_durations[i]
146
- end_time = start_time + duration
147
-
148
- # 字幕显示整个面板的时长
149
- f.write(f"{subtitle_index}\n")
150
- f.write(f"{format_time(start_time)} --> {format_time(end_time)}\n")
151
- f.write(f"{speech}\n\n")
152
- subtitle_index += 1
153
 
154
  return subtitle_file
155
  except Exception as e:
@@ -317,7 +332,7 @@ def create_video(project_dir, image_paths, caption_subtitle_file, speech_subtitl
317
  combined_filter = (
318
  f"subtitles={process_sub_path(caption_subtitle_file)}:"
319
  "force_style='"
320
- "FontName=Noto Sans CJK SC,"
321
  "Fontsize={},"
322
  "Alignment=2,"
323
  "MarginV={},"
@@ -327,7 +342,7 @@ def create_video(project_dir, image_paths, caption_subtitle_file, speech_subtitl
327
  ),
328
  f"subtitles={process_sub_path(speech_subtitle_file)}:"
329
  "force_style='"
330
- "FontName=Noto Sans CJK SC,"
331
  "Fontsize={},"
332
  "Alignment=8,"
333
  "MarginV={},"
 
104
  logger.error(f"Error getting audio duration: {e}")
105
  return 5.0 # 默认5秒
106
 
107
+ # 在生成ASS文件时添加完整样式头
108
+ ASS_STYLE_HEADER = """[Script Info]
109
+ WrapStyle: 0
110
+ ScaledBorderAndShadow: yes
111
+ PlayResX: 1920
112
+ PlayResY: 1080
113
+ [V4+ Styles]
114
+ Format: Name, Fontname, Fontsize, PrimaryColour, SecondaryColour, OutlineColour, BackColour, Bold, Italic, Underline, StrikeOut, ScaleX, ScaleY, Spacing, Angle, BorderStyle, Outline, Shadow, Alignment, MarginL, MarginR, MarginV, Encoding
115
+ Style: Caption,Noto Sans CJK SC,54,&H00FFFFFF,&H000000FF,&H00333333,&H00000000,0,0,0,0,100,100,0,0,1,2,3,2,100,100,50,0
116
+ Style: Speech,Noto Sans CJK SC,48,&H00FFFFFF,&H000000FF,&H00333333,&H00000000,0,0,0,0,100,100,0,0,1,2,3,8,100,100,50,0
117
+ [Events]
118
+ Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text
119
+ """
120
+ def smart_wrap(text, video_width=1920):
121
+ """智能换行算法"""
122
+ max_chars = int(video_width // 38) # 基于典型字体尺寸计算
123
+ lines = []
124
+ current_line = []
125
+ current_len = 0
126
+
127
+ for char in text:
128
+ char_len = 2 if ord(char) > 255 else 1 # 全角字符计为2单位
129
+ if current_len + char_len > max_chars * 2:
130
+ lines.append(''.join(current_line))
131
+ current_line = [char]
132
+ current_len = char_len
133
+ else:
134
+ current_line.append(char)
135
+ current_len += char_len
136
+ lines.append(''.join(current_line))
137
+
138
+ return r'\N'.join(lines)
139
+
140
  # 创建caption字幕文件(底部显示)
141
  def create_caption_subtitle_file(project_dir, captions, panel_start_times, panel_durations):
142
  try:
 
 
143
  with open(subtitle_file, "w", encoding="utf-8") as f:
144
+ f.write(ASS_STYLE_HEADER)
145
+ for i, (caption, start, duration) in enumerate(zip(captions, panel_start_times, panel_durations)):
146
+ wrapped_text = smart_wrap(caption)
147
+ f.write(
148
+ f"Dialogue: 0,{format_time(start)},{format_time(start + duration)},"
149
+ f"Caption,,0,0,0,,{wrapped_text}\n"
150
+ )
 
 
 
 
 
 
 
151
 
152
  return subtitle_file
153
  except Exception as e:
 
157
  # 创建speech字幕文件(顶部显示)
158
  def create_speech_subtitle_file(project_dir, speeches, panel_start_times, panel_durations):
159
  try:
 
 
160
  with open(subtitle_file, "w", encoding="utf-8") as f:
161
+ f.write(ASS_STYLE_HEADER)
162
+ for i, (speech, start, duration) in enumerate(zip(speeches, panel_start_times, panel_durations)):
163
+ wrapped_text = smart_wrap(speech)
164
+ f.write(
165
+ f"Dialogue: 0,{format_time(start)},{format_time(start + duration)},"
166
+ f"Speech,,0,0,0,,{wrapped_text}\n"
167
+ )
 
 
 
 
 
 
 
168
 
169
  return subtitle_file
170
  except Exception as e:
 
332
  combined_filter = (
333
  f"subtitles={process_sub_path(caption_subtitle_file)}:"
334
  "force_style='"
335
+ #"FontName=Noto Sans CJK SC,"
336
  "Fontsize={},"
337
  "Alignment=2,"
338
  "MarginV={},"
 
342
  ),
343
  f"subtitles={process_sub_path(speech_subtitle_file)}:"
344
  "force_style='"
345
+ #"FontName=Noto Sans CJK SC,"
346
  "Fontsize={},"
347
  "Alignment=8,"
348
  "MarginV={},"