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)
This commit is contained in:
Jorge Martin Espinosa 2025-08-26 10:41:07 +02:00 committed by GitHub
parent 9cd7c0ce49
commit 8c1c0b63bd
3 changed files with 11 additions and 12 deletions

View file

@ -27,7 +27,11 @@ class VideoCompressorHelper(
fun getOutputSize(inputSize: Size): Size { fun getOutputSize(inputSize: Size): Size {
val resultMajor = min(inputSize.major(), maxSize) val resultMajor = min(inputSize.major(), maxSize)
val aspectRatio = inputSize.major().toFloat() / inputSize.minor().toFloat() 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)
}
} }
/** /**

View file

@ -123,8 +123,8 @@ class ThumbnailFactory @Inject constructor(
val thumbnailResult = ThumbnailResult( val thumbnailResult = ThumbnailResult(
file = thumbnailFile, file = thumbnailFile,
info = ThumbnailInfo( info = ThumbnailInfo(
height = bitmapThumbnail.height.toLong(),
width = bitmapThumbnail.width.toLong(), width = bitmapThumbnail.width.toLong(),
height = bitmapThumbnail.height.toLong(),
mimetype = mimeTypeToThumbnailMimeType(mimeType), mimetype = mimeTypeToThumbnailMimeType(mimeType),
size = thumbnailFile.length() size = thumbnailFile.length()
), ),

View file

@ -61,8 +61,8 @@ class VideoCompressor @Inject constructor(
val width = metadata?.width ?: Int.MAX_VALUE val width = metadata?.width ?: Int.MAX_VALUE
val height = metadata?.height ?: Int.MAX_VALUE val height = metadata?.height ?: Int.MAX_VALUE
val videoResizeEffect = videoCompressorConfig.videoCompressorHelper?.let { val videoResizeEffect = run {
val outputSize = it.getOutputSize(Size(width, height)) val outputSize = videoCompressorConfig.videoCompressorHelper.getOutputSize(Size(width, height))
if (metadata?.rotation == 90 || metadata?.rotation == 270) { if (metadata?.rotation == 90 || metadata?.rotation == 270) {
// If the video is rotated, we need to swap width and height // If the video is rotated, we need to swap width and height
Presentation.createForWidthAndHeight( Presentation.createForWidthAndHeight(
@ -89,19 +89,14 @@ class VideoCompressor @Inject constructor(
val inputMediaItem = MediaItem.fromUri(uri) val inputMediaItem = MediaItem.fromUri(uri)
val outputMediaItem = EditedMediaItem.Builder(inputMediaItem) val outputMediaItem = EditedMediaItem.Builder(inputMediaItem)
.setFrameRate(newFrameRate) .setFrameRate(newFrameRate)
.run { .setEffects(Effects(emptyList(), listOf(videoResizeEffect)))
if (videoResizeEffect != null) {
setEffects(Effects(emptyList(), listOf(videoResizeEffect)))
} else {
this
}
}
.build() .build()
val encoderFactory = DefaultEncoderFactory.Builder(context) val encoderFactory = DefaultEncoderFactory.Builder(context)
.setRequestedVideoEncoderSettings( .setRequestedVideoEncoderSettings(
VideoEncoderSettings.Builder() 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) .setBitrate(newBitrate)
.build() .build()
) )