关于海南鸡饭字幕时间轴不准的解决方法
发现ai的时间轴的开始阶段都比较准确,不准确主要在于结束阶段,造成很多字幕停留时间过长,或者有些字幕停留时间过短,一闪而过找deepseek给我编了一段c++代码,这几天没时间,等有空的时候,我编译一个小软件测试一下dp的编程水平
把代码贴出来,给大家参考,会编码的同学可以自己拿过去玩玩
请编写一段c++代码
给定一个电影的字幕文件
1、打开字幕文件
2、编辑字幕文件,将字幕文件的显示时间设为如下要求
如果单条字幕显示时间短于2秒,则将字幕显示时间设定为3秒
如果单条字幕显示时间长于5秒,则将字幕显示时间定为5秒
3、完成后关闭文件
我们需编写C++代码处理字幕文件(.srt格式),要求:对于每条字幕,计算其显示时长(结束时间 - 开始时间)。如果时长 < 2秒,则调整结束时间使得时长为3秒;如果时长 > 5秒,则调整结束时间使得时长为5秒。保持开始时间不变,只修改结束时间。需注意毫秒精度。
实现步骤:
打开字幕文件,逐行读取,识别时间行(格式:HH:MM:SS,mmm --> HH:MM:SS,mmm)。
解析开始时间和结束时间,计算当前时长(毫秒)。
根据规则计算新结束时间:若时长<2000ms,新结束=开始+3000ms;若时长>5000ms,新结束=开始+5000ms;否则不变。
将修改后的时间行写回,其他行(序号、文本、空行)原样保留。
输出到新文件或覆盖原文件(这里可覆盖原文件,但建议备份或写新文件)。本代码将结果写回原文件(先读入内存再写回)。
注意处理边界:字幕时间可能跨小时,但计算方法正确。
代码将包含必要头文件、时间解析/格式化函数、主逻辑。
以下 C++ 代码实现了对 SRT 字幕文件的时间调整功能:若字幕显示时长不足 2 秒,则延长至 3 秒;若超过 5 秒,则缩短至 5 秒;其余情况保持不变。
cpp
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <regex>
#include <iomanip>
#include <sstream>
// 时间结构体:时、分、秒、毫秒
struct Time {
int h, m, s, ms;
};
// 解析 "HH:MM:SS,mmm" 字符串为 Time 结构
Time parseTime(const std::string& timeStr) {
Time t;
char comma;
std::stringstream ss(timeStr);
ss >> t.h >> comma >> t.m >> comma >> t.s >> comma >> t.ms;
return t;
}
// 将 Time 结构格式化为 "HH:MM:SS,mmm"
std::string formatTime(const Time& t) {
std::stringstream ss;
ss << std::setw(2) << std::setfill('0') << t.h << ":"
<< std::setw(2) << std::setfill('0') << t.m << ":"
<< std::setw(2) << std::setfill('0') << t.s << ","
<< std::setw(3) << std::setfill('0') << t.ms;
return ss.str();
}
// 将 Time 转换为毫秒数(从 0 开始)
int timeToMillis(const Time& t) {
return ((t.h * 60 + t.m) * 60 + t.s) * 1000 + t.ms;
}
// 将毫秒数转换为 Time 结构(自动规整小时)
Time millisToTime(int totalMs) {
Time t;
t.h = totalMs / 3600000;
totalMs %= 3600000;
t.m = totalMs / 60000;
totalMs %= 60000;
t.s = totalMs / 1000;
t.ms = totalMs % 1000;
return t;
}
// 调整字幕时间行:根据规则修改结束时间
// 参数:原始开始时间、原始结束时间
// 返回:新的时间行字符串
std::string adjustTimeLine(const std::string& startStr, const std::string& endStr) {
Time start = parseTime(startStr);
Time end = parseTime(endStr);
int startMs = timeToMillis(start);
int endMs = timeToMillis(end);
int duration = endMs - startMs;
int newEndMs = endMs;
if (duration < 2000) { // 小于2秒 -> 设为3秒
newEndMs = startMs + 3000;
} else if (duration > 5000) { // 大于5秒 -> 设为5秒
newEndMs = startMs + 5000;
}
Time newEnd = millisToTime(newEndMs);
return formatTime(start) + " --> " + formatTime(newEnd);
}
// 处理字幕文件
bool processSubtitleFile(const std::string& filename) {
std::ifstream inFile(filename);
if (!inFile.is_open()) {
std::cerr << "错误:无法打开文件 " << filename << std::endl;
return false;
}
std::vector<std::string> outputLines;
std::string line;
// 匹配时间行的正则表达式:HH:MM:SS,mmm --> HH:MM:SS,mmm
std::regex timePattern(R"((\d{2}:\d{2}:\d{2},\d{3})\s*-->\s*(\d{2}:\d{2}:\d{2},\d{3}))");
while (std::getline(inFile, line)) {
std::smatch match;
if (std::regex_match(line, match, timePattern)) {
// 是时间行,进行修改
std::string start = match;
std::string end = match;
std::string newTimeLine = adjustTimeLine(start, end);
outputLines.push_back(newTimeLine);
} else {
// 其他行(序号、字幕文本、空行)原样保留
outputLines.push_back(line);
}
}
inFile.close();
// 将修改后的内容写回原文件(覆盖)
std::ofstream outFile(filename);
if (!outFile.is_open()) {
std::cerr << "错误:无法写入文件 " << filename << std::endl;
return false;
}
for (const auto& l : outputLines) {
outFile << l << '\n';
}
outFile.close();
return true;
}
int main() {
std::string filename = "subtitle.srt";// 请替换为实际字幕文件路径
if (processSubtitleFile(filename)) {
std::cout << "字幕文件处理成功!所有显示时间已按要求调整。\n";
} else {
std::cerr << "处理失败。\n";
return 1;
}
return 0;
}
代码说明
时间解析与格式化
parseTime:将 HH:MM:SS,mmm 字符串转换为结构体。
formatTime:反向转换,保证两位时、分、秒和三位毫秒。
timeToMillis / millisToTime:用于方便地计算时间差和生成新结束时间。
核心调整函数 adjustTimeLine
计算原始显示时长(毫秒)。
若时长 < 2000ms → 新结束 = 开始 + 3000ms。
若时长 > 5000ms → 新结束 = 开始 + 5000ms。
否则保持原结束时间不变。
返回修改后的时间行字符串。
文件处理流程
使用正则表达式识别时间行(匹配形如 00:01:23,456 --> 00:01:25,789 的行)。
其他行(序号、字幕文本、空行)原样保留。
将所有行存入 vector,处理完成后重新写入原文件(覆盖)。
使用方法
将代码中的 filename 修改为您的字幕文件路径(例如 "movie.srt")。
编译(需支持 C++11 或更高版本):
bash
g++ -std=c++11 adjust_subtitle.cpp -o adjust_subtitle
运行:
bash
./adjust_subtitle 如果只是根据临界值修改字幕显示时间,其实用py脚本会更简单 本帖最后由 daral331 于 2026-4-6 07:54 编辑
楼主,根据我的观测,应该是:若时长 > 5000ms → 新结束 = 结束 - 5000ms。比较准确
但是我们不会编程的就很难看懂了
这个功能我也做了个类似的,是根据单条字幕字数判断的,并且把海南鸡饭里面有时候大量出现的重复文字简化了。
缺点也很明显,海南鸡饭有时候断句没做好,一条字幕可能是跨了好几段话,会导致后面说话的时候字幕已经结束了。 jushuwumiao 发表于 2026-4-7 10:18
这个功能我也做了个类似的,是根据单条字幕字数判断的,并且把海南鸡饭里面有时候大量出现的重复文字简化了 ...
海南鸡饭的配置文件有一个关于重复字幕合并的选项,你把两条字幕之间的间隔时间缩短会好很多,默认间隔是20秒 jacky56 发表于 2026-4-7 15:40
海南鸡饭的配置文件有一个关于重复字幕合并的选项,你把两条字幕之间的间隔时间缩短会好很多,默认间隔是 ...
感谢,回头试一下
页:
[1]