You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
Music/MusicShared/Sources/MusicShared/HLSManifestGenerator.swift

43 lines
1.6 KiB

import Foundation
public enum HLSManifestGenerator: Sendable {
public struct TimeRange: Equatable, Sendable {
public var start: Double
public var duration: Double
}
public static func manifest(trackId: Int64, duration: Double, segmentDuration: Double, token: String? = nil) -> String {
let count = segmentCount(duration: duration, segmentDuration: segmentDuration)
let targetDuration = Int(segmentDuration.rounded(.up))
var lines: [String] = [
"#EXTM3U",
"#EXT-X-VERSION:3",
"#EXT-X-TARGETDURATION:\(targetDuration)",
"#EXT-X-MEDIA-SEQUENCE:0",
]
let tokenQuery = token.map { "?token=\($0)" } ?? ""
for i in 0..<count {
let range = segmentTimeRange(index: i, trackDuration: duration, segmentDuration: segmentDuration)
lines.append(String(format: "#EXTINF:%.3f,", range.duration))
lines.append("segments/\(i).mp3\(tokenQuery)")
}
lines.append("#EXT-X-ENDLIST")
lines.append("")
return lines.joined(separator: "\n")
}
public static func segmentCount(duration: Double, segmentDuration: Double) -> Int {
guard duration > 0, segmentDuration > 0 else { return 0 }
return Int((duration / segmentDuration).rounded(.up))
}
public static func segmentTimeRange(index: Int, trackDuration: Double, segmentDuration: Double) -> TimeRange {
let start = Double(index) * segmentDuration
let remaining = trackDuration - start
let duration = min(segmentDuration, remaining)
return TimeRange(start: start, duration: duration)
}
}