Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

修复字幕未及时清除的问题 #774

Closed
wants to merge 2 commits into from

Conversation

FantasyKingdom
Copy link
Contributor

@FantasyKingdom FantasyKingdom commented Apr 20, 2024

有时候解码出字幕,但是字幕无内容也需要及时刷新。
不然会出现人物已经很久没说话了,但是字幕却一直显示的问题。

这个修改主要是用来处理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这个都可以去掉了。

@kingslay
Copy link
Owner

你可以提供下视频片段让我来测试下吗?
我的代码里面的这一段,正常来说就可以用当前的时间来为上一个字幕设置结束时间的。

 if let preSubtitleFrame, preSubtitleFrame.part.end == preSubtitleFrame.part.start {
            preSubtitleFrame.part.end = start
        }

@kingslay
Copy link
Owner

我在main分支,修复这个问题了。你可以试下。其实是因为这个字幕会输出两个时间片段一摸一样的字幕片段。我加了一个判断,把它过滤掉了。这样preSubtitleFrame就起作用了。

@FantasyKingdom
Copy link
Contributor Author

你的修改并没有解决问题。
解码出来的字幕不是严格的时间顺序的
所以后一个字幕的start时间可能比前面一条字幕的start还要小,导致end设置了一个比start小的值,这时如果没有新的空字幕,而只依赖上述的第二段代码是无法清除掉当前字幕的。我提交的代码可以解决这个问题。

图中的xxxx是SubtitleDecode中的字幕start时间。
当前已经播放到22秒了,仍显示12.47的字幕
image

@FantasyKingdom
Copy link
Contributor Author

12.513和12.512是两条无内容的字幕。
因为12.471这条字幕的end值已经被设置为了12.47。所以不会更新它的end值。
导致12.471这条字幕一直被显示。

@kingslay
Copy link
Owner

不好意思。因为那个url播放太卡了。所以我是通过ffmpeg来下载一分钟的片段进行测试。ffmpeg对于下载下来的字幕时间戳应该是有做了重新矫正。所以我本地只要用等于进行判断就不会有问题了。但是线上的url是要用>=来进行判断。我改好了。麻烦你在试下。

@FantasyKingdom
Copy link
Contributor Author

FantasyKingdom commented Apr 23, 2024

这样改虽然可以解决这个问题,但是我感觉某些情况下会把一部分正常的字幕给漏掉了。

我觉得就不应该使用preSubtitleFrame这个对象,可以去掉,而是将解码出来的空字幕放到字幕的缓冲区会比较好,像第一个评论说的那样。当然,这仅是我自己的看法。

@kingslay
Copy link
Owner

可以试着把preSubtitleFrame给去掉。但是对于开始时间和结束时间一样的字幕。还是需要item.part < time或者是part.end <= part.start来进行判断,不能直接用一个固定的长度 5s。不然对于文字字幕的话,那有可能在某个时间段同时显示两个文字字幕。

@FantasyKingdom
Copy link
Contributor Author

FantasyKingdom commented Apr 23, 2024

我把preSubtitleFrame去掉了,然后这样改从逻辑上应该是没有你说的这个问题的
image
image

@kingslay
Copy link
Owner

嗯,你这样改是可以的。而且如果是空字幕应该不需要返回一个空的字幕了。因为之前是有item.part < time 这个判断,所以才可以返回空字幕进行清空。现在是根据 item.part == time来判断了。空字幕应该是无法返回了。你可以去掉这个代码试下。应该也是没有问题的。
image

@FantasyKingdom
Copy link
Contributor Author

即使是空字幕,也是有设置时间的,把它当作正常字幕即可,只是无内容。
按照我的这种改法那parts.append(SubtitlePart(0, 0, attributedString: nil))这一句是不能少的。
image

@kingslay
Copy link
Owner

kingslay commented Apr 24, 2024

嗯,我按照你的思路改好了。你的思路确实更好。返回一个空字幕是一个正确的方式。这样才能解决字幕解码不按顺序的问题。你可以试下

@FantasyKingdom
Copy link
Contributor Author

是的,这样改就没问题了。既能解决字幕重复字幕及乱序问题,而且整体逻辑也更加清晰了。之前的各种<=判断在第一次看代码的时候真的很让人迷惑😄。

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants