Fixed HLS downloading for Twitch, DialyMotion, Nebula.

This commit is contained in:
Koen J
2025-12-05 15:31:31 +01:00
parent bda534e485
commit 3a11d0d9d1
@@ -589,38 +589,54 @@ 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 -> require(segmentFiles.isNotEmpty()) { "segmentFiles must not be empty" }
val fileList = File(context.cacheDir, "fileList-${UUID.randomUUID()}.txt")
fileList.writeText(segmentFiles.joinToString("\n") { "file '${it.absolutePath}'" }) suspendCancellableCoroutine { continuation ->
val concatInput = buildString {
append("concat:")
append(
segmentFiles.joinToString("|") { file ->
file.absolutePath
}
)
}
val cmd = "-i \"$concatInput\" -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? //No callback
} }
val executorService = Executors.newSingleThreadExecutor() val executorService = Executors.newSingleThreadExecutor()
val session = FFmpegKit.executeAsync(cmd,
{ session -> val session = FFmpegKit.executeAsync(
if (ReturnCode.isSuccess(session.returnCode)) { cmd,
fileList.delete() { completedSession ->
executorService.shutdown()
if (ReturnCode.isSuccess(completedSession.returnCode)) {
continuation.resumeWith(Result.success(Unit)) continuation.resumeWith(Result.success(Unit))
} else { } else {
val errorMessage = if (ReturnCode.isCancel(session.returnCode)) { val errorMessage = if (ReturnCode.isCancel(completedSession.returnCode)) {
"Command cancelled" "Command cancelled"
} else { } else {
"Command failed with state '${session.state}' and return code ${session.returnCode}, stack trace ${session.failStackTrace}" "Command failed with state '${completedSession.state}' " +
"and return code ${completedSession.returnCode}, " +
"stack trace ${completedSession.failStackTrace}"
} }
fileList.delete()
continuation.resumeWithException(RuntimeException(errorMessage)) continuation.resumeWithException(RuntimeException(errorMessage))
} }
}, },
{ Logger.v(TAG, it.message) }, { log ->
Logger.v(TAG, log.message)
},
statisticsCallback, statisticsCallback,
executorService executorService
) )
continuation.invokeOnCancellation { continuation.invokeOnCancellation {
session.cancel() session.cancel()
executorService.shutdownNow()
} }
} }
} }