From 1e0a852c7a6691ae319f05573bd798c7021ff91e Mon Sep 17 00:00:00 2001 From: Luna712 <142361265+Luna712@users.noreply.github.com> Date: Sat, 30 Sep 2023 17:46:37 -0600 Subject: [PATCH] Remove FFmpeg and FFprobe --- .../utils/ThumbnailSpriteGenerator.kt | 152 ++---------------- 1 file changed, 13 insertions(+), 139 deletions(-) diff --git a/app/src/main/java/com/lagradost/cloudstream3/utils/ThumbnailSpriteGenerator.kt b/app/src/main/java/com/lagradost/cloudstream3/utils/ThumbnailSpriteGenerator.kt index 90a26de9..1e1d5114 100644 --- a/app/src/main/java/com/lagradost/cloudstream3/utils/ThumbnailSpriteGenerator.kt +++ b/app/src/main/java/com/lagradost/cloudstream3/utils/ThumbnailSpriteGenerator.kt @@ -6,9 +6,6 @@ import android.graphics.BitmapFactory import android.graphics.Canvas import android.media.MediaMetadataRetriever import java.io.File -import com.arthenica.ffmpegkit.FFmpegKit -import com.arthenica.ffmpegkit.FFprobeKit -import com.arthenica.ffmpegkit.ReturnCode internal interface ThumbnailSpriteCallback { fun onThumbnailSpriteGenerated(spriteBitmap: Bitmap) @@ -53,20 +50,11 @@ internal class ThumbnailSpriteGenerator( val thumbnailWidth = videoWidth / maxColumns val thumbnailHeight = videoHeight / maxLines - val thumbnailList: ArrayList - - if (videoPath.contains(".m3u8")) { - // Using FFmpeg is only really needed for files like M3u8 files - // MediaMetadataRetriever can handle most other things - // If we don't want to support them, then this could really probably be removed - thumbnailList = generateThumbnailsFFmpeg(thumbnailWidth, thumbnailHeight, frameIntervalMillis) - } else { - thumbnailList = ArrayList() - for (timeInMillis in 0 until videoDuration step frameIntervalMillis) { - val thumbnail = generateThumbnail(timeInMillis, thumbnailWidth, thumbnailHeight) - if (thumbnail != null) { - thumbnailList.add(thumbnail) - } + val thumbnailList = ArrayList() + for (timeInMillis in 0 until videoDuration step frameIntervalMillis) { + val thumbnail = generateThumbnail(timeInMillis, thumbnailWidth, thumbnailHeight) + if (thumbnail != null) { + thumbnailList.add(thumbnail) } } @@ -123,72 +111,6 @@ internal class ThumbnailSpriteGenerator( null } } - - private fun generateThumbnailsFFmpeg(thumbnailWidth: Int, thumbnailHeight: Int, frameIntervalMillis: Long): ArrayList { - return try { - // Use FFmpeg to generate thumbnail sprites for online videos - val frameIntervalSeconds = (frameIntervalMillis / 1000.0).toDouble() - - val context: Context = MainActivity.instance.applicationContext - val cacheDir = context.cacheDir - val outputFilePathPattern = File(cacheDir, "thumbnail%d.jpg").absolutePath - - val ffmpegCommand: Array = arrayOf( - "-i", videoPath, - "fps=1/$frameIntervalSeconds,scale=$thumbnailWidth:$thumbnailHeight", - "-preset", "ultrafast", - "-an", - "-y", - outputFilePathPattern - ) - - val session = FFmpegKit.executeWithArguments(ffmpegCommand) - val returnCode: ReturnCode = session.returnCode - - if (ReturnCode.isSuccess(returnCode)) { - // Read the image into a Bitmap - // Determine the number of generated frames dynamically - var frameNumber = 1 - - val generatedThumbnails = ArrayList() - - while (true) { - val filePath = outputFilePathPattern.replace("%d", frameNumber.toString()) - - val thumbnail: Bitmap? - if (File(filePath).exists()) { - thumbnail = BitmapFactory.decodeFile(filePath) - - // Clean up: Delete the temporary file - File(filePath).delete() - } else { - thumbnail = null - } - - if (thumbnail != null) { - generatedThumbnails.add(thumbnail) - - val spriteBitmap = createSpriteBitmap(generatedThumbnails) - callback.onThumbnailSpriteGenerated(spriteBitmap) - frameNumber++ - } else { - // No more frames found, exit the loop - break - } - } - - generatedThumbnails - } else { - val errorMessage = "FFmpeg execution failed with return code: $returnCode, ${session.getOutput()}" - callback.onThumbnailSpriteGenerationError(Exception(errorMessage)) - ArrayList() - } - } catch (e: Exception) { - e.printStackTrace() - callback.onThumbnailSpriteGenerationError(e) - ArrayList() - } - } private fun createSpriteBitmap(thumbnails: List): Bitmap { val spriteWidth = thumbnails[0].width * maxColumns @@ -207,13 +129,9 @@ internal class ThumbnailSpriteGenerator( private fun getVideoDuration(): Long { return try { - if (videoPath.contains(".m3u8")) { - getVideoDurationFFprobe() - } else { - val durationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION) + val durationString = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION) - durationString?.toLong() ?: 0 - } + durationString?.toLong() ?: 0 } catch (e: Exception) { e.printStackTrace() callback.onThumbnailSpriteGenerationError(e) @@ -221,64 +139,20 @@ internal class ThumbnailSpriteGenerator( } } - private fun getVideoDurationFFprobe(): Long { - val session = FFprobeKit.getMediaInformation(videoPath) - val mediaInformation = session.mediaInformation - val returnCode: ReturnCode = session.returnCode - - return if (ReturnCode.isSuccess(returnCode) && mediaInformation.duration != null) { - (mediaInformation.duration.toDouble() * 1000.0).toLong() - } else { - val errorMessage = "FFprobe execution failed with return code: $returnCode, ${session.getOutput()}" - callback.onThumbnailSpriteGenerationError(Exception(errorMessage)) - 0 - } - } - private fun getVideoDimensions(): Pair? { return try { - if (videoPath.contains(".m3u8")) { - getVideoDimensionsFFprobe() - } else { - val width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toInt() - val height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toInt() + val width = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_WIDTH)?.toInt() + val height = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_VIDEO_HEIGHT)?.toInt() - if (width != null && height != null) { - Pair(width, height) - } else { - null - } + if (width != null && height != null) { + Pair(width, height) + } else { + null } } catch (e: Exception) { e.printStackTrace() callback.onThumbnailSpriteGenerationError(e) null } - } - - private fun getVideoDimensionsFFprobe(): Pair? { - val session = FFprobeKit.getMediaInformation(videoPath) - val mediaInformation = session.mediaInformation - val returnCode: ReturnCode = session.returnCode - - return if (ReturnCode.isSuccess(returnCode) && mediaInformation.streams.isNotEmpty()) { - val videoStream = mediaInformation.streams.find { it.width != null && it.height != null } - if (videoStream != null) { - val width = videoStream.width - val height = videoStream.height - - if (width != null && height != null) { - Pair(width.toInt(), height.toInt()) - } else { - null - } - } else { - null - } - } else { - val errorMessage = "FFprobe execution failed with return code: $returnCode, ${session.getOutput()}" - callback.onThumbnailSpriteGenerationError(Exception(errorMessage)) - null - } } }