fixed some bugs on ios
This commit is contained in:
@@ -318,21 +318,27 @@ final class PlayerController: ObservableObject {
|
||||
}
|
||||
|
||||
/// 只播放当前句子,播完自动暂停并回到句首(评测“播放原句”)。
|
||||
/// 必须先打上句尾标记再 seek,这样 completion 里的 forwardPlaybackEndTime
|
||||
/// 会卡在当前句 endMs,而不是等 250ms 观察器才停。
|
||||
func playCurrentSentenceAndStop() {
|
||||
guard let sentence = currentSentence else {
|
||||
return
|
||||
}
|
||||
performSeek(to: sentenceSeekPosition(sentence))
|
||||
stopAtSentenceEnd = true
|
||||
stopAtSentenceEndIndex = sentence.index
|
||||
play()
|
||||
lastSentenceIndex = sentence.index
|
||||
playbackIntent = true
|
||||
performSeek(to: sentenceSeekPosition(sentence), resumePlayback: true)
|
||||
}
|
||||
|
||||
// MARK: - 设置
|
||||
|
||||
func setContinuousPlayback(_ enabled: Bool) {
|
||||
config.continuousPlayback = enabled
|
||||
refreshSentenceBoundaryGuard()
|
||||
if !enabled {
|
||||
lastSentenceIndex = currentSentence?.index ?? lastSentenceIndex
|
||||
}
|
||||
refreshSentenceBoundaryGuard(force: true)
|
||||
}
|
||||
|
||||
func setSentenceMode(_ enabled: Bool) {
|
||||
@@ -783,6 +789,13 @@ final class PlayerController: ObservableObject {
|
||||
tick()
|
||||
return
|
||||
}
|
||||
// 评测“播放原句”即使处于连续播放,也要用当前句硬边界,不能滑进下一句。
|
||||
if stopAtSentenceEnd,
|
||||
let index = stopAtSentenceEndIndex,
|
||||
let sentence = mediaItem?.sentences.first(where: { $0.index == index }) {
|
||||
applySentenceEndAction(sentence)
|
||||
return
|
||||
}
|
||||
// 若最后一个句子的 endMs 就是视频末尾,forwardPlaybackEndTime 和自然结束
|
||||
// 是同一时间点。此时必须执行“当前句”的句尾动作,而不能整条视频回零。
|
||||
if config.sentenceMode,
|
||||
|
||||
@@ -88,16 +88,20 @@ enum ImitationAssessor {
|
||||
appendFile(&body, boundary: boundary, name: "audio", filename: filename, mimeType: mimeType, data: recordingData)
|
||||
body.append(Data("--\(boundary)--\r\n".utf8))
|
||||
|
||||
var headers = [
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "multipart/form-data; boundary=\(boundary)",
|
||||
"X-Client-Key": AppConfig.assessmentAPIKey,
|
||||
]
|
||||
if !AppConfig.authToken.isEmpty {
|
||||
headers["Authorization"] = "Bearer \(AppConfig.authToken)"
|
||||
}
|
||||
let result = try await HTTPClient.execute(
|
||||
baseURL: AppConfig.serverBaseURL,
|
||||
path: path,
|
||||
method: "POST",
|
||||
timeout: AppConfig.assessmentTimeout,
|
||||
headers: [
|
||||
"Accept": "application/json",
|
||||
"Content-Type": "multipart/form-data; boundary=\(boundary)",
|
||||
"X-Client-Key": AppConfig.assessmentAPIKey,
|
||||
],
|
||||
headers: headers,
|
||||
body: body
|
||||
)
|
||||
guard (200...299).contains(result.statusCode) else {
|
||||
|
||||
@@ -90,6 +90,9 @@ struct RootView: View {
|
||||
.onChange(of: activeModule) { module in
|
||||
if module == .train {
|
||||
controller.setContinuousPlayback(continuousPlayback)
|
||||
} else if module == .test {
|
||||
// 与安卓测试页一致:按当前句窗口播放,避免滑进下一句。
|
||||
controller.setContinuousPlayback(false)
|
||||
} else {
|
||||
controller.setContinuousPlayback(true)
|
||||
}
|
||||
|
||||
@@ -35,7 +35,7 @@ struct TestView: View {
|
||||
PlayerSectionView(
|
||||
controller: controller,
|
||||
showsContinuousToggle: false,
|
||||
continuousPlayback: .constant(true),
|
||||
continuousPlayback: .constant(false),
|
||||
showsSubtitle: $testSubtitleVisible,
|
||||
onFullscreen: onFullscreen
|
||||
)
|
||||
@@ -321,7 +321,7 @@ struct TestView: View {
|
||||
dubSegments[sentence.index] = audioURL
|
||||
dubRawSegments[sentence.index] = rawPersistedURL
|
||||
mergedDubURL = nil
|
||||
submitAssessment(recordingURL: url)
|
||||
submitAssessment(recordingURL: audioURL)
|
||||
}
|
||||
|
||||
private func restorePlaybackAudioSession() {
|
||||
|
||||
Reference in New Issue
Block a user