mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-08-05 07:41:23 +00:00
Merge branch 'small-hls-fixes' into 'master'
Fix HLS downloading for nebula See merge request videostreaming/grayjay!85
This commit is contained in:
commit
90a5c7e11b
3 changed files with 13 additions and 9 deletions
|
@ -310,6 +310,8 @@ class UISlideOverlays {
|
||||||
val masterPlaylistContent = masterPlaylistResponse.body?.string()
|
val masterPlaylistContent = masterPlaylistResponse.body?.string()
|
||||||
?: throw Exception("Master playlist content is empty")
|
?: throw Exception("Master playlist content is empty")
|
||||||
|
|
||||||
|
val resolvedPlaylistUrl = masterPlaylistResponse.url
|
||||||
|
|
||||||
val videoButtons = arrayListOf<SlideUpMenuItem>()
|
val videoButtons = arrayListOf<SlideUpMenuItem>()
|
||||||
val audioButtons = arrayListOf<SlideUpMenuItem>()
|
val audioButtons = arrayListOf<SlideUpMenuItem>()
|
||||||
//TODO: Implement subtitles
|
//TODO: Implement subtitles
|
||||||
|
@ -322,7 +324,7 @@ class UISlideOverlays {
|
||||||
|
|
||||||
val masterPlaylist: HLS.MasterPlaylist
|
val masterPlaylist: HLS.MasterPlaylist
|
||||||
try {
|
try {
|
||||||
masterPlaylist = HLS.parseMasterPlaylist(masterPlaylistContent, sourceUrl)
|
masterPlaylist = HLS.parseMasterPlaylist(masterPlaylistContent, resolvedPlaylistUrl)
|
||||||
|
|
||||||
masterPlaylist.getAudioSources().forEach { it ->
|
masterPlaylist.getAudioSources().forEach { it ->
|
||||||
|
|
||||||
|
@ -398,11 +400,11 @@ class UISlideOverlays {
|
||||||
if (masterPlaylistContent.lines().any { it.startsWith("#EXTINF:") }) {
|
if (masterPlaylistContent.lines().any { it.startsWith("#EXTINF:") }) {
|
||||||
withContext(Dispatchers.Main) {
|
withContext(Dispatchers.Main) {
|
||||||
if (source is IHLSManifestSource) {
|
if (source is IHLSManifestSource) {
|
||||||
StateDownloads.instance.download(video, HLSVariantVideoUrlSource("variant", 0, 0, "application/vnd.apple.mpegurl", "", null, 0, false, sourceUrl), null, null)
|
StateDownloads.instance.download(video, HLSVariantVideoUrlSource("variant", 0, 0, "application/vnd.apple.mpegurl", "", null, 0, false, resolvedPlaylistUrl), null, null)
|
||||||
UIDialogs.toast(container.context, "Variant video HLS playlist download started")
|
UIDialogs.toast(container.context, "Variant video HLS playlist download started")
|
||||||
slideUpMenuOverlay.hide()
|
slideUpMenuOverlay.hide()
|
||||||
} else if (source is IHLSManifestAudioSource) {
|
} else if (source is IHLSManifestAudioSource) {
|
||||||
StateDownloads.instance.download(video, null, HLSVariantAudioUrlSource("variant", 0, "application/vnd.apple.mpegurl", "", "", null, false, false, sourceUrl), null)
|
StateDownloads.instance.download(video, null, HLSVariantAudioUrlSource("variant", 0, "application/vnd.apple.mpegurl", "", "", null, false, false, resolvedPlaylistUrl), null)
|
||||||
UIDialogs.toast(container.context, "Variant audio HLS playlist download started")
|
UIDialogs.toast(container.context, "Variant audio HLS playlist download started")
|
||||||
slideUpMenuOverlay.hide()
|
slideUpMenuOverlay.hide()
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -630,10 +630,8 @@ class VideoDownload {
|
||||||
|
|
||||||
private suspend fun combineSegments(context: Context, segmentFiles: List<File>, targetFile: File) = withContext(Dispatchers.IO) {
|
private suspend fun combineSegments(context: Context, segmentFiles: List<File>, targetFile: File) = withContext(Dispatchers.IO) {
|
||||||
suspendCancellableCoroutine { continuation ->
|
suspendCancellableCoroutine { continuation ->
|
||||||
val fileList = File(context.cacheDir, "fileList-${UUID.randomUUID()}.txt")
|
val cmd =
|
||||||
fileList.writeText(segmentFiles.joinToString("\n") { "file '${it.absolutePath}'" })
|
"-i \"concat:${segmentFiles.joinToString("|")}\" -c copy \"${targetFile.absolutePath}\""
|
||||||
|
|
||||||
val cmd = "-f concat -safe 0 -i \"${fileList.absolutePath}\" -c copy \"${targetFile.absolutePath}\""
|
|
||||||
|
|
||||||
val statisticsCallback = StatisticsCallback { _ ->
|
val statisticsCallback = StatisticsCallback { _ ->
|
||||||
//TODO: Show progress?
|
//TODO: Show progress?
|
||||||
|
@ -643,7 +641,6 @@ class VideoDownload {
|
||||||
val session = FFmpegKit.executeAsync(cmd,
|
val session = FFmpegKit.executeAsync(cmd,
|
||||||
{ session ->
|
{ session ->
|
||||||
if (ReturnCode.isSuccess(session.returnCode)) {
|
if (ReturnCode.isSuccess(session.returnCode)) {
|
||||||
fileList.delete()
|
|
||||||
continuation.resumeWith(Result.success(Unit))
|
continuation.resumeWith(Result.success(Unit))
|
||||||
} else {
|
} else {
|
||||||
val errorMessage = if (ReturnCode.isCancel(session.returnCode)) {
|
val errorMessage = if (ReturnCode.isCancel(session.returnCode)) {
|
||||||
|
@ -651,7 +648,6 @@ class VideoDownload {
|
||||||
} else {
|
} else {
|
||||||
"Command failed with state '${session.state}' and return code ${session.returnCode}, stack trace ${session.failStackTrace}"
|
"Command failed with state '${session.state}' and return code ${session.returnCode}, stack trace ${session.failStackTrace}"
|
||||||
}
|
}
|
||||||
fileList.delete()
|
|
||||||
continuation.resumeWithException(RuntimeException(errorMessage))
|
continuation.resumeWithException(RuntimeException(errorMessage))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -61,7 +61,13 @@ class HLS {
|
||||||
val playlistType = lines.find { it.startsWith("#EXT-X-PLAYLIST-TYPE:") }?.substringAfter(":")
|
val playlistType = lines.find { it.startsWith("#EXT-X-PLAYLIST-TYPE:") }?.substringAfter(":")
|
||||||
val streamInfo = lines.find { it.startsWith("#EXT-X-STREAM-INF:") }?.let { parseStreamInfo(it) }
|
val streamInfo = lines.find { it.startsWith("#EXT-X-STREAM-INF:") }?.let { parseStreamInfo(it) }
|
||||||
|
|
||||||
|
val initSegment =
|
||||||
|
lines.find { it.startsWith("#EXT-X-MAP:") }?.substringAfter(":")?.split(",")?.get(0)
|
||||||
|
?.substringAfter("=")?.trim('"')
|
||||||
val segments = mutableListOf<Segment>()
|
val segments = mutableListOf<Segment>()
|
||||||
|
if (initSegment != null) {
|
||||||
|
segments.add(MediaSegment(0.0, resolveUrl(sourceUrl, initSegment)))
|
||||||
|
}
|
||||||
var currentSegment: MediaSegment? = null
|
var currentSegment: MediaSegment? = null
|
||||||
lines.forEach { line ->
|
lines.forEach { line ->
|
||||||
when {
|
when {
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue