Closed FantasyKingdom closed 5 months ago
你可以提供下视频片段让我来测试下吗? 我的代码里面的这一段,正常来说就可以用当前的时间来为上一个字幕设置结束时间的。
if let preSubtitleFrame, preSubtitleFrame.part.end == preSubtitleFrame.part.start {
preSubtitleFrame.part.end = start
}
我在main分支,修复这个问题了。你可以试下。其实是因为这个字幕会输出两个时间片段一摸一样的字幕片段。我加了一个判断,把它过滤掉了。这样preSubtitleFrame就起作用了。
你的修改并没有解决问题。 解码出来的字幕不是严格的时间顺序的 所以后一个字幕的start时间可能比前面一条字幕的start还要小,导致end设置了一个比start小的值,这时如果没有新的空字幕,而只依赖上述的第二段代码是无法清除掉当前字幕的。我提交的代码可以解决这个问题。
图中的xxxx是SubtitleDecode中的字幕start时间。 当前已经播放到22秒了,仍显示12.47的字幕
12.513和12.512是两条无内容的字幕。 因为12.471这条字幕的end值已经被设置为了12.47。所以不会更新它的end值。 导致12.471这条字幕一直被显示。
不好意思。因为那个url播放太卡了。所以我是通过ffmpeg来下载一分钟的片段进行测试。ffmpeg对于下载下来的字幕时间戳应该是有做了重新矫正。所以我本地只要用等于进行判断就不会有问题了。但是线上的url是要用>=来进行判断。我改好了。麻烦你在试下。
这样改虽然可以解决这个问题,但是我感觉某些情况下会把一部分正常的字幕给漏掉了。
我觉得就不应该使用preSubtitleFrame这个对象,可以去掉,而是将解码出来的空字幕放到字幕的缓冲区会比较好,像第一个评论说的那样。当然,这仅是我自己的看法。
可以试着把preSubtitleFrame给去掉。但是对于开始时间和结束时间一样的字幕。还是需要item.part < time或者是part.end <= part.start来进行判断,不能直接用一个固定的长度 5s。不然对于文字字幕的话,那有可能在某个时间段同时显示两个文字字幕。
我把preSubtitleFrame去掉了,然后这样改从逻辑上应该是没有你说的这个问题的
嗯,你这样改是可以的。而且如果是空字幕应该不需要返回一个空的字幕了。因为之前是有item.part < time 这个判断,所以才可以返回空字幕进行清空。现在是根据 item.part == time来判断了。空字幕应该是无法返回了。你可以去掉这个代码试下。应该也是没有问题的。
即使是空字幕,也是有设置时间的,把它当作正常字幕即可,只是无内容。 按照我的这种改法那parts.append(SubtitlePart(0, 0, attributedString: nil))这一句是不能少的。
嗯,我按照你的思路改好了。你的思路确实更好。返回一个空字幕是一个正确的方式。这样才能解决字幕解码不按顺序的问题。你可以试下
是的,这样改就没问题了。既能解决字幕重复字幕及乱序问题,而且整体逻辑也更加清晰了。之前的各种<=判断在第一次看代码的时候真的很让人迷惑😄。
有时候解码出字幕,但是字幕无内容也需要及时刷新。 不然会出现人物已经很久没说话了,但是字幕却一直显示的问题。
这个修改主要是用来处理preSubtitleFrame.part.end == preSubtitleFrame.part.start的这种没有持续时间的字幕,可以再加一个preSubtitleFrame.part.end == preSubtitleFrame.part.start判断,不加其实也没有影响。
题外话: 第一段代码 extension FFmpegAssetTrack: KSSubtitleProtocol { public func search(for time: TimeInterval) -> [SubtitlePart] { subtitle?.outputRenderQueue.search { item -> Bool in item.part < time || item.part == time }.map(.part) ?? [] } } 第二段代码: if let subtile = selectedSubtitleInfo { let currentTime = currentTime - subtile.delay - subtitleDelay newParts = subtile.search(for: currentTime) if newParts.isEmpty { newParts = parts.filter { part in part.end <= part.start || part == currentTime } } }
我觉得对于那种没有duration的字幕,视频文件中应该会提供一个空字幕来进行清除(我提交的这段代码)。 可以把duration设置为无限长或者长一点的时间比如5秒,然后用空字幕进行清除。 而不用像第一段代码和第二段代码那样去判断item.part < time或者是part.end <= part.start。以及preSubtitleFrame这个都可以去掉了。