update
This commit is contained in:
@ -3,7 +3,7 @@ from utils.helpers import get_media_duration,get_media_info
|
||||
from pathlib import Path
|
||||
from typing import List, Dict, Optional
|
||||
import streamlit as st # 為了存取 secrets
|
||||
from scripts import step1_notion_sync, step2_translate_ipa
|
||||
# from scripts_ import step1_notion_sync, step2_translate_ipa
|
||||
import json
|
||||
from notion_client import Client
|
||||
from google.cloud import translate_v2 as translate
|
||||
@ -567,7 +567,7 @@ class Project:
|
||||
# 3. 初始化一個空的 AudioSegment 作為拼接的基礎
|
||||
# 這是比「拿第一個檔案當基礎」更穩健的做法
|
||||
combined_audio = AudioSegment.empty()
|
||||
|
||||
|
||||
# 4. 遍歷所有音訊檔並依次拼接
|
||||
for wav_file in wav_files:
|
||||
# 讀取單個 .wav 檔案
|
||||
@ -625,6 +625,7 @@ class Project:
|
||||
|
||||
try:
|
||||
# 從 self.data 讀取各語言的文本行
|
||||
title_line = self.data.get("title", "")
|
||||
en_lines = [line.strip() for line in self.data.get("en", "").split('\n') if line.strip()]
|
||||
zh_lines = [line.strip() for line in self.data.get("zh", "").split('\n') if line.strip()]
|
||||
ipa_lines = [line.strip() for line in self.data.get("ipa", "").split('\n') if line.strip()]
|
||||
@ -655,10 +656,11 @@ class Project:
|
||||
subs.info["Title"] = self.name
|
||||
|
||||
# 6. 定義所有需要的樣式 (從您的腳本中精確複製)[1]
|
||||
subs.styles["EN"] = pysubs2.SSAStyle(fontname="Noto Sans", fontsize=140, primarycolor=pysubs2.Color(255, 248, 231), outlinecolor=pysubs2.Color(255, 248, 231), outline=2, alignment=pysubs2.Alignment.TOP_CENTER, marginv=280)
|
||||
subs.styles["IPA"] = pysubs2.SSAStyle(fontname="Noto Sans", fontsize=110, primarycolor=pysubs2.Color(255, 140, 0), outlinecolor=pysubs2.Color(255, 140, 0), outline=1, alignment=pysubs2.Alignment.TOP_CENTER, marginv=340)
|
||||
subs.styles["ZH"] = pysubs2.SSAStyle(fontname="Noto Sans TC", fontsize=140, primarycolor=pysubs2.Color(102, 128, 153), outlinecolor=pysubs2.Color(102, 128, 153), outline=1, alignment=pysubs2.Alignment.TOP_CENTER, marginv=440)
|
||||
subs.styles["NUMBER"] = pysubs2.SSAStyle(fontname="Segoe UI Symbol", fontsize=120, primarycolor=pysubs2.Color(144, 144, 144), outlinecolor=pysubs2.Color(144, 144, 144), bold=True, outline=1, borderstyle=1,alignment=pysubs2.Alignment.TOP_RIGHT, marginl=0, marginr=260, marginv=160)
|
||||
subs.styles["TITLE"] = pysubs2.SSAStyle(fontname="源泉圓體丹 R", fontsize=80, primarycolor=pysubs2.Color(230, 221, 196), outlinecolor=pysubs2.Color(230, 221, 196), outline=0, borderstyle=2, alignment=pysubs2.Alignment.TOP_CENTER, marginl=0, marginr=0, marginv=200)
|
||||
subs.styles["EN"] = pysubs2.SSAStyle(fontname="Noto Sans", fontsize=140, primarycolor=pysubs2.Color(255, 248, 231), outlinecolor=pysubs2.Color(255, 248, 231), outline=2,borderstyle=2, alignment=pysubs2.Alignment.TOP_CENTER, marginv=400)
|
||||
subs.styles["IPA"] = pysubs2.SSAStyle(fontname="Noto Sans", fontsize=110, primarycolor=pysubs2.Color(255, 140, 0), outlinecolor=pysubs2.Color(255, 140, 0), outline=1, alignment=pysubs2.Alignment.TOP_CENTER, marginv=500)
|
||||
subs.styles["ZH"] = pysubs2.SSAStyle(fontname="Noto Sans TC", fontsize=140, primarycolor=pysubs2.Color(152, 188, 193), outlinecolor=pysubs2.Color(152, 188, 193), outline=1, alignment=pysubs2.Alignment.TOP_CENTER, marginv=600)
|
||||
subs.styles["NUMBER"] = pysubs2.SSAStyle(fontname="NaiKaiFont", fontsize=60, primarycolor=pysubs2.Color(164, 124, 104), outlinecolor=pysubs2.Color(164, 124, 104),outline=1, angle=-10, borderstyle=2,alignment=pysubs2.Alignment.TOP_RIGHT, marginl=0, marginr=260, marginv=160)
|
||||
|
||||
# 7. 遍歷音訊檔,生成四層字幕事件
|
||||
st.session_state.operation_status = {
|
||||
@ -673,10 +675,10 @@ class Project:
|
||||
end_time = current_time_ms + duration_ms
|
||||
|
||||
# 為每一層字幕建立一個事件
|
||||
subs.append(pysubs2.SSAEvent(start=start_time, end=end_time, text=en_lines[i], style="EN"))
|
||||
subs.append(pysubs2.SSAEvent(start=start_time, end=end_time, text=f"[{ipa_lines[i]}]", style="IPA"))
|
||||
subs.append(pysubs2.SSAEvent(start=start_time, end=end_time, text=zh_lines[i], style="ZH"))
|
||||
subs.append(pysubs2.SSAEvent(start=start_time, end=end_time, text=i, style="NUMBER"))
|
||||
subs.append(pysubs2.SSAEvent(start=start_time, end=end_time, text=f"{{\\fad(300, 300)}}{en_lines[i]}" , style="EN"))
|
||||
subs.append(pysubs2.SSAEvent(start=start_time, end=end_time, text=f"{{\\fad(300, 300)}}/{ipa_lines[i]}/" , style="IPA"))
|
||||
subs.append(pysubs2.SSAEvent(start=start_time, end=end_time, text=f"{{\\fad(300, 300)}}{zh_lines[i]}" , style="ZH"))
|
||||
subs.append(pysubs2.SSAEvent(start=start_time, end=end_time, text=f"{{\\fad(300, 300)}}{str(i+1)}" , style="NUMBER"))
|
||||
|
||||
current_time_ms = end_time
|
||||
st.session_state.operation_status = {
|
||||
@ -684,6 +686,7 @@ class Project:
|
||||
"value": (i + 1) / total_files,
|
||||
"message": f"正在處理字幕... ({i+1}/{total_files})"
|
||||
}
|
||||
subs.insert(0, pysubs2.SSAEvent(start=0, end=end_time, text=title_line, style="TITLE"))
|
||||
# 8. 儲存 .ass 檔案
|
||||
subs.save(str(ass_path))
|
||||
st.session_state.operation_status = {
|
||||
@ -736,7 +739,7 @@ class Project:
|
||||
final_video_path = self.paths['final_video']
|
||||
bg_final_path = output_dir / "bg_final.mp4"
|
||||
transition_duration = 1.0
|
||||
print("111")
|
||||
|
||||
for file_path in [logo_video, open_video, end_video, audio_path, ass_path]:
|
||||
if not file_path or not file_path.exists():
|
||||
st.session_state.operation_status = {
|
||||
@ -744,7 +747,6 @@ class Project:
|
||||
"message": f"缺少必需的檔案: {e}"
|
||||
}
|
||||
return
|
||||
print("222")
|
||||
|
||||
base_videos = sorted([p for p in temp_video_dir.iterdir() if p.is_file() and p.suffix.lower() in ['.mp4', '.mov']])
|
||||
if not base_videos:
|
||||
@ -753,7 +755,6 @@ class Project:
|
||||
"message": f"資料夾中沒有影片可供合成。: {e}"
|
||||
}
|
||||
return
|
||||
print("333")
|
||||
|
||||
|
||||
p_loop_count, error_msg = self.calculate_loop_count(transition_duration=transition_duration)
|
||||
@ -761,7 +762,6 @@ class Project:
|
||||
# 如果計算出錯,拋出一個錯誤讓外層的 except 捕捉
|
||||
raise ValueError(f"計算循環次數時失敗: {error_msg}")
|
||||
|
||||
print("444")
|
||||
# --- 2. 一步式生成主要內容影片 (bg_final.mp4) ---
|
||||
if not bg_final_path.exists():
|
||||
print(f"⚙️ 準備一步式生成主要內容影片 (循環 {p_loop_count} 次)...")
|
||||
@ -899,10 +899,8 @@ class Project:
|
||||
video_paths = [p for p in video_folder.iterdir() if p.is_file() and p.suffix.lower() in ['.mp4', '.mov']]
|
||||
video_lengths = [get_media_duration(p) for p in video_paths]
|
||||
video_lengths = [l for l in video_lengths if l is not None and l > 0]
|
||||
print("ccc")
|
||||
if not video_lengths:
|
||||
return None, "在 `test` 資料夾中找不到有效的影片檔案。"
|
||||
print("ddd")
|
||||
n = len(video_lengths)
|
||||
m = sum(video_lengths)
|
||||
tr = transition_duration
|
||||
|
||||
Reference in New Issue
Block a user