Writing
靜態歌詞也能先「跟上」:用進度把未知位置縮到三行
Product,Notes,Automation
Created by Ronnie Wong on 2026/7/22
靜態歌詞最令人挫折的時刻,不是它沒有文字,而是歌正在播,文字卻像一本沒有書籤的書。你看得到全部內容,卻不知道現在該看哪裡。
常見的直覺是:既然有麥克風,就做 ASR,把聽到的歌詞直接對上文字。但歌唱辨識比口述聽寫難得多,還帶著語言、音質、成本與隱私的問題。更重要的是,它把一個本來可以拆小的問題,一開始就當成「必須選出唯一正解」。
這次在 LyricGlass 裡,我們先處理一個更務實的版本:已知歌曲總長度、目前播放位置,以及一份可能不完整的靜態歌詞時,能不能先把畫面帶到大致正確的三行?這不是產生同步 LRC,也不是用來控制播放;它是讓單一裝置上的歌詞顯示,在沒有時間戳時仍然有可用的視覺定位。
先承認:靜態歌詞本身沒有時間
只有純文字,無法直接推導「第 78 秒正在唱哪一行」。缺少的不是演算法技巧,而是時間證據。
不過,歌曲進度本身是一條很弱、卻真實存在的訊號。假設歌曲播到 40%,把這個比例投射到正規化後的歌詞文字長度,就能取得一個大致中心點;再從中心點取回一段足夠寬的文字窗口。這是一個粗估,不是假裝知道每一行的時間戳。
我把窗口寬度寫成一個常數 c:
窗口長度 = ceil(c × 正規化後歌詞總長度)c 越大,命中機率越高,但候選範圍也越寬;若 c = 1,答案永遠是整份歌詞,當然不會錯,也完全沒有價值。因此真正的問題不是「怎樣拿滿分」,而是「最小而仍可靠的窗口要多大」。
把漂亮的假設,改成可被推翻的研究
第一版只有五首樣本,c = 0.465 剛好能讓所有可評估的歌詞行落進窗口。這個數字看起來精準,卻沒有資格成為產品答案:同一批歌既拿來選常數,又拿來評分,本質上是在對樣本校準。
所以實驗擴展到 30 首不同結構的 LRCLIB 記錄:9 種語言、30 個研究分層、共 1,401 個歌詞 occurrence。樣本只保存研究所需的 metadata;歌詞正文不寫進研究產物。同步歌詞只作為隱藏答案,靜態 plainLyrics 才是演算法真正可見的輸入。
這裡另一個容易被忽略的規則是:不能假設靜態歌詞完整。缺少一段主歌、重複句被省略、拆行或合行,都是真實資料條件,而不是可以悄悄排除的髒資料。因此評估把無法對齊的 occurrence 直接算作 miss,另外報告可對齊覆蓋率;不讓「只挑容易對齊的行」把命中率美化掉。
30 首樣本的曲線讓原本的數字失效了:追求同批樣本的最小滿分窗口,需要 c = 0.4831;但 c = 0.4 已命中 1,373 / 1,401 個 occurrence,整體為 98.0%,而候選窗口比那個滿分值小約 17%。
為什麼最後選 0.4,而不是 0.4831
0.4831 是一個很好的研究觀察:樣本一擴大,舊的五首校準值就不再成立。但它不是一個好的產品信念,因為它正是為這 30 首樣本的滿分邊界而長出來的數字。
0.4 反而比較誠實。它是一個容易理解、刻意保留餘裕的粗定位先驗:回傳約 40% 的歌詞,讓後續邏輯只在這個區域內工作。它不聲稱能選出唯一歌詞行,也不把範圍外的 2% 漏失藏起來。
真正重要的轉折是:產品不必把「唯一行」當成第一版的驗收條件。對歌詞顯示而言,把正確區域自動捲進可見範圍,使用者往往已經能立刻接回歌曲。這把問題從「替使用者做完判斷」,改成「先消除大部分搜尋成本」。
從研究數字,到真實畫面
Lab v0 只會在最終歌詞文件是 UNSYNCED、有 plainLyrics、且歌曲時長與播放位置都已知時啟用。它不根據 Apple Music、Musixmatch、Netease 或 LRCLIB 的來源身分改變算法;來源不是完整度的證據。
投射後,介面標示三個鄰近候選行,並把中間行自動捲到可視區中央。這個畫面刻意保留 NO LINE SELECTED:它告訴使用者「我們把範圍帶到這裡」,而不是偷偷把中間行包裝成已確定的同步結果。
兩個匿名的真機 UNSYNCED 樣本都落在預期的三行可見區域。這是很小、但足以支持 v0 產品目標的正向觀察;它不是 corpus 命中率的替代品,也不是單行精準度的證據。這個差別值得被保留,因為只有保留,後續研究才不會被一次漂亮 demo 帶偏。
元音分析不是前提,而是第二層
我們仍然研究語言中立的元音證據與八秒鐘的聲學窗口,但它的角色已經改變:不是用來拯救一個完全不知道位置的系統,而是只在 c = 0.4 返回的候選區間內,嘗試把三行再排序成一行。
這個分層大幅降低了難度,也讓失敗比較安全。若音訊證據不足、文字端編碼器尚未接上,或最佳候選和次佳候選沒有足夠差距,系統就停在「未選行」,不改寫歌詞時間、不生成假的 LRC、更不暗中切換到其他資料來源。
換句話說,粗定位本身已經有獨立產品價值;精細辨識只是讓它更好,而不是讓它第一次變得可用。
這次留下的幾條準則
- 先定義使用者真正需要的精度;可見的三行,未必比不存在的單行答案差。
- 不要把校準集上的滿分當成通用常數;選定常數後,仍需要歌曲級 holdout 驗證。
- 不完整歌詞不是例外條件,必須留在正式分母裡。
- 來源名稱不是資料品質證據;應根據最後拿到的文件狀態決定是否適用。
- 粗定位與精細辨識要分層驗證,並分開報告各自的可靠度。
- 在信心不足時保留不確定,比輸出一條看似同步的錯誤歌詞更誠實。
我喜歡這個案例,因為它沒有從「模型能不能做最難的事」開始,而是從「今天能不能讓使用者少找一頁歌詞」開始。把未知位置從整份文字壓到三行,聽起來不像人工智慧的壯舉;但對正在播放的歌而言,那已經是一種很具體的同步感。