96 lines
2.6 KiB
Swift
96 lines
2.6 KiB
Swift
import Foundation
|
||
|
||
struct SentenceBoundary: Identifiable, Equatable, Decodable {
|
||
let index: Int
|
||
let startMs: Int64
|
||
let endMs: Int64
|
||
let text: String?
|
||
let language: String?
|
||
let referenceSpeechDurationMs: Int64?
|
||
|
||
var id: Int { index }
|
||
|
||
private enum CodingKeys: String, CodingKey {
|
||
case index, text, language
|
||
case startMs = "start_ms"
|
||
case endMs = "end_ms"
|
||
case referenceSpeechDurationMs = "reference_speech_duration_ms"
|
||
}
|
||
}
|
||
|
||
struct SentenceBoundaryDocument: Decodable {
|
||
let videoHash: String
|
||
let durationMs: Int64
|
||
let algorithmVersion: String
|
||
let sentences: [SentenceBoundary]
|
||
|
||
private enum CodingKeys: String, CodingKey {
|
||
case videoHash = "video_hash"
|
||
case durationMs = "duration_ms"
|
||
case algorithmVersion = "algorithm_version"
|
||
case sentences
|
||
}
|
||
}
|
||
|
||
struct TrainingVideoSummary: Identifiable, Decodable {
|
||
let videoHash: String
|
||
let title: String
|
||
let streamUrl: String
|
||
let durationMs: Int64?
|
||
let sizeBytes: Int64
|
||
let language: String?
|
||
let sentenceCount: Int
|
||
let status: String
|
||
|
||
var id: String { videoHash }
|
||
|
||
private enum CodingKeys: String, CodingKey {
|
||
case title, language, status
|
||
case videoHash = "video_hash"
|
||
case streamUrl = "stream_url"
|
||
case durationMs = "duration_ms"
|
||
case sizeBytes = "size_bytes"
|
||
case sentenceCount = "sentence_count"
|
||
}
|
||
|
||
/// 与安卓端一致:相对路径基于服务地址解析;服务地址为 http 时强制使用 http 流地址。
|
||
func resolvedStreamURL(baseURL: String) -> URL? {
|
||
guard let base = URL(string: baseURL) else { return nil }
|
||
var absolute = URL(string: streamUrl, relativeTo: base)?.absoluteString ?? streamUrl
|
||
if base.scheme == "http" {
|
||
absolute = absolute.replacingOccurrences(
|
||
of: "https://",
|
||
with: "http://",
|
||
options: [.anchored]
|
||
)
|
||
}
|
||
return URL(string: absolute)
|
||
}
|
||
}
|
||
|
||
struct TrainingMediaItem: Identifiable, Equatable {
|
||
let id: String
|
||
let title: String
|
||
let url: URL
|
||
let sentences: [SentenceBoundary]
|
||
let isLocalFile: Bool
|
||
|
||
init(
|
||
id: String,
|
||
title: String,
|
||
url: URL,
|
||
sentences: [SentenceBoundary] = [],
|
||
isLocalFile: Bool = false
|
||
) {
|
||
self.id = id
|
||
self.title = title
|
||
self.url = url
|
||
self.sentences = sentences
|
||
self.isLocalFile = isLocalFile
|
||
}
|
||
|
||
static func == (lhs: TrainingMediaItem, rhs: TrainingMediaItem) -> Bool {
|
||
lhs.id == rhs.id
|
||
}
|
||
}
|