某些歌词显示与演唱对不上时,可以方便使用。之前为了编辑一下歌词,度娘了好久都没有一款合适的编辑器,然后查找appstore,每款好用的基本上都需要收费,github, gitee都翻了没有找到合适的。
于是我和AI一起搞了一个歌词编辑器: vue-lrc-editor。
特性
- ✅ 本地播放 — 音频文件通过
URL.createObjectURL加载,不上传服务器 - ✅ 进度拖拽 — 音频播放进度条,实时同步当前时间
- ✅ 逐行打点 — 播放到对应位置时一键插入
[mm:ss.xx],支持自动跳到下一行连续打点 - ✅ 时间戳可编辑 — 点击时间标签可直接修改分 / 秒 / 厘秒,失焦或回车保存,Esc 取消
- ✅ 一行多时间 — 同一行可添加多个播放时间戳,自动按时间排序
- ✅ 歌词编辑 — 添加 / 编辑 / 删除歌词行,textarea 自适应高度,未选中时也能读完整行
- ✅ 点击选中 — 点击任意行即选中该行(整行卡片均为可点击区域)
- ✅ 上 / 下插入空行 — 在任意行上方或下方快速插入空行
- ✅ 行排序 — 上下移动调整歌词顺序
- ✅ 文本导入 — 粘贴多行文本,按行批量生成歌词(覆盖模式)
- ✅ LRC 导入 / 导出 — 支持标准 LRC 格式(含元数据
ti/ar/al/offset) - ✅ 查看 LRC 输出 — 底部工具栏一键弹窗预览导出内容,支持复制
- ✅ 实时高亮 — 播放时自动高亮当前歌词行
- ✅ 美化界面 — 基于 Element Plus + Tailwind CSS,开箱即用
环境要求
本库以 peerDependency 形式依赖以下包,请确保你的项目已安装:
| 包 | 最低版本 |
|---|---|
vue | ^3.3.0 |
element-plus | ^2.14.0 |
@element-plus/icons-vue | ^2.3.2 |
安装
若你的项目尚未安装上述 peerDependency:
npm install快速开始
组件内部使用了 Element Plus 及其图标,因此除本库样式外,还需引入 Element Plus 自带样式(图标包无需手动注册,组件内部已按需引入)。
<script setup lang="ts">
import { LrcEditor } from 'vue-lrc-editor'
import 'vue-lrc-editor/dist/style.css' // 本库样式(Tailwind 编译产物)
import 'element-plus/dist/index.css' // Element Plus 组件样式(peerDependency)
</script>
<template>
<!-- 容器需有明确高度,编辑器会撑满父级 -->
<div class="h-screen">
<LrcEditor />
</div>
</template>组件 API
LrcEditor(推荐入口)
集成了音频播放与歌词编辑的完整编辑器,开箱即用。
Props:无。
通过 ref 暴露的方法:
| 方法 | 返回 | 说明 |
|---|---|---|
exportLrc() | string | 导出 LRC 格式字符串 |
parseLrc(text) | LyricData | 解析 LRC 文本为结构化数据 |
importText(text) | number | 按行导入纯文本歌词,返回新增行数 |
getMeta() | LrcMetaData | 获取元数据 |
getLines() | LrcLine[] | 获取全部歌词行 |
getSelectedLine() | LrcLine | null | 获取当前选中行 |
<script setup lang="ts">
import { ref } from 'vue'
import { LrcEditor } from 'vue-lrc-editor'
const editorRef = ref<InstanceType<typeof LrcEditor>>()
function viewOutput() {
console.log(editorRef.value?.exportLrc())
}
</script>
<template>
<LrcEditor ref="editorRef" />
</template>AudioPlayer
音频加载与播放控制面板。
Props:
| 名称 | 类型 | 说明 |
|---|---|---|
selectedLine | LrcLine | null | 当前选中行,用于「插入时间」按钮定位目标行 |
Emits:
| 事件 | 参数 | 说明 |
|---|---|---|
audio-loaded | file: File | 选择音频文件后触发 |
time-update | time: number | 播放进度更新(每 100ms) |
select-line | line: LrcLine | 请求选中某行 |
insert-time | line, time | 在指定行、指定时间插入时间戳 |
暴露:state、togglePlay、seekTo、setVolume、insertCurrentTime
LyricList
歌词列表与底部工具栏(添加行 / 文本导入 / 导入 LRC / 查看 LRC 输出 / 导出 LRC)。
Props:
| 名称 | 类型 | 说明 |
|---|---|---|
songName | string | 导出文件名(缺省回退到 LRC 标题 / lyrics) |
Emits:
| 事件 | 参数 | 说明 |
|---|---|---|
need-current-time | lineId: string | 单行请求插入当前播放时间,由父组件提供 |
暴露:setActiveLine、selectLine、scrollLineIntoView、getSelectedLine、meta、lines、selectedId、insertTimeStamp、addLineAt、exportLrc、parseLrc、importText、clear
LyricLine
单行歌词卡片(通常由 LyricList 内部渲染,也可单独使用)。
Props:index、text、stamps、isSelected、isActive
Emits:update:text、select、delete、move('up'|'down')、insert-stamp、delete-stamp(uid)、update-stamp(uid, seconds)、insert-above、insert-below
Composables
useLyrics()
歌词数据与操作的响应式核心。
const {
meta, // Ref<LrcMetaData>
lines, // Ref<LrcLine[]>
selectedId, // Ref<string>
addLine, // (text?, timeStamp?) => LrcLine
addLineAt, // (relativeId, 'before'|'after') => LrcLine | null
deleteLine, // (id) => void
moveLine, // (id, 'up'|'down') => void
insertTimeStamp, // (lineId, seconds) => void
deleteTimeStamp, // (lineId, uid) => void
updateTimeStamp, // (lineId, uid, seconds) => void —— 修改并自动重排
exportLrc, // () => string
parseLrc, // (text) => LyricData
importText, // (text) => number
clear // () => void
} = useLyrics()useAudio()
音频播放 composable,纯前端,文件不上传服务器。
const {
state, // Ref<AudioState>:{ playing, currentTime, duration, volume, fileName }
loadFile, // (file: File) => void
play, // () => void
pause, // () => void
togglePlay, // () => void
seekTo, // (sec) => void
setVolume, // (vol) => void
onTimeUpdate // Ref<(time: number) => void> —— 设置后随播放进度回调,用于高亮当前行
} = useAudio()
类型定义
interface LrcTimeStamp {
seconds: number; // 时间(秒,精确到小数点后 2 位)
uid: string; // 唯一标识(区分同一行的多个时间戳)
}
interface LrcLine {
id: string;
text: string;
stamps: LrcTimeStamp[]; // 一个行可以有多个时间戳
order: number; // 排序序号
}
interface LrcMetaData {
title?: string; // [ti:xxx]
artist?: string; // [ar:xxx]
album?: string; // [al:xxx]
offset?: number; // [offset:xxx]
}
interface LyricData {
meta: LrcMetaData;
lines: LrcLine[];
}
以上类型及工具函数 fmtTime / parseTimeStr 均从包入口导出,可直接 import 使用。
LRC 格式示例
[ti:歌曲名]
[ar:歌手]
[al:专辑]
[offset:0]
[00:00.00]第一句歌词
[00:05.00][00:08.00]同一行两个时间戳
[00:12.00]第三句编辑器交互说明
- 逐行打点:选中一行 → 播放音频 → 唱到该句时点「插入时间」,时间戳落到当前选中行并自动跳到下一行,连续打点无需手动换行。
- 编辑时间戳:点击行内的
[mm:ss.xx]标签,进入分 / 秒 / 厘秒三段编辑;输满两位自动跳到下一段,Enter或失焦保存(自动钳制到合法范围),Esc取消;标签右侧×删除该时间戳。 - 行操作:鼠标悬停行卡片右侧出现操作组 —— 插入当前播放时间、上方 / 下方插入空行、上移、下移、删除。
- 点击选中:点击行卡片任意位置即选中该行。
- 查看 LRC 输出:底部工具栏点「查看 LRC 输出」弹窗预览导出内容,支持一键复制(「导出 LRC」则直接下载
.lrc文件)。 - 文本导入:点「文本导入」展开输入框,每行一句,点「按行导入」以覆盖模式生成歌词。
开发
npm install
npm run dev # 开发预览(localhost:5173)
npm run typecheck # 仅类型检查(vue-tsc --noEmit)
npm run build # 构建发布产物(vue-tsc 类型检查 + vite 库构建,输出到 dist/)
npm run build:html # 单文件 HTML:把 dev 预览内联成单个 html/index.html,双击即可打开- 库构建(
npm run build)输出 UMD / ESM 产物及样式到dist/,供 npm 消费。 - 单文件构建(
npm run build:html)将 vue / element-plus / 图标 / 源码 / 样式全部内联进一个独立index.html,零外部依赖,便于离线分发或演示。
