本 repo 是以下 paper 的原作者實作:
"MPEcho: A Melody and Phoneme-Aware Generative Framework for Controllable Cover Song Generation" ISMIR 2026.
本套件主要貢獻者為:Hsuan-Yu Yeh
相關 weight 可以由 HF 下載,並放置於 ./ckpts 中
本專案全自動化地整合了聲源分離、歌詞轉寫、歌聲標註、MIDI 預測與字幕生成流程,完美適合以下需求:
- 研究人員/開發者:建立大規模、精細歌聲標註資料集,推動 SVS(歌聲合成)、音樂訊號處理等領域發展。
- 內容創作者:產生 ASS 格式字幕並製作動態卡拉OK,減少製作時間。
- 音樂愛好者/工程師:快速獲取一首歌的人聲、背景、MIDI、歌詞與分句等多種格式資料,一次滿足多重應用!
- 作業系統支援:目前僅在 Linux 環境下測試,其他作業系統(macOS、Windows)可能需要額外調整。
- 缺乏圖形化介面(GUI):本專案以工程導向為主,僅提供命令列介面,對一般使用者較不友善。
- 使用門檻較高:相關代碼較偏向工程實作,需具備一定的 Python 與終端機操作經驗。
- 功能整合性:目前部分模組依賴外部工具與第三方資源,執行流程需依照說明文件操作。
本專案主要支援中文與日文,提供下列核心功能:
-
聲源分離(Source Separation)
- 利用 Demucs 或 MelBandRoformer 進行人聲與背景音樂的分離。
- 可結合 UVR(Ultimate Vocal Remover)中的 Echo 與和聲去除模型,對分離出的人聲檔案進一步處理,提升純淨度。
-
歌詞轉寫(Lyrics Transcription)
- 採用 Whisper 或 Faster-Whisper,將音檔自動轉成對應歌詞,支援高準確率的語音辨識。
-
自動歌聲標註(Automatic Singing Voice Annotation)
⭐ 主要貢獻與特色功能:- Alignment(有歌詞):
在給定逐句或整首歌詞的情境下,精確標記每個音素(phoneme)與文字的起止邊界(boundaries)。 - Phoneme Segmentation(無歌詞):
直接預測音素及其邊界,並自動分句,無需輸入歌詞也能進行歌聲分析。 TextGrid的輸出結果建議使用Praat應用程式檢視與編輯
- Alignment(有歌詞):
-
MIDI 預測(MIDI Prediction)
- 可結合已標註資料,透過 ROSVOT 取得 MIDI 音樂資訊。
- 提供 rule-based(規則式)方法,結合 F0(基頻)、節拍、調性等資訊,預測並量化 MIDI。
-
卡拉OK 字幕生成(Karaoke Subtitle Generation)
- 自動生成 ASS 格式字幕檔,便於進一步用 Aegisub 製作動態卡拉OK 字幕。
- 黑色:輸入/輸出資料(粗體底線標示資料形式)
- 綠色:Phonsa 內部腳本(未特別標註者為
bin/資料夾內腳本) - 橘色:不可調整的 logits 或大類別
- 藍色:外部其他功能模組
- 棕色空心箭頭:無歌詞到有歌詞 pipeline 的銜接流程
使用流程圖時,請先確認你的需求,找到對應的「輸入」與「輸出」黑色框框。依照連線順序,依序執行流程圖上的綠色框框腳本,過程中會產生中間資訊,最終取得你要的輸出。
- 輸入:Mixture Audio
- 需求輸出:Karaoke-style subtitles
執行流程(可選兩種):
- 順序1(更精確分句):
source_separation.py→unsupervised_phoneme_segmentation.py→transcription.py→sentences_alignment.py→generate_ass.py - 順序2(全曲辨識+對齊):
source_separation.py→transcription.py→alignment.py→generate_ass.py
- 輸入:Clean vocal Audio、Line-by-line Lyrics
- 輸出:Fully labeled Json
執行流程:
sentences_alignment.py → alignment_to_ROSVOT_data.py → ROSVOT → combine_final_meta.py
- 輸入:Mixture Audio、逐句歌詞
- 輸出:Quantized Midi(包含對應的歌詞 txt)
執行流程:
source_separation.py → sentences_alignment.py → midi_prediction.py
- Fastsinger: AIlabs內部歌聲合成系統-軒瑜分支
- Faster-whisper: Transcription可選模型
- ROSVOT: MIDI prediction model for SVS
- Aegisub: 製作字幕免費軟體
- Praat: TextGrid(標註對齊檔案)檢視與編輯
若要在AILabs使用,模型已經存放在/volume/nas-ai-music-dataset/ai-autoalignment/model/PhonSA中,link volume: nas-ai-music-dataset即可使用
若要執行 3.自動歌聲標註(Automatic Singing Voice Annotation) 的功能,請先下載並準備好所需的預訓練模型,提供以下兩種下載方式:
您可以直接從以下 Google Drive 連結下載所有預訓練模型壓縮檔,並自行將其解壓縮。
請執行 data_processing/download_pretrained_model.py 腳本,根據需求選擇語言與輸出資料夾,腳本將自動幫您下載並解壓預訓練模型。
使用方法:
python data_processing/download_pretrained_model.py --lang <zh|ja|all> --out_dir <output_directory>--lang參數可選擇zh(中文)、ja(日文)或all(全部)。--out_dir參數請指定模型存放的輸出目錄。
請依照上述任一方式完成模型下載後,確認模型資料夾位置並在之後設定到config的yaml中(詳見inference config setting)。
本專案需 Python 3.9 以上版本。
pip install -r requirements.txt
export PYTHONPATH=.apt-get update
apt-get install ffmpeg若需在 transcription 階段啟用 faster-whisper,請依照官方 faster-whisper repo 安裝相關套件。
如為 AILabs 環境,亦可直接執行(需link volume: nas-ai-music-dataset):
bash ailabs_faster_whisper_install.sh進行一鍵安裝。
若需執行 bin/midi_prediction.py,請額外執行:
bash requirement_midi.sh此外,bin/midi_prediction.py 會使用 ROSVOT 的 F0 預測模型。請至 ROSVOT repo 下載所需模型檔案,並解壓縮到任意路徑。執行時請於 config 中指定正確的模型路徑。
本專案的主要功能皆以指令列程式的形式收錄於 bin/ 目錄下,請於 phonsa repo 的根目錄中執行相應程式,並指定對應的 config 設定檔。Config 設定檔的指定方式有以下兩種:
-
環境變數指定(建議用於長期或批次運行)
在執行命令前,先設定全域環境變數
PHONSA_DEFAULT_CONFIG為 config 檔案路徑:export PHONSA_DEFAULT_CONFIG=infer/alignment_myfile_zh.yaml python bin/alignment.py -
指令參數指定(適合個別功能與臨時測試)
直接於執行命令時,透過
--config參數指定 config 檔案:python bin/alignment.py --config configs/infer/alignment_myfile_zh.yaml
請注意:
bin/內的所有功能均需依此方式指定 config 設定檔,否則將無法正常運行。- config 檔案可根據不同功能與需求進行調整,詳細可調參數與範例將於下方各功能段落說明 (可利用搜尋CTRL+F查詢
.py檔名稱)。
本專案支援「批量處理」與「單曲處理」兩種輸入格式,方便依據不同任務需求彈性應用,可同時使用。
請準備一個 list[dict] 結構的 JSON 檔案,每個 dict 需包含下列欄位(不同任務會要求不同資訊):
- song_id (必填):
唯一識別字串,將作為所有輸出檔案的檔名。 - song_path (必填):
歌曲檔案路徑(副檔名需為 librosa.load() 支援格式,無取樣率限制)。 - lyric(整段歌詞對齊時必需):
歌詞字串,會自動過濾不合法字元。- 中文模型:支援中文或英文(英文自動轉為類似拼音對齊)。
- 日文模型:支援平假名、片假名、漢字。
- clips(逐句對齊時必需):
list[list[start_time(float), end_time(float), lyric(str)]]- 依句順序排列,每句包含開始/結束時間與歌詞。
- 時間不能重疊,最後一句的 end_time = -1 代表至音檔結束。
- 若無時間資訊,全部 start_time 設 0.0、end_time 設 -1。
蒐集 meta 的範例程式可參考:
data_processing/meta_collection.py
Input.json 範例:
[
{
"song_id": "little_star",
"lyric": "一閃一閃亮晶晶滿天都是小星星",
"song_path": "/audio/absolute/path/little_star.wav",
"clips": [
[12.35, 16.78, "一閃一閃亮晶晶"],
[19.43, 23.80, "滿天都是小星星"]
]
}
]僅需提供「音檔路徑」及「歌詞.txt」路徑(如需更細資訊或逐句時間請改用「批量處理」格式)。
txt檔案若需分句,請用換行分隔,歌詞格式同批量處理: lyric。
lyric.txt 範例:
一閃一閃亮晶晶
滿天都是小星星執行主程式後,會自動在 single_file_meta 資料夾產生對應的 JSON meta 檔。
在bin中的腳本都適用,不特別隸屬於某個功能的configs 粗體選項為建議使用者依需求調整,其餘可沿用預設值。
請先於 /configs/infer/base.yaml 設定基本選項:
-
test_data (必填):
(str 或 list[Union[str, list[str, str]]])- (str): 批量處理 JSON 路徑
- (list): 可混合以下格式
- (str): 批量處理 JSON 路徑
- (list[str, str]): 單曲音檔路徑與歌詞路徑(無歌詞則用空字串
'')
範例:
test_data: - ['/audio/absolute/path/little_star_nolyric.wav', ''] - ['/audio/absolute/path/little_star.wav', 'lyric.txt'] - generated_meta/opencpop_test.json
-
test_sample: (list[str]) 僅針對指定 song_id 執行
-
for_test: (int) 隨機抽取 N 首測試(含 test_sample),0 表示關閉
-
model_dir (必填):模型資料夾路徑,中文與日文的模型路徑會不同
-
model_name:模型名稱,會載入
{model_dir}/{model_name}_model.pt模型檔案 -
meta_save_filename: 輸出meta (in 'output_dir'/meta)的檔名前綴,以區別不同次的結果
-
output_dir: 主要輸出路徑
-
specific_logits_dir: 特別指定logits的資料夾路徑,以使用之前其他實驗時執行過的結果
-
seed: (int) 隨機種子
-
device: (str) CUDA 裝置
-
User_Warning_Checking: (bool) 要輸出的結果檔案時若已存在,是否詢問用戶(false 則自動覆蓋存在檔案)
-
force_rerun: (bool) 若為False則不會重複執行已經有的中途檔案與結果;若為True則強制覆蓋既有結果
小提醒:
每個功能可能還有專屬的 config 可調選項,細節與範例請見後續各功能說明章節。
可使用下列指令進行自動歌詞辨識:
python bin/transcription.py本功能支援三種辨識模型,可針對整首音檔或每個音檔片段(如有 clips 資訊)進行辨識:
- 自有微調(Finetune)模型 (即General Config中的
model_dir的模型) - Whisper 預訓練模型
- Faster-whisper 模型
| 參數名稱 | 型態 | 預設值 | 說明 |
|---|---|---|---|
save_ori_lyric |
bool | false | 是否將原歌詞(如有)存入結果(多用於評測) |
save_into_input_meta |
bool | true | 是否將辨識結果直接寫入輸入 meta,方便後續任務接續 |
compute_logits |
bool | true | 是否計算 logits,避免重複模型讀取(僅當 use_pretrained='' 時有效) |
use_pretrained |
str | '' | 模型選擇:'' = 自有模型,'whisper','faster-whisper' |
pretrained_size |
str | 'medium' | Whisper/Faster-whisper 的模型大小 |
beam_size |
int | 5 | beam search 寬度 |
ignore_exist_lyric |
bool | false | 是否強制覆寫已存在歌詞 |
condition_on_previous_text |
bool | true | faster-whisper 專屬功能,根據前句參考內容 |
remove_non_chinese |
bool | false | 中文專用:是否移除非中文字 |
illegal_word |
list | [] | 若出現指定詞語,直接將該句設為空白(移除幻聽) |
max_stack_word |
int | 3 | 疊字最大上限,防止出現過長重複字 |
- 若
save_into_input_meta=true,則 General Config 中 test_data 指定的 meta 檔案會直接被帶有預測結果的新檔案覆寫。 - 各音檔辨識結果會儲存在:
output_dir/transcription/{song_id}.json,每個檔案對應一首音檔。 - 全部音檔的辨識結果會彙整於:
output_dir/meta/{meta_save_filename}_transcription.json,便於批次檢視與管理。
補充說明:
- 可靈活選用任一模型,並依需求調整辨識片段範圍、後處理等設定。
- 若 clips 有提供,將對每個片段分別辨識;否則對整首音檔辨識。
- 辨識結果可直接寫入 meta,便於 pipeline 流程無縫接續其他功能。
output_dir與{meta_save_filename}是指在General Config中的設定
- 全音檔對齊:使用 meta 中的
lyric與音檔進行整首對齊python bin/alignment.py
- 逐句對齊:使用 meta 中的
clips資訊與音檔逐句對齊 (註:目前此方法的標註結果不含換氣'@')python bin/sentences_alignment.py
| 參數名稱 | 型態 | 預設值 | 說明 |
|---|---|---|---|
save_audio_for_check |
bool | false | 是否將 input audio 一同輸出至結果資料夾,便於 Praat 檢查 |
use_given_phoneme |
bool | true | 是否使用 meta 中提供的 phoneme(如有),常用於評測 |
logits_only |
bool | false | 是否僅計算 logits 而不執行對齊 |
use_given_bre_label |
bool | false | 是否使用 full_label 中的換氣標籤 ('@') |
bre_pred |
bool | true | 是否自動從未對齊片段預測換氣標籤 ('@') |
min_bre_len |
float | 0.1 | 被判定為換氣標籤的最短區間長度(單位:秒) |
infer_add_boundary |
bool | true | 是否將 boundary_token 加入對齊序列 |
-
output_dir/alignment/{song_id}.TextGrid- 含每個音檔的對齊結果
- Tier 說明:
pred sentence: 逐句對齊區間,僅 sentences_alignment.py 有pred word: 字級區間pred phoneme: 音素級區間
-
output_dir/meta/{meta_save_filename}_alignment.json- 彙整全部音檔對齊結果,格式同訓練資料(詳見
TRAIN.md)
- 彙整全部音檔對齊結果,格式同訓練資料(詳見
-
output_dir/meta/{meta_save_filename}_alignment_interval_error_list.json- 執行 sentences_alignment.py 時,記錄個別音檔對齊錯誤訊息
補充說明:
- 可依需求選擇全首或逐句對齊流程,並靈活調整對齊相關參數。
- 對齊結果便於後續於 Praat 等工具視覺化檢查及後處理。
output_dir與{meta_save_filename}是指在General Config中的設定
可使用下列指令進行音素自動標註與分句:
python bin/unsupervised_phoneme_segmentation.py| 參數名稱 | 型態 | 預設值 | 說明 |
|---|---|---|---|
auto_split_audio_clips |
bool | true | 是否自動將分句結果音檔儲存(存檔總容量約等於輸入音檔總大小,格式為 wav) |
combine_clips_len |
float | 0 | 若分句片段長度小於指定秒數,則自動合併片段,預設 0 代表不啟用 |
long_sil_th |
float | 1.0 | 判斷分句用的靜音閾值(秒) |
save_audio_for_check |
bool | false | 是否將 input audio 一同輸出至結果資料夾,便於 Praat 檢查 |
write_into_meta |
bool | true | 是否將辨識結果直接寫入輸入 meta,方便後續任務接續 |
save_textgrid |
bool | true | 是否儲存 TextGrid 結果 |
save_top5 |
bool | false | 是否在 TextGrid 中輸出每個 frame 預測的前五名(詳細預測結果) |
-
output_dir/phoneme_prediction/{song_id}/{song_id}-{n}.wav:自動分句的音檔backup_meta.json:對應自動分句音檔的 meta 結果,格式同訓練資料(詳見TRAIN.md)
-
output_dir/ph_pred_textgrid/{song_id}.TextGrid- 含每個音檔的對齊與音素預測結果
- Tier 說明:
sentence:分句結果,"V" 代表有聲片段pred word:字級區間pred phoneme:音素級區間
補充說明:
- 支援自動分句與音素標註,適用於無標註資料或需快速前處理的場景。
- 輸出結果可直接用於 Praat 視覺化檢查,也可無縫接續訓練/對齊等後續流程。
output_dir與{meta_save_filename}是指在General Config中的設定
作者自製的考慮各種音樂資訊的Rule-based MIDI prediction,需是帶有背景音樂的音檔才能有好效果。(在執行完source_separation.py後meta中mixture_path的音檔)
可使用下列指令進行自動 MIDI 預測:
python bin/midi_prediction.py| 參數名稱 | 型態 | 預設值 | 說明 |
|---|---|---|---|
textgrid_source |
str | 'alignment' | 指定來源 TextGrid 類型,可選 'alignment' 或 'phoneme_prediction' |
save_inplace |
bool | false | 是否將F0與beat等音樂資訊儲存在與音檔相同的路徑中 |
pe_ckpt |
str | (需填路徑) | F0 預測模型權重路徑,請至 ROSVOT 下載並指定(AILabs內部可免) |
one_note_per_word |
bool | false | 是否一個單字只對應一個音高音符(即無轉音) |
short_note_th |
float | 0.15 | 最短音符長度閾值(秒),過短音符將移除 |
extend_notes |
dict | enabled:True space_sec_th:0.299 |
控制音符延長,當相鄰音符間隔小於 space_sec_th 時自動延長前個音符到下個音符開始 |
fix_pitch_jump |
dict | enabled:True space_sec_th:0.5 jump_pitch:15 |
防止相鄰音高斷裂,當間隔小於 space_sec_th 且音高變化超過 jump_pitch 時自動修正一個八度 |
output_dir/midi_prediction/textgrid/:主輸出結果,包含MIDI值與相應調整對齊後的標註結果 ({song_id}.TextGrid)- Tier 說明:
pred sentence: 逐句對齊區間 (繼承自textgrid_source)pred word: 字級區間 (繼承自textgrid_source)pred phoneme: 音素級區間 (繼承自textgrid_source)beats: 拍點,數字1~4代表第一正拍到第四正拍,0與8是自動填入的16分音符(1/4正拍)與8分音符(1/2正拍)pred midi: 預測的MIDI,無音高的地方為空值
midi/:預測的 MIDI 檔案({song_id}.mid)f0/:對應 F0 預測資料({song_id}.f0.pt)beats/:節拍資訊 ({song_id}.beats.npy)key/:調性資訊 ({song_id}.key.txt)txt/:純文字歌詞,#符號代表轉音,即複製前個字的母音,與midi/內的檔案文字與MIDI一對一對應,可作為Fastsinger的input(Ex: Song Template, End2end SVS) ({song_id}.txt)
補充說明:
- 須先下載 ROSVOT F0 預測模型並於 config 指定
pe_ckpt路徑。- 輸出資料夾結構可參考
examples/output/midi_prediction/。- 支援根據不同 TextGrid 來源(如對齊或音素預測)靈活配置。
output_dir是指在General Config中的設定
可使用下列指令進行自動聲源分離,並會自動管理input meta中(即test_data in General Config)的相關路徑:
python bin/midi_prediction.py| 參數名稱 | 型態 | 預設值 | 說明 |
|---|---|---|---|
model_type |
str | 'demucs' | 使用的模型架構類型,可選 'demucs' 或 'mel_band_roformer'。 |
model_name |
str | 'default' | 指定模型權重名稱(僅適用於 demucs),推薦使用 'default'。 |
vocal_only |
bool | true | 是否僅儲存分離後的人聲(Vocal)與伴奏(inst),false 則會輸出所有樂器音軌。 |
save_inplace |
bool | false | 是否直接在原始音檔目錄儲存分離結果,若為 true 則忽略 output_dir 設定。 |
verbose |
bool | false | 是否於伺服器後台印出詳細處理日誌(log)。 |
uvr_settings.enabled |
bool | true | 是否啟用 Ultimate Vocal Remover (UVR) 進行人聲後處理(去殘響、除合音等)。 |
uvr_settings.model_sequence |
list(str) | ['UVR-De-Echo-Aggressive', '6_HP-Karaoke-UVR'] | UVR 處理序列,指定使用的模型名稱順序(先去回音再做合聲分離等)。 |
uvr_settings.is_normalization |
bool | true | 是否將輸出音檔數值歸一化到 [-1, 1],以避免爆音。 |
uvr_settings.target_sr |
int/None | None | UVR 處理時的目標取樣率,設為 None 表示使用模型預設取樣率。 |
uvr_settings.vocal_stem_only |
bool | true | UVR 處理鏈是否僅保留乾淨人聲,設為 false 則會額外儲存分離出的雜訊音檔(處理時間較長)。 |
output_dir/source_separation/{song_id}.{model_type}.{stem_type}.wav: 不同模型不同音軌的輸出結果
補充說明:
- 首次執行會自動下載需要的模型檔案並儲存在
model/中 (除Demucs會自己管理模型位置)- 執行完後會自動更新input meta中的相關路徑 (比如
'song_path'會從原本的音檔路徑改為分離後乾淨人聲的音檔路徑),便於接續任務output_dir是指在General Config中的設定
目前功能仍在持續完善階段,但已可利用標註好的 TextGrid 產生可用字幕,可用於檢查對齊與標註效果。
python bin/generate_ass.py| 參數名稱 | 型態 | 預設值 | 說明 |
|---|---|---|---|
sentence_tier_name |
str | 'pred sentence' | 指定分句資訊的 Tier name |
target_tier_name |
str | 'pred word' | 指定主字幕的 Tier name |
sub_tier_name |
str | 'pred phoneme' | 指定副字幕的 Tier name |
textgrid_source |
str | 'alignment' | 指定來源 TextGrid 類型,可選 'alignment' 或 'phoneme_prediction' |
show_bre |
bool | false | 是否顯示換氣符號 "@" |
zh_transform |
str | '' | 使用 OpenCC 進行文字轉換(如 "t2s" 為繁體轉簡體) |
min_word_duration |
float | 0.02 | 最低單字顯示時長(秒) |
min_split_sil |
float | 0.5 | 最短靜音時長(秒),小於此值會將前字結束延長到下個字開始 |
min_split_bre |
float | 0.2 | 最短可視作分句的換氣時長(僅在 sentence_tier_name 為空時啟用) |
soft_max_sentence_len |
float | 7.0 | 一句軟性的最大句子時長(秒)(僅在 sentence_tier_name 為空時啟用) |
max_sentence_display_len |
int | 60 | 一句最大顯示的字數(僅在 sentence_tier_name 為空時啟用) |
output_dir/ass_txt_output/{song_id}.txt- 產生的卡拉OK字幕檔(ASS 格式),可透過複製貼上到Aegisub介面中下方的字幕區
生成可直接輸入ROSVOT的Input meta
python bin/alignment_to_ROSVOT_data.pyoutput_dir/meta/{meta_save_filename}_ROSVOT.json
可使用下列指令統整 MIDI 標註與 phoneme 標註的 meta 資訊:
python bin/combine_final_meta.py| 參數名稱 | 型態 | 預設值 | 說明 |
|---|---|---|---|
midi_dir |
str | null | 若為空值則自動指定到 midi_prediction.py 的輸出資料夾。若用 ROSVOT 預測,請設為其輸出中的 /midi/ 路徑 |
use_meta_info |
bool | False | 是否採用 test_meta 中的 label 資訊,而非 TextGrid 標註結果 |
word_tier_name |
str | "pred word" | 指定字符階級的 Tier name |
phoneme_tier_name |
str | "pred phoneme" | 指定音素階級的 Tier name |
textgrid_source |
str | "alignment" | 指定來源 TextGrid 類型,可選 'alignment' 或 'phoneme_prediction' |
output_dir/meta/{meta_save_filename}_Final.json- 統整後的 meta 資訊,包含 MIDI 與 phoneme 標註結果,適合用於 SVS 訓練或其他 downstream 任務。
補充說明:
- 可整合來自不同來源(midi_prediction 或 ROSVOT)的 MIDI 標註與 phoneme 標註結果。
output_dir與{meta_save_filename}是指在General Config中的設定
若想訓練新的語言或是進一步Finetune模型,請參考TRAIN.md中的詳細介紹。
以下是本專案所參考或整合的相關開源專案:
-
LyricAlignment
歌詞對齊與訓練程式碼。 -
DiffSinger (Hparams handling)
參考其超參數(hparams)管理方式。 -
Ultimate Vocal Remover
人聲/伴奏分離工具。 -
RMVPE from ROSVOT
準確的音高檢測(RMVPE)模組。 -
MelBandRoformer
基於 Mel 頻帶的 Roformer 音源分離訓練框架。
