Files
hoelee-blog/src/content/posts/zh/generating-subtitles-for-songs-without-timestamps.md
T
hoelee cd6511a0b3
Deploy / build (push) Successful in 22s
docs(review): apply batch-04 consultant fixes and approve 5 tutorial/web3 posts
- performUpkeep: external callable, re-check is mandatory security (not stale-data hygiene)
- BasicNft.tokenURI: ownerOf -> _ownerOf, dead custom error explained
- storage (SSTORE) vs EIP-170 runtime bytecode separated, derived ~1.3M gas for the two SVGs
- subs-15 retimed from a fresh faster-whisper word alignment (10.84s first line, was 28.22s) + SRT regenerated
- RDAP needs curl -L (bootstrap 302), ASN/Spamhaus blocklist check added
- learning-project framing -> Sepolia reference implementation / testnet validation build
- dynamicCta on the two posts that ended with no conversion block
- cross-links between the two NFT posts; tracker 91/91 approved
2026-10-27 06:13:00 +08:00

46 KiB
Raw Blame History

title, description, pubDate, category, blueprint, blueprintLayer, stream, tags, ogImage, banner, dynamicCta, draft
title description pubDate category blueprint blueprintLayer stream tags ogImage banner dynamicCta draft
给没有时间戳的歌曲自动生成字幕 AI 音乐工具只给你音频 —— 没有逐行时间,没有卡拉 OK。这是我给 18 首歌生成 LRC 与 SRT 字幕的完整流程,为什么单纯转写不行,以及让歌词框滚到底的两个 bug。 2026-10-20 tutorials ai-agent-automation L3-local-gpu-inference creative-lab
subtitles
lrc
srt
whisper
forced-alignment
ai-music
python
/og/zh-generating-subtitles-for-songs-without-timestamps.jpg /banners/generating-subtitles-for-songs-without-timestamps.jpg true false

我试过的每一个 AI 音乐工具,交出来的东西形状都一样:一个音频文件。没有一个会告诉你每一句是什么时候唱的。只想听的话没问题,但只要你想把歌词放到屏幕上 —— 卡拉 OK 的那一行、视频字幕、播放器下面的滚动框 —— 就完全不够用。

时间轴才是全部难点。音频反而是简单的部分。

这是我最后跑通的一套流程,用在本地生成的 18 首英文歌上,外加它在浏览器里崩掉的两个地方。下面全部可复现:它唯一需要你提供的东西,是你已经写好的歌词。

你真正需要的两样东西

两种字幕格式,共用同一份数据结构:

格式 用在哪 长什么样
LRC 音乐播放器、卡拉 OK 块、<audio> 歌词层 [mm:ss.xx]歌词行
SRT VLC、YouTube、Premiere、ffmpeg 烧字 序号 / hh:mm:ss,mmm --> hh:mm:ss,mmm / 文本

两者本质都是「行 → 起始时间」(SRT 多一个结束时间)。所以真正的任务是: 给定一串歌词行和一个音频文件,找出每一行从哪儿开始。

为什么「直接转写」行不通

最直觉的做法:跑一次语音识别,把它的分段结果写出去。它会因为两个原因失败。

1. 唱腔的识别率远低于说话。 模型要同时对付乐器、混响和拉长的元音。我这一批里,中文唱词的词错率大约 25–35%,电子混音密集的更差。

2. 它会整段丢掉。 有一首 140 BPM 的燃曲,整段第一段主歌压根没出现在转写结果里 —— 人声被埋住了,模型直接跳过去。另外两首丢了尾奏。

有洞的转写,变不出没洞的字幕。但换个框法就全通了:

你不是在转写,你是在对齐。你早就知道确切的字 —— 那就是你的歌词。音频只是用来提供锚点。

让它成立的思路反转

让识别器给出词级时间戳,然后拿它的输出跟你已知的歌词做最长公共子序列 diff。你根本不在乎它有没有听对 —— 你在乎的是它听出来的那些词顺序对不对,因为每一个匹配都是一个时间锚点。

import difflib

ref = [u for line in lines for u in units(line)]      # 你的歌词
hyp = [w[0] for w in asr_words]                        # 它听到的
sm = difflib.SequenceMatcher(a=ref, b=hyp, autojunk=False)

for tag, i1, i2, j1, j2 in sm.get_opcodes():
    if tag != "equal":
        continue            # 不匹配的地方只是空洞,不是错误
    for k in range(i2 - i1):
        matched[ref_index[i1 + k]] = asr_words[j1 + k][1:]   # (起, 止)

然后每一行歌词取它第一个匹配单位的时间戳。这种做法的稳健性是转写给不了的:60–70% 的词准确率就完全够用,因为每一个位置正确的词都钉住了它所属的那一行。

这批实测的锚定覆盖率 —— 也就是「拿到了至少一个真实锚点」的行占比:

语言 单位 平均锚定覆盖率 全行锚定的歌
英文 词 0.96 9/18 首
中文 字 0.70 11/11 首

英文对齐更好,原因很无聊:词之间用空格隔开,所以每个 ASR token 能干净地对应一个歌词 token。中文则必须把每个字平摊到 token 的时间跨度上:

span = w.end - w.start
for i, ch in enumerate(hanzi_in_word):
    chars.append((ch, w.start + span * i / n, w.start + span * (i + 1) / n))

修正器:三条规则,挡住荒唐的时间

锚点能带你走完大半程。但如果放着不管,锚点之间的空隙会产出物理上不可能的时间 —— 其中两个是真的咬到我了:

故障 A —— 一行落在 0.0 秒。 有一首歌的第一句歌词正好落在零点,前奏都还没结束,因为锚点搜索在开头的喊麦里匹配到了一个零散的字。

故障 B —— 四行挤在 0.6 秒里。 有一首歌的尾奏被识别器整段漏掉,剩下的行被压到相隔 0.18 秒。12 个字不可能在 0.18 秒里唱完。

故障 C —— 六行被死死压在硬下限上。 有一首的整个第一段主歌完全没有可用锚点,于是第 3 条规则把连续六行扫到了最小间隔:每行正好 1.20 秒,大约相当于每秒十个词。输出看起来依然「合理」—— 单调递增、在音频时长范围内 —— 直到我去听那一首,整段主歌六秒就唱完了。只对这一个文件重跑一次对齐,第一行就落到了 10.8 秒而不是 28.2 秒:锚点不是缺失,而是被匹配到了歌里错误的位置。

所以对齐之后,跑三条规则:

  1. 估计这首歌自己的速率 —— 用相邻两行都已锚定的样本(单位数 ÷ 秒数,取中位数)。每行的期望时长 = 单位数 ÷ 速率,下限约 1.8 秒。同一批里英文是 0.96 到 2.33 词/秒,中文是 2.3 到 4.1 字/秒,不能用全局常数。
  2. 按比例填充没锚定的段,而不是固定行距。一段夹在两个锚点之间,就按期望时长分摊;空间不够就等比压缩。
  3. 剔除不可能的锚点 + 强制最小行距。 起始时间早于「5 秒 + 它前面所有内容可能占用的时间」的锚点一定是假匹配 —— 降级重算。然后正向扫一遍,保证任意两行起始间隔不小于 1.2 秒;若尾部被推出音频,再从末尾倒推收回。

最后那趟扫描,才是把「看起来合理」变成「不可能闪烁」的关键。

同时输出两种格式

同一份时间数组,两个写出函数:

def lrc(ts, lines):                      # [mm:ss.xx]
    return "\n".join(f"[{m:02d}:{s:05.2f}]{l}" for (m, s), l in zip(ts, lines))

def srt(spans, lines):                   # hh:mm:ss,mmm
    out = []
    for i, (line, (a, b)) in enumerate(zip(lines, spans), 1):
        out.append(f"{i}\n{stamp(a)} --> {stamp(b)}\n{line}\n")
    return "\n".join(out)

LRC 只要起点;SRT 要起点和终点,所以用下一行的起点当作当前行的结束(这正是最小行距规则重要的原因 —— 没有它,SRT 块会变成零时长,有些播放器会整块跳过)。

验证:我错了两次的地方

字幕早在显示之前就是对的。两个 bug 都在那 20 行播放器脚本里,而且都是读代码看不出来的。

Bug 1 —— 一开播就在末尾。 找当前行我写的是 lines.findIndex(l => l.t > now) - 1。第一句之前 findIndex 返回 0,于是 i 变成 -1,而那句 if (i < 0) i = lines.length - 1 把「还没开始」翻译成了「最后一行」。播放器一打开就停在尾奏。

Bug 2 —— 然后第一个和弦就滚到底。 修完 bug 1,我用 p.offsetTop 来做居中。offsetTop 是相对最近的定位祖先量的 —— 而歌词框没有 position: relative,所以它返回的是这一行到页面顶部的距离,上千像素。scrollTop 被夹到 maxScroll:直接到底,字全看不见。

正确写法根本不关心定位上下文:

const br = box.getBoundingClientRect(), pr = p.getBoundingClientRect();
box.scrollTop += (pr.top - br.top) - (box.clientHeight - pr.height) / 2;

关于「怎么测」的教训比修复本身更重要。 我在 Node 里单测过索引逻辑 —— 通过了。我看过截图 —— 我把高亮的那一行看错了。两者都看不见布局 bug。真正有效的是在 headless Chrome 里打数值探针:stub 掉 currentTime,派发 timeupdate,然后把真实 DOM 读回来。

chrome --headless=new --dump-dom --virtual-time-budget=8000 \
       --window-size=760,520 "file:///probe.html"
Object.defineProperty(a, 'currentTime', { get: () => 100, configurable: true });
a.dispatchEvent(new Event('timeupdate'));
// 然后输出:当前行索引、它在框内的偏移、scrollTop、maxScroll

通过条件是数字,不是观点:当前行在框内的偏移应当约为框高的一半(我得到的 274 px 框里是 124 px);t = 0 时 scrollTop = 0 且没有任何行高亮;只有最后几句时 scrollTop = maxScroll。

结果

18 首歌,没有一首自带时间戳。现在每一首都有逐行的 LRC 和 SRT —— 只靠歌词加音频生成。上面覆盖率表里的中文那一行,来自另一批单独跑的 11 首中文验证集,不是这一页的播放器。

歌曲 18
字幕行数 342
平均锚定覆盖率 0.96
全行锚定的歌 9 / 18(每行都有时间)
处理耗时 每首 63–90 秒,纯 CPU 跑 faster-whisper

跑在 CPU 上是刻意的,不是我绕不过去的限制:这 18 首全部在 Core i9-13900K 上 (跑这套流程的那台 Windows 虚拟机)完成对齐,因为 GPU 要留给生成这些歌曲的 生产管线,而 faster-whisper int8 每首 63–90 秒已经足够便宜 —— 把对齐任务排在 一个扩散生成任务后面等,省下来的那点 CPU 时间根本不值。

下面每个播放器都会滚动歌词、把当前句保持在中间,旁边还有 .srt 下载 —— 想烧字进视频或在 VLC 里打开都行。

<style> .subs-track{margin:2.4rem 0;display:flex;gap:1.6rem;align-items:flex-start;padding:1.25rem;border-radius:12px;background:var(--card,#1e2025);border:1px solid var(--border,#3a3f47);box-shadow:0 4px 16px rgba(0,0,0,.1);box-sizing:border-box;width:100%;max-width:100%;overflow:hidden} .subs-cover{flex:0 0 38%;width:38%;max-width:325px;min-width:220px;aspect-ratio:1/1;border-radius:10px;overflow:hidden;border:1px solid var(--border,#3a3f47);background:#000;box-sizing:border-box} .subs-cover img{width:100%;height:100%;object-fit:cover;display:block} .subs-content{flex:1 1 0;min-width:0;width:100%;max-width:100%;box-sizing:border-box} .subs-content figcaption{display:flex;align-items:flex-start;justify-content:space-between;gap:.35rem .6rem;margin-bottom:.55rem;width:100%;box-sizing:border-box} .subs-title{flex:1 1 auto;min-width:0;font-size:1.08em;font-weight:700;color:var(--foreground,#f3f4f6);line-height:1.35;word-break:break-word;overflow-wrap:break-word} .subs-meta{display:block;width:100%;font-weight:400;opacity:.75;font-size:.85em;line-height:1.45;margin-top:.2rem;white-space:normal;word-break:break-word;overflow-wrap:break-word} .subs-dl{flex:0 0 auto;margin-left:auto;font-size:.8em;font-weight:600;text-decoration:none;border:1px solid var(--accent,#22c55e);border-radius:6px;padding:.18rem .55rem;color:var(--accent,#22c55e);background:transparent;white-space:nowrap;transition:all .15s} .subs-dl:hover{background:rgba(34,197,94,.14)} .subs-dl::before{content:"↓ "} .subs-content audio{width:100%;margin-top:.35rem;box-sizing:border-box} .subs-box{position:relative;max-height:220px;overflow-y:auto;border:1px solid var(--border,#3a3f47);border-radius:8px;padding:.7rem 1rem;margin-top:.6rem;font-size:.95em;line-height:1.6;background:rgba(0,0,0,.25);box-sizing:border-box} .subs-box p{margin:.18rem 0;opacity:.55} .subs-box p.on{opacity:1;font-weight:600;color:var(--accent,#22c55e)} @media(max-width:680px){ .subs-track{flex-direction:column;align-items:stretch;gap:1.2rem;padding:1rem;margin:1.8rem 0} .subs-cover{flex:none;width:100%;max-width:100%;min-width:0;aspect-ratio:1/1;margin:0;border-radius:8px} .subs-content{width:100%;min-width:0} .subs-title{font-size:1.02em} } </style>
Tiny Borrowed Shoes album cover
Tiny Borrowed Shoes · Celtic folk · 21 lines · 139 s.srt
[ti:Tiny Borrowed Shoes]
[ar:Mr Hoelee]
[00:11.56]Underneath the floorboards where the shadows play
[00:14.60]I tied a little ribbon at the break of day
[00:18.32]A button for a table, a thimble for a cup
[00:22.02]I climb the ivy ladder when the sun comes up
[00:27.76]Sugar on the windowsill, a feather in my hand
[00:31.42]The garden is a jungle and a wonderland
[00:35.22]Careful not to wake the cat sleeping by the door
[00:40.00]Tip-toe in my borrowed shoes across the wooden floor
[00:44.46]Fly away, little breeze, carry me along
[00:48.10]Through the clover and the leaves, singing my own song
[00:51.90]Though the world is wide and tall, and I am very small
[00:57.58]In the secret morning light, I can have it all
[01:09.62]Dewdrops on the dandelion shining like a crown
[01:12.24]I catch a floating parachute and spin around and down
[01:15.98]If you hear a tiny laugh hiding in the wall
[01:19.62]That is just my secret song, answering your call
[01:27.26]Fly away, little breeze, carry me along
[01:30.72]Through the clover and the leaves, singing my own song
[01:34.58]Though the world is wide and tall, and I am very small
[01:40.32]In the secret morning light, I can have it all
[01:51.98]La-la-la, in the morning light...
Mist Over Skellig album cover
Mist Over Skellig · Celtic folk · 18 lines · 193 s.srt
[ti:Mist Over Skellig]
[ar:Mr Hoelee]
[00:21.73]Where the gray Atlantic meets the abbey stone
[00:28.56]White birds circle high above the cliff alone
[00:33.56]Carved into the stairway of a thousand years
[00:42.16]Every drop of ocean rain whispers in my ears
[00:49.16]Sail into the silver mist, beyond the western sea
[00:57.96]Where the ancient lanterns glow for you and me
[01:06.32]Hush now, hear the harp strings ring across the foam
[01:14.74]Through the fog and falling stars, the tide will bring us home
[01:25.36]Candles in the chapel window flicker in the gale
[01:33.04]Ink upon the parchment tells a forgotten tale
[01:57.48]Little hands upon the rock, looking at the sky
[02:05.18]Watching all the centuries gently passing by
[02:16.98]Sail into the silver mist, beyond the western sea
[02:22.94]Where the ancient lanterns glow for you and me
[02:30.46]Hush now, hear the harp strings ring across the foam
[02:38.98]Through the fog and falling stars, the tide will bring us home
[02:57.02]Oceans rise and oceans fall...
[03:04.34]The tide will bring us home.
Willow by the Silver Stream album cover
Willow by the Silver Stream · Celtic folk · 19 lines · 197 s.srt
[ti:Willow by the Silver Stream]
[ar:Mr Hoelee]
[00:23.83]Mmm-mmm, ahh-ahh...
[00:26.70]Silver runs the quiet stream beneath the willow tree
[00:33.64]Golden is the evening star shining down on me
[00:40.54]All the little meadow flowers fold their petals tight
[00:46.36]Waiting for the moon to weave a blanket of the night
[00:53.02]May the wind be gentle on your weary wings
[00:59.76]May you hear the lullaby the river softly sings
[01:06.28]Close your eyes and drift away where the shadows gleam
[01:13.52]Peace will walk beside you in the valley of a dream
[01:27.32]Fireflies are dancing slow among the reeds and moss
[01:33.14]Showing every wandering heart the stepping stones to cross
[01:39.46]Nothing in the dark can harm the light inside your chest
[01:46.66]Lay your head upon the grass and let the world rest
[01:53.62]May the wind be gentle on your weary wings
[01:59.76]May you hear the lullaby the river softly sings
[02:06.30]Close your eyes and drift away where the shadows gleam
[02:13.42]Peace will walk beside you in the valley of a dream
[02:50.86]In the valley of a dream...
[02:56.54]Sleep in peace tonight.
Clockwork Starlight album cover
Clockwork Starlight · Japanese healing · 21 lines · 160 s.srt
[ti:Clockwork Starlight]
[ar:Mr Hoelee]
[00:19.30]Ticking in the quiet tower made of porcelain and glass
[00:23.44]I can see the painted clouds and paper swallows pass
[00:32.36]Every gear is turning slow beneath the velvet sky
[00:36.72]Counting all the shooting stars that never say goodbye
[00:46.12]Someone left a silver key beside the windowpane
[00:50.52]Unlocking all the memories hidden in the rain
[00:59.86]Sing for the dawn across the endless night
[01:04.66]Spinning the threads of shadow into light
[01:09.20]Even if the clock should stop and time fades away
[01:13.70]I will keep this little wish until the break of day
[01:22.28]La-la-lu-la, hear the distant bell
[01:31.34]Breaking the silent spell
[01:38.14]Pages of an ancient book are fluttering like wings
[01:42.50]Telling me of emerald seas and forgotten kings
[01:52.16]With my small and trembling hands I open up the door
[01:56.38]Stepping out into a world I've never seen before
[02:05.70]Sing for the dawn across the endless night
[02:10.56]Spinning the threads of shadow into light
[02:15.02]Even if the clock should stop and time fades away
[02:21.12]I will keep this little wish until the break of day
[02:33.64]Until the break of day...
Waltz of the Dandelion album cover
Waltz of the Dandelion · Japanese healing · 18 lines · 179 s.srt
[ti:Waltz of the Dandelion]
[ar:Mr Hoelee]
[00:17.62]One, two, three, the summer breeze is knocking at my door
[00:22.56]Dancing with the sunlit dust upon the wooden floor
[00:30.62]Out across the grassy hill the dandelions grow
[00:38.40]Waiting for a little breath to tell them where to go
[00:48.08]La-la-la, wherever you may fly
[00:53.28]Underneath the big and gentle sky
[00:57.28]Even when the seasons change and winter turns to spring
[01:06.06]I will still remember every little song we sing
[01:27.36]Drops of rain upon a leaf are rolling into one
[01:34.62]Shining like a diamond in the afternoon sun
[01:42.46]If you ever lose your way or feel a little sad
[01:50.26]Think about the quiet days and all the smiles we had
[02:00.18]La-la-la, wherever you may fly
[02:05.28]Underneath the big and gentle sky
[02:09.14]Even when the seasons change and winter turns to spring
[02:17.90]I will still remember every little song we sing
[02:25.96]La-la-la, la-la-la...
[02:29.46]See you again someday.
Whale in the Milky Way album cover
Whale in the Milky Way · Japanese healing · 20 lines · 164 s.srt
[ti:Whale in the Milky Way]
[ar:Mr Hoelee]
[00:12.10]Ah-ah-ah, ooh-ooh...
[00:15.70]Up above the sleeping town where all the rooftops end
[00:21.86]Swims a giant silver whale that wants to be my friend
[00:27.94]Ripples in the Milky Way are washing on the shore
[00:34.34]Leaving little seashells by my bedroom door
[00:40.98]Can you hear the quiet song echoing in space?
[00:47.28]Every lonely little star has found a hiding place
[00:59.60]Float away, float away, into the velvet blue
[01:06.26]I am sending all my gentle lullabies to you
[01:12.74]Through the clouds of stardust and the galaxies afar
[01:19.59]You are never lost because I see how bright you are
[01:38.82]Paper boats upon the sea of infinite delight
[01:44.56]Carrying our tiny dreams across the quiet night
[01:51.08]Hold my hand and do not fear the deep and silent sky
[01:57.42]We can ride the silver whale and watch the world go by
[02:04.14]Float away, float away, into the velvet blue
[02:10.26]I am sending all my gentle lullabies to you
[02:16.74]Through the clouds of stardust and the galaxies afar
[02:23.52]You are never lost because I see how bright you are
[02:32.74]Goodnight, little star...
Puddle Jumping Parade album cover
Puddle Jumping Parade · Japanese cute · 21 lines · 105 s.srt
[ti:Puddle Jumping Parade]
[ar:Mr Hoelee]
[00:06.76]One, two! Ready, go!
[00:08.68]Put on my yellow boots and grab my red umbrella too
[00:12.30]The rain has stopped and left the sky a shiny, happy blue!
[00:16.08]A giant puddle in the street is looking back at me
[00:20.08]I take a giant running leap—one, two, and three!
[00:23.86]Splash! Goes the water, jumping to the sky
[00:27.66]Even little sparrows stop to watch us marching by!
[00:32.66]Hooray, hooray! Join the happy parade!
[00:36.20]Dancing in the sunshine that the morning made!
[00:40.16]Clap your hands together, stomp your little feet
[00:44.44]Every single puddle makes the melody complete!
[00:49.30]La-la-la, step in time, smiling ear to ear!
[00:56.42]A snail upon the garden wall is waving with its horn
[01:00.10]The brightest, biggest rainbow in the neighborhood is born!
[01:03.90]We'll share a pocketful of sweets and sing a silly tune
[01:07.72]And march around the playground till we reach the afternoon!
[01:13.06]Hooray, hooray! Join the happy parade!
[01:16.24]Dancing in the sunshine that the morning made!
[01:20.12]Clap your hands together, stomp your little feet
[01:23.90]Every single puddle makes the melody complete!
[01:29.20]Jump! Splash! Hooray!
Strawberry Cloud Bakery album cover
Strawberry Cloud Bakery · Japanese cute · 19 lines · 100 s.srt
[ti:Strawberry Cloud Bakery]
[ar:Mr Hoelee]
[00:08.32]Ding-dong rings the little bell above the bakery door
[00:13.48]Flour on the apron and confetti on the floor
[00:16.54]Butter in the mixing bowl and sugar in the pan
[00:20.34]Baking up the fluffiest creations that I can!
[00:24.20]Wait a little minute as the oven starts to glow
[00:29.12]Watch the little loaves of bread begin to rise and grow!
[00:34.04]Welcome to the bakery upon the strawberry cloud!
[00:39.24]Where singing in the kitchen is definitely allowed!
[00:42.76]A croissant for the puppy and a muffin for the cat
[00:46.20]With a dollop of vanilla cream upon a beret hat!
[00:57.82]Pour a cup of warm milk tea and sit beside the window
[01:01.68]Wave hello to everyone walking down below
[01:05.98]If your day is sour like a lemon on a tree
[01:09.78]Take a bite of honey toast and share a smile with me!
[01:13.90]Welcome to the bakery upon the strawberry cloud!
[01:19.26]Where singing in the kitchen is definitely allowed!
[01:22.48]A croissant for the puppy and a muffin for the cat
[01:26.20]With a dollop of vanilla cream upon a beret hat!
[01:33.58]Fresh out of the oven! Yum, yum!
Captain Marshmallow album cover
Captain Marshmallow · Japanese cute · 22 lines · 95 s.srt
[ti:Captain Marshmallow]
[ar:Mr Hoelee]
[00:08.06]Attention please! Captain on the deck!
[00:10.64]Sofa is my pirate ship, the carpet is the sea
[00:13.92]Pillow fort is waiting there for teddy bear and me
[00:17.52]Put a paper triangle upon my curly head
[00:20.96]No one has to take a nap or go to sleep in bed!
[00:25.68]Left turn! Right turn! Watch out for the shark!
[00:31.08]Wait—that's just the fluffy dog barking in the dark!
[00:36.78]Aye, aye, Captain Marshmallow!
[00:38.42]Sailing where the candy breezes blow!
[00:42.04]Cookies in the treasure chest, chocolate on the map
[00:45.56]Give a little salute and a double-double clap! (Clap-clap!)
[00:50.74]We rule the living room today!
[00:56.34]Homework is forbidden by the royal pirate law
[00:59.60]Every single citizen must draw a dinosaur!
[01:03.12]More pudding for the afternoon, and juice inside the cup
[01:07.28]When the clock strikes dinner time, we'll eat the treasure up!
[01:13.80]Aye, aye, Captain Marshmallow!
[01:15.28]Sailing where the candy breezes blow!
[01:19.00]Cookies in the treasure chest, chocolate on the map
[01:22.46]Give a little salute and a double-double clap! (Clap-clap!)
[01:26.82]We rule the living room today!
[01:33.00]Mission accomplished! Yay!
Lanterns on the Lotus Pond album cover
Lanterns on the Lotus Pond · Guofeng fusion · 19 lines · 131 s.srt
[ti:Lanterns on the Lotus Pond]
[ar:Mr Hoelee]
[00:10.69]Patter goes the summer rain upon the lotus leaf
[00:15.29]Washing all the dusty world and bringing cool relief
[00:19.89]Stepping on the wet bluestone beside the willow bridge
[00:24.49]Dragonflies are resting on the painted wooden ridge
[00:28.58]Fold a little paper boat and light a candlewick
[00:33.16]Make a wish before the current carries it so quick
[00:40.46]Floating down the lotus pond, a hundred lanterns glow
[00:46.38]Mirrored in the ripples where the silver fishes go
[00:49.62]Listen to the bamboo flute across the misty stream
[00:54.22]In the courtyard of the moon, we share a summer dream
[01:03.96]Silk fan in my little hand to chase the fireflies
[01:08.72]Red string braided in my hair beneath the lantern skies
[01:13.36]Grandma tells a fairy tale of rabbits in the moon
[01:18.22]While the sweet osmanthus flowers blossom in the June
[01:25.54]Floating down the lotus pond, a hundred lanterns glow
[01:30.02]Mirrored in the ripples where the silver fishes go
[01:34.62]Listen to the bamboo flute across the misty stream
[01:39.36]In the courtyard of the moon, we share a summer dream
[02:06.76]Red lanterns drifting far away...
Wings of the Kunpeng album cover
Wings of the Kunpeng · Guofeng fusion · 19 lines · 213 s.srt
[ti:Wings of the Kunpeng]
[ar:Mr Hoelee]
[00:25.18]Deep beneath the silent waves where no one ever sees
[00:31.60]Sleeps a tiny silver fish dreaming of the breeze
[00:38.16]Counting every falling tear that drops into the tide
[00:44.50]Waiting for the heavy gates of heaven to divide
[00:51.16]Do not fear the rising storm or shadows in the deep
[00:57.24]There is still an ancient promise that the ocean keeps
[01:06.34]Spread your wings and rise above the sea of clouds and rain
[01:13.18]Never let the mortal world bind you with a chain
[01:19.74]Fly across the mountain peaks where immortal rivers flow
[01:25.96]I will watch you turn to wind and let your spirit go
[01:49.10]Cycles of a thousand years are written in the stars
[01:54.96]Time will heal the broken shells and wash away the scars
[02:01.32]When the red camellia blooms upon the snowy shore
[02:07.58]We will meet beyond the sky and part ways nevermore
[02:16.86]Spread your wings and rise above the sea of clouds and rain
[02:23.52]Never let the mortal world bind you with a chain
[02:30.18]Fly across the mountain peaks where immortal rivers flow
[02:36.26]I will watch you turn to wind and let your spirit go
[02:48.84]Ah-ah-ah, fly into the wind...
The Puppeteer's Thread album cover
The Puppeteer's Thread · Guofeng fusion · 19 lines · 221 s.srt
[ti:The Puppeteer's Thread]
[ar:Mr Hoelee]
[00:24.12]Carved from a willow branch, painted with a smile
[00:34.16]Dressed in tiny embroidered silk, traveling mile by mile
[00:46.00]Ten thin threads of crimson silk tied upon my hands
[00:55.50]Dancing in the market square across the distant lands
[01:07.80]Crowds will gather when the gong begins to softly ring
[01:13.12]Laughing at the little doll that cannot speak or sing
[01:21.66]Dance in the lantern light, spin around the stage
[01:26.70]Telling all the legends of a long-forgotten age
[01:32.42]Though my heart is made of wood and cannot feel the rain
[01:37.66]Every pull upon the thread remembers joy and pain
[02:10.68]Autumn leaves are falling down upon the empty street
[02:15.82]Only echoes remain of the applause so sweet
[02:21.36]Keep me in the wooden box beside your warm fireplace
[02:26.98]Even when the paint fades off my little smiling face
[02:36.74]Dance in the lantern light, spin around the stage
[02:42.86]Telling all the legends of a long-forgotten age
[02:48.56]Though my heart is made of wood and cannot feel the rain
[02:54.02]Every pull upon the thread remembers joy and pain
[03:05.04]Ten thin threads of crimson silk...
Paper Airplane in September album cover
Paper Airplane in September · Acoustic folk · 18 lines · 128 s.srt
[ti:Paper Airplane in September]
[ar:Mr Hoelee]
[00:10.42]Sunlight on the wooden desk is moving inch by inch
[00:15.10]Sparrows on the telegraph wire never seem to flinch
[00:20.88]I fold a page of notebook paper creases nice and neat
[00:25.60]And throw it out the window to the quiet autumn street
[00:30.88]Fly away, paper plane, into the golden air
[00:36.36]Carry all the little words I didn't dare to share
[00:41.64]Goodbye to the summer clouds, hello to the breeze
[00:48.72]Floating past the bicycles and underneath the trees
[01:03.30]Chalk dust on the blackboard fades as afternoon goes by
[01:08.38]Clouds like cotton candy drift across the September sky
[01:13.76]Every simple little thing we took for granted then
[01:18.90]Stays inside a photograph we'll look at once again
[01:24.30]Fly away, paper plane, into the golden air
[01:29.66]Carry all the little words I didn't dare to share
[01:34.90]Goodbye to the summer clouds, hello to the breeze
[01:41.68]Floating past the bicycles and underneath the trees
[01:57.78]Underneath the autumn trees...
[02:02.18]Goodbye, summer days.
Porridge and Evening Smoke album cover
Porridge and Evening Smoke · Acoustic folk · 17 lines · 144 s.srt
[ti:Porridge and Evening Smoke]
[ar:Mr Hoelee]
[00:11.54]Smoke is rising from the roof into the purple sky
[00:17.04]While the evening swallows call and hurry on up high
[00:22.84]Steam upon the kitchen glass is blurring out the view
[00:28.48]Sitting on a wooden stool, I wait for dinner too
[00:34.02]One bowl of warm white rice, a dish of tender greens
[00:39.52]The simplest kind of happiness is what the evening means
[00:45.42]No matter how the outside world is noisy, cold, and wide
[00:50.98]The lamp upon the dining table keeps us warm inside
[01:09.84]Wrinkles on a gentle hand that smooths my messy hair
[01:14.88]Telling me to eat it all and sit up in my chair
[01:20.48]Years will pass like river water flowing to the sea
[01:26.26]But this quiet kitchen light will always stay with me
[01:33.04]One bowl of warm white rice, a dish of tender greens
[01:38.76]The simplest kind of happiness is what the evening means
[01:44.60]No matter how the outside world is noisy, cold, and wide
[01:50.14]The lamp upon the dining table keeps us warm inside
[01:57.40]The lamp is always on for you...
Green Train to the Sea album cover
Green Train to the Sea · Acoustic folk · 17 lines · 108 s.srt
[ti:Green Train to the Sea]
[ar:Mr Hoelee]
[00:10.84]Clickety-clack upon the track, the green train starts to roll
[00:14.28]Leaving all the city gray behind the tunnel hole
[00:19.42]Forehead pressed against the glass, I watch the fields go by
[00:24.20]Golden wheat and windmills waving underneath the sky
[00:28.38]Take me where the spring wind blows across the open blue
[00:33.78]Ten miles of wildflowers blooming just for me and you
[00:38.82]Every station has a name I've never heard before
[00:43.46]Soon the scent of salty air will meet us at the shore
[00:57.42]Strangers sharing oranges and stories in the seat
[01:02.46]Sunlight dancing in the aisle around my dangling feet
[01:07.48]Postcards in my backpack waiting for a stamp and pen
[01:11.50]To tell the people back at home I'm coming back again
[01:16.22]Take me where the spring wind blows across the open blue
[01:21.52]Ten miles of wildflowers blooming just for me and you
[01:26.80]Every station has a name I've never heard before
[01:31.40]Soon the scent of salty air will meet us at the shore
[01:46.20]Look, there is the sea...
Sanctuary of the Dawn album cover
Sanctuary of the Dawn · Choral · 19 lines · 182 s.srt
[ti:Sanctuary of the Dawn]
[ar:Mr Hoelee]
[00:22.82]Ahh-ahh, sanctus, ahh...
[00:25.64]Shadows fade before the light that rises in the east
[00:31.74]Every troubled storm is stilled and every sorrow ceased
[00:37.76]Through the tall stained-glass windows morning beams descend
[00:44.12]Shining on a quiet road where broken hearts can mend
[00:50.56]Peace be with you, weary soul, lay your burden down
[00:58.74]Where the silver rivers flow beyond the sleeping town
[01:05.08]Lift your eyes unto the hills where golden angels sing
[01:11.46]Rest beneath the gentle shelter of a shining wing
[01:21.16]Like a bell across the valley ringing clear and true
[01:27.18]Every dawn is bringing back a promise made anew
[01:34.18]Walk into the quiet light and leave the dark behind
[01:40.06]There is grace in every breath for all of humankind
[01:48.40]Peace be with you, weary soul, lay your burden down
[01:54.64]Where the silver rivers flow beyond the sleeping town
[02:01.02]Lift your eyes unto the hills where golden angels sing
[02:07.48]Rest beneath the gentle shelter of a shining wing
[02:15.30]Peace be with you... forevermore.
[02:26.48]Amen, ahh...
Look Upon Your Path album cover
Look Upon Your Path · Choral · 17 lines · 122 s.srt
[ti:Look Upon Your Path]
[ar:Mr Hoelee]
[00:09.64]Look upon the winding path where fallen leaves are blown
[00:14.64]Children walking hand in hand so no one is alone
[00:19.64]Even when the winter wind is cold against your face
[00:25.04]Every step you take today is leading to a place
[00:31.52]Shine your light into the dark, let your voice be heard
[00:36.60]Rising like the morning lark, a brave and little bird
[00:41.60]Though the night is long and deep, the stars are watching still
[00:46.68]Spring will wake the seeds asleep upon the quiet hill
[00:57.00]Write a song upon the wind for everyone who strays
[01:02.16]Hope is like a tiny spark that sets the sky ablaze
[01:07.48]Hold the hand beside you tight and never look below
[01:11.88]There are gardens waiting where the wildest rivers flow
[01:21.30]Shine your light into the dark, let your voice be heard
[01:26.36]Rising like the morning lark, a brave and little bird
[01:31.34]Though the night is long and deep, the stars are watching still
[01:36.44]Spring will wake the seeds asleep upon the quiet hill
[01:45.98]Look upon your path... the dawn is near.
Bells of the Winter Star album cover
Bells of the Winter Star · Choral · 18 lines · 177 s.srt
[ti:Bells of the Winter Star]
[ar:Mr Hoelee]
[00:08.50]Ding-dong, ding-dong, ring out the bells...
[00:18.20]Snowflakes falling from the sky in silence pure and white
[00:25.44]Dressing every cedar bough in robes of silver light
[00:34.56]Listen to the steeple bells across the frozen square
[00:43.42]Sending out a melody upon the midnight air
[00:52.92]Ring, silver bells, across the winter snow
[01:01.30]Tell all the world the star has begun to glow
[01:11.76]Gloria, gloria, hear the angels sing
[01:19.28]Peace on the earth this holy night will bring
[01:32.12]Candles in the frosted glass are shining warm and clear
[01:40.42]Guiding every traveler home at the end of year
[01:49.68]Every chime is like a prayer ascending to the sky
[01:58.26]Watched by all the quiet stars that never pass us by
[02:09.62]Ring, silver bells, across the winter snow
[02:18.22]Tell all the world the star has begun to glow
[02:28.00]Gloria, gloria, hear the angels sing
[02:37.14]Peace on the earth this holy night will bring
[02:49.30]Gloria... peace on the earth.
<script> // subs-track: scroll LRC in step with ; current line stays centred document.querySelectorAll('audio[data-lrc]').forEach((audio) => { const raw = document.getElementById(audio.dataset.lrc).textContent; const lines = raw.split('\n').map((l) => { const m = l.match(/\[(\d+):(\d+)(?:\.(\d+))?\](.*)/); return m ? { t: +m[1] * 60 + +m[2] + (+(m[3] || '0')) / 100, txt: m[4] } : null; }).filter(Boolean); const box = document.createElement('div'); box.className = 'subs-box'; lines.forEach((l) => { const p = document.createElement('p'); p.textContent = l.txt; box.appendChild(p); }); audio.parentNode.insertBefore(box, audio.nextSibling); let cur = -1; audio.addEventListener('timeupdate', () => { const now = audio.currentTime; // last line whose timestamp has passed; -1 before the first line starts let i = -1; for (let k = 0; k < lines.length; k++) { if (lines[k].t <= now) i = k; else break; } if (i !== cur) { if (cur >= 0) box.children[cur].classList.remove('on'); cur = i; if (cur >= 0) { const p = box.children[cur]; p.classList.add('on'); const br = box.getBoundingClientRect(), pr = p.getBoundingClientRect(); box.scrollTop += (pr.top - br.top) - (box.clientHeight - pr.height) / 2; } else { box.scrollTop = 0; } } }); }); </script>