From fa755e5b7564bc7d2731638910e60a9232c85c3d Mon Sep 17 00:00:00 2001 From: Jorge Martin Espinosa Date: Tue, 26 Aug 2025 10:41:07 +0200 Subject: [PATCH] Use variable bitrate mode when transcoding to ensure compatibility with old devices (#5223) * Use variable bitrate mode when transcoding This should be compatible with more devices that may lack the needed codecs to properly encode using constant bitrate mode (CBR). * Fix video output size (again) --- .../androidutils/media/VideoCompressorHelper.kt | 6 +++++- .../mediaupload/impl/ThumbnailFactory.kt | 2 +- .../libraries/mediaupload/impl/VideoCompressor.kt | 15 +++++---------- 3 files changed, 11 insertions(+), 12 deletions(-) diff --git a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/media/VideoCompressorHelper.kt b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/media/VideoCompressorHelper.kt index 91953a22a3..fd1440b117 100644 --- a/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/media/VideoCompressorHelper.kt +++ b/libraries/androidutils/src/main/kotlin/io/element/android/libraries/androidutils/media/VideoCompressorHelper.kt @@ -27,7 +27,11 @@ class VideoCompressorHelper( fun getOutputSize(inputSize: Size): Size { val resultMajor = min(inputSize.major(), maxSize) val aspectRatio = inputSize.major().toFloat() / inputSize.minor().toFloat() - return Size(resultMajor, (resultMajor / aspectRatio).roundToInt()) + return if (inputSize.width >= inputSize.height) { + Size(resultMajor, (resultMajor / aspectRatio).roundToInt()) + } else { + Size((resultMajor / aspectRatio).roundToInt(), resultMajor) + } } /** diff --git a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/ThumbnailFactory.kt b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/ThumbnailFactory.kt index 7151836f17..123d59b029 100644 --- a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/ThumbnailFactory.kt +++ b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/ThumbnailFactory.kt @@ -123,8 +123,8 @@ class ThumbnailFactory @Inject constructor( val thumbnailResult = ThumbnailResult( file = thumbnailFile, info = ThumbnailInfo( - height = bitmapThumbnail.height.toLong(), width = bitmapThumbnail.width.toLong(), + height = bitmapThumbnail.height.toLong(), mimetype = mimeTypeToThumbnailMimeType(mimeType), size = thumbnailFile.length() ), diff --git a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/VideoCompressor.kt b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/VideoCompressor.kt index c21bd301ef..04bffd6c94 100644 --- a/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/VideoCompressor.kt +++ b/libraries/mediaupload/impl/src/main/kotlin/io/element/android/libraries/mediaupload/impl/VideoCompressor.kt @@ -61,8 +61,8 @@ class VideoCompressor @Inject constructor( val width = metadata?.width ?: Int.MAX_VALUE val height = metadata?.height ?: Int.MAX_VALUE - val videoResizeEffect = videoCompressorConfig.videoCompressorHelper?.let { - val outputSize = it.getOutputSize(Size(width, height)) + val videoResizeEffect = run { + val outputSize = videoCompressorConfig.videoCompressorHelper.getOutputSize(Size(width, height)) if (metadata?.rotation == 90 || metadata?.rotation == 270) { // If the video is rotated, we need to swap width and height Presentation.createForWidthAndHeight( @@ -89,19 +89,14 @@ class VideoCompressor @Inject constructor( val inputMediaItem = MediaItem.fromUri(uri) val outputMediaItem = EditedMediaItem.Builder(inputMediaItem) .setFrameRate(newFrameRate) - .run { - if (videoResizeEffect != null) { - setEffects(Effects(emptyList(), listOf(videoResizeEffect))) - } else { - this - } - } + .setEffects(Effects(emptyList(), listOf(videoResizeEffect))) .build() val encoderFactory = DefaultEncoderFactory.Builder(context) .setRequestedVideoEncoderSettings( VideoEncoderSettings.Builder() - .setBitrateMode(MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_CBR) + // Use VBR which is generally better for quality and compatibility, although slightly worse for file size + .setBitrateMode(MediaCodecInfo.EncoderCapabilities.BITRATE_MODE_VBR) .setBitrate(newBitrate) .build() )