Skip to content

Examples

ChouChiu edited this page Sep 23, 2026 · 3 revisions

使用示例

全部示例代码均内嵌测试数据,可直接复制运行。

解析与数据读取

自动识别并解析

use lyrics_helper::parse_auto;

fn main() {
    let content = "[00:12.00]Hello World\n[00:15.50]Second line";
    let data = parse_auto(content).expect("识别或解析失败");

    if let Some(lines) = &data.lines {
        for line in lines {
            println!("{}", line.text_from_any());
        }
    }
}

读取元数据与时间戳

use lyrics_helper::{parse, LyricsRawTypes};

fn main() {
    let content = "[ti:Song Title]\n[ar:Artist Name]\n[00:12.00]Hello World";
    let data = parse(content, LyricsRawTypes::Lrc).expect("解析失败");

    if let Some(meta) = &data.track_metadata {
        println!("曲名: {:?}", meta.title);
        println!("艺术家: {:?}", meta.artist);
    }

    if let Some(lines) = &data.lines {
        for line in lines {
            println!("[{:?}] {}", line.start_time(), line.text_from_any());
        }
    }
}

遍历逐字音节时间

use lyrics_helper::models::LineInfo;
use lyrics_helper::{parse, LyricsRawTypes};

fn main() {
    let content = "[0,2000]Hello(0,600) (600,400)World(1000,1000)\n\
                   [3000,2500]Second(3000,1200) (4200,200)line(4400,1100)";
    let data = parse(content, LyricsRawTypes::Qrc).expect("解析失败");

    if let Some(lines) = &data.lines {
        for line in lines {
            if let Some(syllables) = line.syllables() {
                for syl in syllables {
                    println!("  [{},{}] {}", syl.start_time(), syl.end_time(), syl.text());
                }
            }
        }
    }
}

读取翻译、注音与背景和声子行

use lyrics_helper::{parse, LyricsRawTypes};

fn main() {
    let content = r#"<?xml version="1.0" encoding="UTF-8"?>
<tt xmlns="http://www.w3.org/ns/ttml" xmlns:itunes="http://music.apple.com/lyric-ttml-internal" xmlns:ttm="http://www.w3.org/ns/ttml#metadata" xml:lang="en">
  <body>
    <div>
      <p begin="0.0" end="3.0" itunes:key="L1">
        <span begin="0.0" end="1.5">Hello</span>
        <span begin="1.5" end="3.0" ttm:role="x-bg">(<span begin="1.5" end="3.0">echo</span>)</span>
      </p>
    </div>
  </body>
  <itunes:translations>
    <itunes:translation type="subtitle" xml:lang="zh">
      <itunes:text for="L1">你好</itunes:text>
    </itunes:translation>
  </itunes:translations>
</tt>"#;

    let data = parse(content, LyricsRawTypes::Ttml).expect("解析失败");
    let line = &data.lines.as_ref().unwrap()[0];

    // 主文本与拼接子行的完整文本
    println!("主文本: {}", line.text_from_any());
    println!("完整显示: {}", line.full_text());

    // 翻译与注音
    if let Some(zh) = line.chinese_translation() {
        println!("中文翻译: {zh}");
    }

    // 伴唱子行
    if let Some(sub) = line.sub_line() {
        println!("子行内容: {}", sub.text_from_any());
    }
}

格式转换

逐字格式互转

QRC、KRC、YRC 与 Lyricify Syllable 之间可以互相转换,音节级时间轴完整保留:

use lyrics_helper::{generate_string, parse, LyricsRawTypes, LyricsTypes};

fn main() {
    let syllable = "[4]Hel(0,600)lo(600,400) (1000,300)World(1300,700)\n\
                    [4]Second(3000,1200) (4200,200)line(4400,1100)";
    let data = parse(syllable, LyricsRawTypes::LyricifySyllable).unwrap();

    let qrc = generate_string(&data, LyricsTypes::Qrc).unwrap();
    println!("--- QRC ---\n{qrc}");

    let yrc = generate_string(&data, LyricsTypes::Yrc).unwrap();
    println!("--- YRC ---\n{yrc}");
}

逐字降级为逐行 LRC

use lyrics_helper::{generate_string, parse, LyricsRawTypes, LyricsTypes};

fn main() {
    let qrc = "[0,2000]Hello(0,600) (600,400)World(1000,1000)\n\
               [3000,2500]Second(3000,1200) (4200,200)line(4400,1100)";
    let data = parse(qrc, LyricsRawTypes::Qrc).unwrap();

    // 逐字降级为 LRC 逐行
    let lrc = generate_string(&data, LyricsTypes::Lrc).unwrap();
    println!("{lrc}");
}

歌词解密

use lyrics_helper::{decrypt_krc, decrypt_qrc, parse, LyricsRawTypes};

fn main() {
    // 1. QRC 解密
    let qrc_hex = "9FD341D70ACF96D59FB0C7DBB4D6DC3597BDB2000DB276840C98E56C039C7200698E953B\
                   BA404B8F7B04CF1342633627F64E04CEF5B16748696B9A64B3987B174943C1CE7EFB04A0\
                   725C8833D4ED3DA19E2B2B2EAE76F5365BE4571E7EA46C44";
    if let Some(qrc) = decrypt_qrc(qrc_hex) {
        let data = parse(&qrc, LyricsRawTypes::Qrc).unwrap();
        println!("QRC 解密成功: {} 行", data.lines.as_ref().unwrap().len());
    }

    // 2. KRC 解密
    let krc_b64 = "a3JjMTidGsglTQAO96N6R6CsQj70xu/m37M169y3v7RPU+Do3QAL+VO6caa00kJo1dGLHMwLQ\
                   P1Sv7SlsM90FOeOblfHU2Y=";
    if let Some(krc) = decrypt_krc(krc_b64) {
        let data = parse(&krc, LyricsRawTypes::Krc).unwrap();
        println!("KRC 解密成功: {} 行", data.lines.as_ref().unwrap().len());
    }
}

时间偏移与跨文档对齐

调整时间戳

use lyrics_helper::helpers::offset_helper::add_offset;
use lyrics_helper::{generate_string, parse, LyricsRawTypes, LyricsTypes};

fn main() {
    let content = "[00:12.00]Hello World";
    let mut data = parse(content, LyricsRawTypes::Lrc).unwrap();

    if let Some(lines) = &mut data.lines {
        // 延后 500ms(负值延后,正值提前)
        add_offset(lines, -500);
    }

    let output = generate_string(&data, LyricsTypes::Lrc).unwrap();
    println!("{output}");
}

跨文档逐词时间对齐

将逐词文档(如 YRC)的时间迁移到排版规范的逐行歌词上:

use lyrics_helper::helpers::word_timing::apply_word_timings;
use lyrics_helper::{LineInfo, SyllableInfo};

fn main() {
    let mut text_lines = vec![LineInfo::new_line(
        "Ugh, you're a monster".to_string(),
        Some(90),
        Some(2160),
    )];

    let word_lines = vec![LineInfo::new_syllable(vec![
        SyllableInfo::new("Ugh".to_string(), 90, 420).into(),
        SyllableInfo::new("you're ".to_string(), 420, 690).into(),
        SyllableInfo::new("a ".to_string(), 690, 960).into(),
        SyllableInfo::new("monster".to_string(), 960, 2160).into(),
    ])];

    apply_word_timings(&mut text_lines, &word_lines);

    assert!(text_lines[0].is_syllable());
    assert_eq!(text_lines[0].text_from_any(), "Ugh, you're a monster");
}

Clone this wiki locally