1308351.png

浮霄

GF  2024-03-31 22:09
(音声当然得笑着去听啦 >-<  愿你永葆那份欢愉)

关于在手机上把音声的vtt字幕转换成lrc歌词的解决办法【附代码】

不知道大家伙儿有没有遇到过下载了论坛大佬自购的官中字幕音声,却无法被主流音乐播放器识别的情况。反正这种情况我已经遇到了不止一次了,而且绝大多数情况都是被VTT格式的字幕文件给卡住。究其原因,主要还是购买完音声后,DLsite想让你在网站上听,所以就连“大家一起来翻译”提供的网页打轴工具生成的都是浏览器能够识别的字幕文件格式,即VTT。
引用
VTT格式的文件通常用于在Web上显示文本轨道,如字幕或歌词,主要是主流浏览器和视频播放器可以识别;而LRC格式的文件则是主要用于显示逐行对应歌曲的歌词文本,主要是音乐播放器可以识别。

之前遇到这种情况,无论是用一些在线转换格式的网站还是某些大佬自己写的批处理转换文件或者subtitle edit自带的另存为转换功能,其实忍忍也就过去了,结果今天在手机上下了一部葵姐的官中音声,又TM出现了这个逼问题,正巧赶上家里断电修灯,没办法开电脑处理。
md,这次忍不了,和你爆了,就是为了方便才用手机听音声,结果搞得次次还得开电脑,烦死了。最终我在极度郁闷的情况下自己搓了一个python脚本,实现了vtt批量转lrc的功能,同时也避免了转换出来的文件名多带一个".wav"的坑爹问题。这下只要在手机上装一个自带python运行环境的应用,就可以用手机实现字幕转换了。
具体的使用方法我打包放在压缩包里了,需要的自己下载。这里把顺便代码贴出来:
复制代码
  1. # 作者:浮霄默客
  2. # 日期:2024.4.5
  3. # 描述:将VTT格式的文件转换为LRC格式
  4. import os  # 导入操作系统模块
  5. import re  # 导入正则表达式模块
  6. # 去除多余的扩展名
  7. def extract_filename_without_extensions(input_file):
  8.     # 将输入文件名按照点分割成部分
  9.     file_parts = input_file.split('.')
  10.     # 初始化文件名部分列表,第一个部分始终是文件名的一部分
  11.     file_name_parts = [file_parts[0]]
  12.     # 已知的扩展名列表
  13.     known_extensions = {
  14.         'mp3', 'wav', 'acc', 'flac',
  15.         'MP3', 'WAV', 'ACC', 'FLAC',
  16.         'vtt', 'srt', 'lrc', 'VTT',
  17.         'SRT', 'LRC'
  18.     }
  19.     # 从第二个元素开始遍历文件名的各部分
  20.     for part in file_parts[1:]:
  21.         # 如果部分是已知扩展名则结束循环
  22.         if part in known_extensions:
  23.             break
  24.         # 将非扩展名部分添加到文件名部分列表中
  25.         file_name_parts.append(part)
  26.     
  27.     # 重建文件名,忽略扩展名
  28.     file_name = '.'.join(file_name_parts)
  29.     return file_name
  30. # 将VTT文件转换为LRC格式
  31. def convert_vtt_to_lrc(input_file, output_file):
  32.     with open(input_file, 'r', encoding='utf-8') as vtt_file:
  33.         lines = vtt_file.readlines()  # 读取VTT文件的所有行
  34.     lrc_lines = []  # 存储转换后的LRC行
  35.     start_time = ""  # 初始化起始时间
  36.     end_time = ""  # 初始化结束时间
  37.     count = 1  # 初始化计数器,从1开始
  38.     subtitle_marker_exists = False  # 标记是否已经存在字幕标记
  39.     subtitle_add = "" #存储单行或多行字幕
  40.     
  41.     for line in lines:  # 遍历VTT文件的每一行
  42.         line = line.strip()  # 去除行两端的空白字符
  43.         if re.match(r'\d{2}:\d{2}:\d{2}\.\d{3} --> \d{2}:\d{2}:\d{2}\.\d{3}', line):
  44.             # 如果是时间戳行
  45.             # 添加上一个格式化后的内容到LRC行列表
  46.             if count != 1:
  47.                 lrc_lines.append(f"{start_time}{subtitle_add}\n{end_time}\n")  
  48.                 subtitle_add = "" #清空字幕存储单元
  49.             times = re.findall(r'(\d{2}):(\d{2}):(\d{2})\.(\d{3})', line)  # 提取时间信息
  50.             # 格式化起始时间
  51.             start_time = f"[{int(times[0][0])*60 + int(times[0][1]):02}:{times[0][2]}.{int(round(int(times[0][3]) / 10)):02}]"
  52.             # 格式化结束时间  
  53.             end_time = f"[{int(times[1][0])*60 + int(times[1][1]):02}:{times[1][2]}.{int(round(int(times[1][3]) / 10)):02}]"  
  54.             count += 1  # 计数器加1
  55.         elif line.isnumeric():
  56.             # 如果是纯数字行
  57.             if count == int(line) and not subtitle_marker_exists:
  58.                 subtitle_marker_exists = True #字幕数标已读取,标志置真
  59.                 continue  # 如果是数标,跳过该行
  60.             else:
  61.                 #处理纯数字字幕行
  62.                 subtitle_add += str(line) + " "
  63.                 subtitle_marker_exists = False  # 重置字幕标记
  64.         elif not line:
  65.             # 如果是空行,跳过
  66.             continue
  67.         else:
  68.             # 处理字幕行
  69.             if start_time and end_time:
  70.                 subtitle_add += str(line) + " "
  71.                 subtitle_marker_exists = False  # 重置字幕标记
  72.     # 添加最后一个格式化后的内容到LRC行列表
  73.     lrc_lines.append(f"{start_time}{subtitle_add}\n{end_time}\n")
  74.     #获取转换文件的文件名
  75.     file_name = extract_filename_without_extensions(input_file)
  76.     #生成LRC文件路径
  77.     lrc_file_name = file_name + ".lrc"
  78.     with open(lrc_file_name, 'w', encoding='utf-8') as lrc_file_obj:
  79.         lrc_file_name_str = str(lrc_file_obj.name)  # 获取LRC文件名
  80.         lrc_file_obj.write(f"[ti:{lrc_file_name_str}]\n")  # 写入标题信息
  81.         lrc_file_obj.write("[by: 浮霄默客]\n")  # 写入作者信息
  82.         for lrc_line in lrc_lines:
  83.             lrc_file_obj.write(lrc_line)  # 写入每行LRC内容
  84.     print(f"文件转换完成:{input_file} -> {lrc_file_name_str}")  # 打印转换完成信息
  85. vtt_files = [file for file in os.listdir() if file.endswith(".vtt")]  # 获取所有VTT文件
  86. for vtt_file in vtt_files:  # 遍历每个VTT文件
  87.     convert_vtt_to_lrc(vtt_file, "")  # 转换为LRC格式

后续更新内容请移步
关于手机转换音声字幕格式的后续【工具分享】

此帖售价 0 SP币,已有 134 人购买
若发现会员采用欺骗的方法获取财富,请立刻举报,我们会对会员处以2-N倍的罚金,严重者封掉ID!


2024.4.1 修改了部分代码,解决了遇到纯数字行时(比如倒计时)的字幕错误。
2024.4.1 简化部分代码。同时把脚本打包成了exe可执行文件,pc端不需要安装python环境就能完成转换了。
2024.4.2 修改部分逻辑,解决了遇到多行字幕时的字幕错误。
2024.4.4 增加去扩展名函数。解决了文件名中包含"."导致的命名错误问题。
2024.4.5 更新了扩展名列表。

none.gif

xpc

大佬nb,已经用上了
之前要听汉化还要挨个用网页工具转格式再重命名,都要红温了

w1Gl44.jpg

无语

B2F  2024-03-31 22:19
(crazys无语)
大佬NB

404


yagami.png

夜神月

牛的牛的

none.gif

yoyami

B5F  2024-03-31 22:31
(yoyami)
GitHub上有个开源项目subtitleedit,专门处理字幕类型的文件
https://github.com/SubtitleEdit/subtitleedit

1308351.png

浮霄

B6F  2024-03-31 22:37
(音声当然得笑着去听啦 >-<  愿你永葆那份欢愉)

回 5楼(yoyami) 的帖子

subtitle edit平时打轴一直在用的,这次主要是不想开电脑了。

1308351.png

浮霄

B7F  2024-04-01 11:59
(音声当然得笑着去听啦 >-<  愿你永葆那份欢愉)
4.1更新:对代码做了一定的优化和修改,同时降低了pc端的使用难度,请使用修改后的版本。

莉莉丝的脐

B8F  2024-04-01 12:30
        

1308351.png

浮霄

B9F  2024-04-03 21:34
(音声当然得笑着去听啦 >-<  愿你永葆那份欢愉)

2050563.png

凛遥咲

大佬牛的 感谢分享

讯风


none.gif

0a8763bb

感谢分享

sadsad8964