mirror of
https://gitlab.futo.org/videostreaming/grayjay.git
synced 2025-04-29 22:24:29 +02:00
add non iv version
Changelog: added
This commit is contained in:
parent
9014fb581d
commit
470b7bd2e5
@ -65,6 +65,7 @@ import java.io.File
|
|||||||
import java.io.FileOutputStream
|
import java.io.FileOutputStream
|
||||||
import java.io.IOException
|
import java.io.IOException
|
||||||
import java.lang.Thread.sleep
|
import java.lang.Thread.sleep
|
||||||
|
import java.nio.ByteBuffer
|
||||||
import java.time.OffsetDateTime
|
import java.time.OffsetDateTime
|
||||||
import java.util.UUID
|
import java.util.UUID
|
||||||
import java.util.concurrent.Executors
|
import java.util.concurrent.Executors
|
||||||
@ -593,9 +594,9 @@ class VideoDownload {
|
|||||||
|
|
||||||
val variantPlaylist = HLS.parseVariantPlaylist(vpContent, hlsUrl)
|
val variantPlaylist = HLS.parseVariantPlaylist(vpContent, hlsUrl)
|
||||||
val decryptionInfo: DecryptionInfo? = if (variantPlaylist.decryptionInfo != null) {
|
val decryptionInfo: DecryptionInfo? = if (variantPlaylist.decryptionInfo != null) {
|
||||||
val keyResponse = client.get(variantPlaylist.decryptionInfo.keyUrl)
|
val keyResponse = client.get(variantPlaylist.decryptionInfo.keyUrl, mutableMapOf("Cookie" to "sails.sid=s%3AeSKom53v4W3_0CliWJFFMj9k3hcAuyhx.Nf9lF1sUSQ0GUvCKBOM64bsV%2BZMOkiKke43eHO6gTZI;"))
|
||||||
check(keyResponse.isOk) { "HLS request failed for decryption key: ${keyResponse.code}" }
|
check(keyResponse.isOk) { "HLS request failed for decryption key: ${keyResponse.code}" }
|
||||||
DecryptionInfo(keyResponse.body!!.bytes(), variantPlaylist.decryptionInfo.iv.hexStringToByteArray())
|
DecryptionInfo(keyResponse.body!!.bytes(), variantPlaylist.decryptionInfo.iv?.hexStringToByteArray())
|
||||||
} else {
|
} else {
|
||||||
null
|
null
|
||||||
}
|
}
|
||||||
@ -611,7 +612,7 @@ class VideoDownload {
|
|||||||
try {
|
try {
|
||||||
segmentFiles.add(segmentFile)
|
segmentFiles.add(segmentFile)
|
||||||
|
|
||||||
val segmentLength = downloadSource_Sequential(client, outputStream, segment.uri, if (index == 0) null else decryptionInfo) { segmentLength, totalRead, lastSpeed ->
|
val segmentLength = downloadSource_Sequential(client, outputStream, segment.uri, if (index == 0) null else decryptionInfo, index) { segmentLength, totalRead, lastSpeed ->
|
||||||
val averageSegmentLength = if (index == 0) segmentLength else downloadedTotalLength / index
|
val averageSegmentLength = if (index == 0) segmentLength else downloadedTotalLength / index
|
||||||
val expectedTotalLength = averageSegmentLength * (variantPlaylist.segments.size - 1) + segmentLength
|
val expectedTotalLength = averageSegmentLength * (variantPlaylist.segments.size - 1) + segmentLength
|
||||||
onProgress(expectedTotalLength, downloadedTotalLength + totalRead, lastSpeed)
|
onProgress(expectedTotalLength, downloadedTotalLength + totalRead, lastSpeed)
|
||||||
@ -651,10 +652,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?
|
||||||
@ -664,7 +663,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)) {
|
||||||
@ -672,7 +670,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))
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -792,7 +789,7 @@ class VideoDownload {
|
|||||||
else {
|
else {
|
||||||
Logger.i(TAG, "Download $name Sequential");
|
Logger.i(TAG, "Download $name Sequential");
|
||||||
try {
|
try {
|
||||||
sourceLength = downloadSource_Sequential(client, fileStream, videoUrl, null, onProgress);
|
sourceLength = downloadSource_Sequential(client, fileStream, videoUrl, null, 0, onProgress);
|
||||||
} catch (e: Throwable) {
|
} catch (e: Throwable) {
|
||||||
Logger.w(TAG, "Failed to download sequentially (url = $videoUrl)")
|
Logger.w(TAG, "Failed to download sequentially (url = $videoUrl)")
|
||||||
throw e
|
throw e
|
||||||
@ -822,7 +819,7 @@ class VideoDownload {
|
|||||||
|
|
||||||
data class DecryptionInfo(
|
data class DecryptionInfo(
|
||||||
val key: ByteArray,
|
val key: ByteArray,
|
||||||
val iv: ByteArray
|
val iv: ByteArray?
|
||||||
) {
|
) {
|
||||||
override fun equals(other: Any?): Boolean {
|
override fun equals(other: Any?): Boolean {
|
||||||
if (this === other) return true
|
if (this === other) return true
|
||||||
@ -843,7 +840,7 @@ class VideoDownload {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun downloadSource_Sequential(client: ManagedHttpClient, fileStream: FileOutputStream, url: String, decryptionInfo: DecryptionInfo?, onProgress: (Long, Long, Long) -> Unit): Long {
|
private fun downloadSource_Sequential(client: ManagedHttpClient, fileStream: FileOutputStream, url: String, decryptionInfo: DecryptionInfo?, index: Int, onProgress: (Long, Long, Long) -> Unit): Long {
|
||||||
val progressRate: Int = 4096 * 5;
|
val progressRate: Int = 4096 * 5;
|
||||||
var lastProgressCount: Int = 0;
|
var lastProgressCount: Int = 0;
|
||||||
val speedRate: Int = 4096 * 5;
|
val speedRate: Int = 4096 * 5;
|
||||||
@ -902,8 +899,15 @@ class VideoDownload {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (decryptionInfo != null) {
|
if (decryptionInfo != null) {
|
||||||
val decryptedData =
|
var iv = decryptionInfo.iv
|
||||||
decryptSegment(segmentBuffer.toByteArray(), decryptionInfo.key, decryptionInfo.iv)
|
if (iv == null) {
|
||||||
|
iv = ByteBuffer.allocate(16)
|
||||||
|
.putLong(0L)
|
||||||
|
.putLong(index.toLong())
|
||||||
|
.array()
|
||||||
|
}
|
||||||
|
|
||||||
|
val decryptedData = decryptSegment(segmentBuffer.toByteArray(), decryptionInfo.key, iv!!)
|
||||||
fileStream.write(decryptedData)
|
fileStream.write(decryptedData)
|
||||||
} else {
|
} else {
|
||||||
fileStream.write(segmentBuffer.toByteArray())
|
fileStream.write(segmentBuffer.toByteArray())
|
||||||
@ -1222,7 +1226,7 @@ class VideoDownload {
|
|||||||
else if (container.contains("audio/webm"))
|
else if (container.contains("audio/webm"))
|
||||||
return "webm";
|
return "webm";
|
||||||
else if (container == "application/vnd.apple.mpegurl")
|
else if (container == "application/vnd.apple.mpegurl")
|
||||||
return "mp4a";
|
return "mp4";
|
||||||
else
|
else
|
||||||
return "audio";// throw IllegalStateException("Unknown container: " + container)
|
return "audio";// throw IllegalStateException("Unknown container: " + container)
|
||||||
}
|
}
|
||||||
|
@ -69,9 +69,7 @@ class HLS {
|
|||||||
keyInfo?.find { it.startsWith("IV=") }?.substringAfter("=")?.substringAfter("x")
|
keyInfo?.find { it.startsWith("IV=") }?.substringAfter("=")?.substringAfter("x")
|
||||||
|
|
||||||
val decryptionInfo: DecryptionInfo? = key?.let { k ->
|
val decryptionInfo: DecryptionInfo? = key?.let { k ->
|
||||||
iv?.let { i ->
|
DecryptionInfo(k, iv)
|
||||||
DecryptionInfo(k, i)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
val initSegment =
|
val initSegment =
|
||||||
@ -390,7 +388,7 @@ class HLS {
|
|||||||
|
|
||||||
data class DecryptionInfo(
|
data class DecryptionInfo(
|
||||||
val keyUrl: String,
|
val keyUrl: String,
|
||||||
val iv: String
|
val iv: String?
|
||||||
)
|
)
|
||||||
|
|
||||||
data class VariantPlaylist(
|
data class VariantPlaylist(
|
||||||
|
Loading…
x
Reference in New Issue
Block a user