歌詞逐字同步引擎
解決常見的歌詞影片問題:整行顯示的速度慢於歌手演唱,透過將每個單詞與其聲學起始點同步,讓視覺與聲音完美匹配。
flowchart TD
A[音頻檔案 MP3/WAV] --> B[聲學包絡分析 RMS]
B --> C[語音辨識 / 語音檢查點]
C --> D[單詞音節權重計算]
D --> E[次秒級單詞時間戳 JSON]
E --> F[漸進式單詞顯示 HTML/CSS]
問題與解決方案
- 問題:當歌手加速演唱(例如快速的 charanam 或斷句)時,靜態的整行顯示會停留在畫面上過久,或在歌手唱完後才出現。
- 解決方案:
- 每行歌詞被標記為獨立的單詞:
["Kanmani", "anbodu", "kaadhalan"]。 - 活躍的語音持續時間根據音節權重和局部 RMS 能量上升進行分配。
- 該行中的所有單詞同時渲染在佈局中,確保字型大小和換行不會跳動。
- 即將到來的單詞以淡色幽靈墨水(
opacity: 0.12)渲染。 - 當歌手唱出某個單詞時,該單詞轉變為深紅色(
opacity: 1,color: #8c1226)。
- 每行歌詞被標記為獨立的單詞:
時間戳提取腳本
import wave, numpy as np
def compute_word_timings(audio, words, t_start, t_end, sr=16000):
dur = t_end - t_start
active_dur = max(0.4, dur * 0.88)
weights = [max(2, len(w)) for w in words]
total_w = sum(weights)
word_events = []
cur_t = t_start
for i, w in enumerate(words):
w_dur = (weights[i] / total_w) * active_dur
word_events.append({
'word': w,
't_rel': round(cur_t, 3)
})
cur_t += w_dur
return word_events
CSS 漸進式單詞高亮
.native .word {
display: inline-block;
opacity: 0.12;
transition: opacity .12s ease-out;
padding: 0 .25cqw;
}
.native .word.revealed {
opacity: 1;
}