androidx / media

Jetpack Media3 support libraries for media use cases, including ExoPlayer, an extensible media player for Android
https://developer.android.com/media/media3
Apache License 2.0
1.73k stars 415 forks source link

Media3 Transformer increases bitrate #1707

Closed abaszadeyiterlan closed 1 month ago

abaszadeyiterlan commented 2 months ago

I wan't to encode videos using media3 transformers api, it works correctly but output bitrate bigger than input bitrate. althoug i am using the reducing frame rate, resolution, bitrate but it not works correctly, and it shows in video metada 1024x576 with 90 rotation. how can i fix that? Thanks in advance.
if (targetFrameRate != null) { if (overlayef != null && actualFrame != null) {

           val editedMediaItem = EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(false)

                .setEffects(
                    Effects(
                        listOf(),
                        listOf(
                            Presentation.createForWidthAndHeight(
                                576, 1024, LAYOUT_SCALE_TO_FIT
                            ), 
                            scale,
                            overlayef,
                            FrameDropEffect.createSimpleFrameDropEffect(actualFrame.toFloat(), targetFrameRate.toFloat())

                        )
                    )
                )

                .build()
            }
        }

        val compositionBuilder = Composition.Builder(EditedMediaItemSequence(editedMediaItem)).setHdrMode(Composition.HDR_MODE_EXPERIMENTAL_FORCE_INTERPRET_HDR_AS_SDR)
        val encoderFactory = DefaultEncoderFactory.Builder(myContext)

            .setRequestedVideoEncoderSettings(videoEncoderSettings)
            .setEnableFallback(true)

            .build()

        val transformer = Transformer.Builder(myContext)

            .setEncoderFactory(encoderFactory)

            .setAudioMimeType(MimeTypes.AUDIO_AAC)
            .setVideoMimeType(MimeTypes.VIDEO_H264)

            .addListener(transformerListener)

            .build()

        try {

                transformer.start(compositionBuilder.build(), ab11)

        } catch (e: PackageManager.NameNotFoundException) {

            Log.e("myExceptTAG", e.message.toString())

        }
droid-girl commented 2 months ago

Hi @abaszadeyiterlan , For the bitrate, please check this comment and #1154 Could you share your videoEncoderSettings setup as well? Are you using the FrameDropEffect to achive the desired framerate?

What is the reason you are using Composition.HDR_MODE_EXPERIMENTAL_FORCE_INTERPRET_HDR_AS_SDR? Have you tried HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL ?

abaszadeyiterlan commented 2 months ago

Hi @abaszadeyiterlan , For the bitrate, please check this comment and #1154 Could you share your videoEncoderSettings setup as well? Are you using the FrameDropEffect to achive the desired framerate?

What is the reason you are using Composition.HDR_MODE_EXPERIMENTAL_FORCE_INTERPRET_HDR_AS_SDR? Have you tried HDR_MODE_TONE_MAP_HDR_TO_SDR_USING_OPEN_GL ?

Thanks for response. Sorry i forgot adding my video encoder settings codes. val pixelsPerFrame = 576 1024 val bitsPerPixel = 0.07 0.1 val frRate = 30 val bitrate = (pixelsPerFrame bitsPerPixel frRate).toInt()

    videoEncoderSettings = VideoEncoderSettings.Builder()

        .setEncodingProfileLevel(
            MediaCodecInfo.CodecProfileLevel.AVCProfileMain,
            MediaCodecInfo.CodecProfileLevel.AVCLevel31
        )

        .setBitrate(bitrate)

        .build()  

And actually I also checked all of the HDR modes but not worked any of them. The original video's bitrate was 1.3 mbit, but with 720x1280 but with 576x1024 after transforming it raised to 1.6 mbit sometimes it can up to 2.5 mbit. Yes i am using the FrameDropEffect to targeted frame rate.

abaszadeyiterlan commented 2 months ago

i also used bitrate between 1000000 and 2000000 but why the input videos bitrate arount 1 mbit but the output over 2 mbit with lower resolutions?

abaszadeyiterlan commented 2 months ago

i modified my code like that ```

val mediaItemSp = MediaItem.fromUri(testUri).buildUpon()
            .setClippingConfiguration(
                MediaItem.ClippingConfiguration.Builder()
                    .setStartPositionMs(mStartPosition.toLong())
                    .setEndPositionMs(mEndPosition.toLong()).build()

            ).build()
        val inputMediaItem = mediaItemSp

        val overlayef: OverlayEffect? = myOverlayEf(myContext)

        var targetBitrate: Int? = null
        var targetFrameRate: Int? = null
        var editedMediaItem = EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(false)
            .build()
        var videoEncoderSettings = VideoEncoderSettings.Builder()
            .build()
        if (actualFrame != null) {
            if (actualFrame >= 30) {
                targetFrameRate = 30
            } else {
                targetFrameRate = null
            }
        }
        if (actualBitrate != null) {
            if (actualBitrate >= 2000000) {
                targetBitrate = 1800000
            }
            if (actualBitrate >= 1500000 && actualBitrate < 2000000) {
                targetBitrate = 1500000
            }

            if (actualBitrate >= 1000000 && actualBitrate < 1500000) {
                targetBitrate = 1000000
            }
            if (actualBitrate < 990000) {
                targetBitrate = null
            }
        }
        if (actualBitrate == null && actualFrame == null) {
            targetFrameRate = null
            targetBitrate = null
        }

        if (targetBitrate != null) {
            videoEncoderSettings = VideoEncoderSettings.Builder()
                .setBitrateMode(BITRATE_MODE_CBR)
                .setBitrate(targetBitrate)
                .build()
        }

        if (targetFrameRate != null) {
            if (overlayef != null && actualFrame != null) {
                editedMediaItem = EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(false)
                    .setEffects(
                        Effects(
                            listOf(),
                            listOf(
                                Presentation.createForWidthAndHeight(
                                    576, 1024, LAYOUT_SCALE_TO_FIT
                                ),
                                overlayef,
                                FrameDropEffect.createSimpleFrameDropEffect(
                                    actualFrame.toFloat(),
                                    targetFrameRate.toFloat()
                                )))).build()
            }
        } else {
            if (overlayef != null && actualFrame != null) {
                editedMediaItem = EditedMediaItem.Builder(inputMediaItem).setRemoveAudio(false)
                    .setEffects(
                        Effects(
                            listOf(),
                            listOf(
                                Presentation.createForWidthAndHeight(
                                    576, 1024, LAYOUT_SCALE_TO_FIT
                                ),
                                overlayef,
                               ))).build()
            }
        }

        val compositionBuilder = Composition.Builder(EditedMediaItemSequence(editedMediaItem))

        Log.e("getTheVideoMData", "actual bitrate $actualBitrate")
        Log.e("getTheVideoMData", "actual frame rate $actualFrame")
        Log.e("getTheVideoMData", "target bitrate $targetBitrate")
        Log.e("getTheVideoMData", "target frame rate $targetFrameRate") 
```but when i add                 .setBitrateMode(BITRATE_MODE_CBR)

the log shows VideoEncoder error: format=Format(null, null, null, video/avc, avc1.4D401F, -1, null, [1024, 576, 29.97003, ColorInfo(BT709, Limited range, SDR SMPTE 170M, false, 8bit Luma, 8bit Chroma)], [-1, -1]), colorInfo=ColorInfo(BT709, Limited range, SDR SMPTE 170M, false, 8bit Luma, 8bit Chroma) and my log getTheVideoMData E actual bitrate 1138922 E actual frame rate 30 E target bitrate 1000000 E target frame rate 30

abaszadeyiterlan commented 2 months ago

I get the output video's with third party apps such as MediaInfo, by the way it acutally increases the output video size with 720x1280 parameters the originial video was 7,37 mb but with 576x1024 my output raised to 11,1 mb.

abaszadeyiterlan commented 2 months ago

Any solution?

ychaparov commented 2 months ago

In most cases, you cannot use the input video bitrate as a guide for the output video bitrate generated by your Android device. The input video may have been generated by a more sophisticated encoder that may achieve good quality at low bitrate.

When using the default setBitrateMode(BITRATE_MODE_VBR) this comment applies.

Are you reporting that using .setBitrateMode(BITRATE_MODE_CBR) causes a failure in Transformer?

Please follow these instructions from the bug report template:

Bug Report After filing this issue please run adb bugreport shortly after reproducing the problem to capture a zip file, and email this to android-media-github@google.com with subject 'Issue #'.

Note: Logcat output is not the same as a full bug report, and is often missing information that's useful for diagnosing issues. Please ensure you're sending a full bug report zip file.