Untertitel brachten den Vorratsspeicher auf 404
Untertitel stehen in der Abspielliste als eigene Spur unter EXT-X-MEDIA — eine Anweisung mit einer Adresse darin. Umgeschrieben habe ich bisher nur EXT-X-MAP, also blieb diese relativ stehen und zeigte danach auf den lokalen Server, wo es sie nicht gibt. Zu sehen war der Fehler erst, als jemand Untertitel einschaltete: HTTP 404, mitten im Film. Jetzt sagt der Umschreiber, **was** fuer eine Adresse er gerade in der Hand hat: eine Qualitaetsstufe, eine Nebenspur, ein Kopfstueck oder ein Schnipsel. Das ist noetig, weil sie Verschiedenes wollen — hinter einer Stufe liegt Bild und die soll vorgeladen werden, hinter einer Untertitel- spur nicht. Sonst lueden wir Untertitel statt Bild: der Film bliebe stehen, waehrend die Anzeige reichlich Vorrat meldet. Dazu wandern alle Adressen im lokalen Server auf die **vollstaendige** Form. Eine relative gilt je nach Liste gegen eine andere Grundadresse — die Untertitelspur liegt woanders als das Bild —, und wer das erst beim Abholen aufloest, loest es irgendwann gegen die falsche auf. Das waere der naechste Fehler derselben Art gewesen. Drei Tests halten die Unterscheidung fest, darunter die Liste mit Untertitelspur, die den 404 ausgeloest hat. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 5
parent
88ba1a540c
commit
cff0c06745
@@ -49,7 +49,7 @@ struct MediaPlaylistTests {
|
||||
/// findet man im laufenden Bild nicht.
|
||||
@Test("Umgeschrieben werden Adressen, sonst nichts")
|
||||
func rewritesOnlyReferences() {
|
||||
let neu = MediaPlaylist(medien).rewritingReferences { "http://127.0.0.1:1234/s/\($0)" }
|
||||
let neu = MediaPlaylist(medien).rewritingReferences { adresse, _ in "http://127.0.0.1:1234/s/\(adresse)" }
|
||||
|
||||
#expect(neu.contains("http://127.0.0.1:1234/s/hls1/main/0.mp4"))
|
||||
#expect(neu.contains("http://127.0.0.1:1234/s/hls1/main/2.mp4"))
|
||||
@@ -68,20 +68,20 @@ struct MediaPlaylistTests {
|
||||
/// irgendetwas falsch wäre.
|
||||
@Test("Das Kopfstück wandert mit")
|
||||
func rewritesInitSegment() {
|
||||
let neu = MediaPlaylist(medien).rewritingReferences { "/s/\($0)" }
|
||||
let neu = MediaPlaylist(medien).rewritingReferences { adresse, _ in "/s/\(adresse)" }
|
||||
#expect(neu.contains("#EXT-X-MAP:URI=\"/s/hls1/main/-1.mp4\""))
|
||||
}
|
||||
|
||||
@Test("Eine Anweisung ohne Adresse bleibt unberührt")
|
||||
func leavesOtherTagsAlone() {
|
||||
let neu = MediaPlaylist(medien).rewritingReferences { "/s/\($0)" }
|
||||
let neu = MediaPlaylist(medien).rewritingReferences { adresse, _ in "/s/\(adresse)" }
|
||||
#expect(neu.contains("#EXT-X-VERSION:7"))
|
||||
#expect(neu.contains("#EXTINF:6.000000,"))
|
||||
}
|
||||
|
||||
@Test("Die Zeilenzahl bleibt gleich")
|
||||
func keepsStructure() {
|
||||
let neu = MediaPlaylist(medien).rewritingReferences { $0 }
|
||||
let neu = MediaPlaylist(medien).rewritingReferences { adresse, _ in adresse }
|
||||
#expect(neu.components(separatedBy: "\n").count == medien.components(separatedBy: "\n").count)
|
||||
}
|
||||
|
||||
@@ -101,7 +101,63 @@ struct MediaPlaylistTests {
|
||||
@Test("Eine leere Eingabe ergibt eine leere Liste, keinen Absturz")
|
||||
func emptyIsEmpty() {
|
||||
#expect(MediaPlaylist("").segments.isEmpty)
|
||||
#expect(MediaPlaylist("").rewritingReferences { $0 } == "")
|
||||
#expect(MediaPlaylist("").rewritingReferences { adresse, _ in adresse } == "")
|
||||
}
|
||||
}
|
||||
|
||||
@Suite("Nebenspuren in der Abspielliste")
|
||||
struct PlaylistRenditionTests {
|
||||
/// **Der Fehler, der mit „404" endete.** Untertitel stehen in einer
|
||||
/// eigenen Anweisung mit einer Adresse darin. Blieb sie stehen, zeigte
|
||||
/// sie relativ auf den lokalen Server — und dort gibt es sie nicht. Zu
|
||||
/// sehen war das erst, als jemand Untertitel einschaltete.
|
||||
private let mitUntertiteln = """
|
||||
#EXTM3U
|
||||
#EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Deutsch",URI="subtitles/0.m3u8"
|
||||
#EXT-X-STREAM-INF:BANDWIDTH=8000000,SUBTITLES="subs"
|
||||
main.m3u8?level=0
|
||||
"""
|
||||
|
||||
@Test("Die Untertitelspur wird mit umgeschrieben")
|
||||
func rewritesSubtitleRendition() {
|
||||
let neu = MediaPlaylist(mitUntertiteln).rewritingReferences { adresse, _ in
|
||||
"/um/\(adresse)"
|
||||
}
|
||||
#expect(neu.contains("URI=\"/um/subtitles/0.m3u8\""))
|
||||
#expect(!neu.contains("URI=\"subtitles/0.m3u8\""))
|
||||
}
|
||||
|
||||
/// **Und sie darf nicht vorgeladen werden.** Sonst lüde der Vorrat
|
||||
/// Untertitel statt Bild: der Film bliebe stehen, während die Anzeige
|
||||
/// reichlich Vorrat meldet.
|
||||
@Test("Stufe und Nebenspur werden unterschieden")
|
||||
func tellsLevelFromRendition() {
|
||||
var arten: [String: MediaPlaylist.Reference] = [:]
|
||||
_ = MediaPlaylist(mitUntertiteln).rewritingReferences { adresse, art in
|
||||
arten[adresse] = art
|
||||
return adresse
|
||||
}
|
||||
|
||||
#expect(arten["main.m3u8?level=0"] == .level)
|
||||
#expect(arten["subtitles/0.m3u8"] == .rendition)
|
||||
}
|
||||
|
||||
@Test("Das Kopfstück gilt als Schnipsel, nicht als Liste")
|
||||
func mapIsASegment() {
|
||||
let liste = """
|
||||
#EXTM3U
|
||||
#EXT-X-MAP:URI="hls1/main/-1.mp4"
|
||||
#EXTINF:6.0,
|
||||
hls1/main/0.mp4
|
||||
"""
|
||||
var arten: [String: MediaPlaylist.Reference] = [:]
|
||||
_ = MediaPlaylist(liste).rewritingReferences { adresse, art in
|
||||
arten[adresse] = art
|
||||
return adresse
|
||||
}
|
||||
|
||||
#expect(arten["hls1/main/-1.mp4"] == .map)
|
||||
#expect(arten["hls1/main/0.mp4"] == .segment)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -113,7 +169,8 @@ struct LocalStreamServerPathTests {
|
||||
@Test("Eine Stufe wird vollständig adressiert, nicht relativ")
|
||||
func levelPathIsAbsolute() {
|
||||
let pfad = LocalStreamServer.localPlaylistPath(
|
||||
for: "http://server:8096/videos/x/main.m3u8?level=1&api_key=t"
|
||||
for: "http://server:8096/videos/x/main.m3u8?level=1&api_key=t",
|
||||
prefetch: true
|
||||
)
|
||||
let teile = URLComponents(string: pfad)
|
||||
#expect(teile?.path == "/level.m3u8")
|
||||
@@ -127,7 +184,7 @@ struct LocalStreamServerPathTests {
|
||||
/// eine Abspielliste oder Bild erwartet.
|
||||
@Test("Die Endung bleibt eine Abspielliste")
|
||||
func levelPathKeepsExtension() {
|
||||
#expect(LocalStreamServer.localPlaylistPath(for: "http://s/a.m3u8").hasPrefix("/level.m3u8"))
|
||||
#expect(LocalStreamServer.localPlaylistPath(for: "http://s/a.m3u8", prefetch: true).hasPrefix("/level.m3u8"))
|
||||
}
|
||||
|
||||
/// Schrägstriche und Punkte im ursprünglichen Pfad dürfen nichts
|
||||
@@ -137,7 +194,7 @@ struct LocalStreamServerPathTests {
|
||||
let pfad = LocalStreamServer.localPath(for: "hls1/main/12.mp4?runtimeTicks=0")
|
||||
let teile = URLComponents(string: pfad)
|
||||
#expect(teile?.path == "/s/")
|
||||
#expect(teile?.queryItems?.first { $0.name == "p" }?.value == "hls1/main/12.mp4?runtimeTicks=0")
|
||||
#expect(teile?.queryItems?.first { $0.name == "u" }?.value == "hls1/main/12.mp4?runtimeTicks=0")
|
||||
}
|
||||
|
||||
/// Eine Stufenliste, durch den Umschreiber gedreht, muss auf den lokalen
|
||||
@@ -152,9 +209,9 @@ struct LocalStreamServerPathTests {
|
||||
main.m3u8?level=1
|
||||
"""
|
||||
let basis = URL(string: "http://server:8096/videos/x/master.m3u8?api_key=t")!
|
||||
let neu = MediaPlaylist(stufen).rewritingReferences { eintrag in
|
||||
let neu = MediaPlaylist(stufen).rewritingReferences { eintrag, _ in
|
||||
let absolut = URL(string: eintrag, relativeTo: basis)?.absoluteString ?? eintrag
|
||||
return LocalStreamServer.localPlaylistPath(for: absolut)
|
||||
return LocalStreamServer.localPlaylistPath(for: absolut, prefetch: true)
|
||||
}
|
||||
|
||||
#expect(neu.components(separatedBy: "/level.m3u8").count == 3)
|
||||
|
||||
Reference in New Issue
Block a user