numandev1 / react-native-compressor

🗜️Compress Image, Video, and Audio same like Whatsapp 🚀✨
MIT License
909 stars 85 forks source link

Change bitrate for video compression does nothing #217

Closed serolgames closed 11 months ago

serolgames commented 12 months ago

Hello, thank you for your package !

There is an issue :

Current behavior

When I set a custom bitrate for video compression it doesn't change anything (even with extreme values like 10 and 300000)

With an original video of 100MB this is the results :

-Bitrate of 2000 my video is 4MB on the output -Bitrate of 300000 my video is 4MB on the output -No bitrate my video is 4MB on the output

Of course the compressionMethod is set to "manual"

Expected behavior

The compression level should change according to that bitrate

Platform

React Native Version

0.72.5 (using expo)

React Native Compressor Version

1.8.12

Reproducible Steps And Demo

               const compressedVideo = await VideoCompressor.compress(
                    result.assets[0].uri,
                    {
                      progressDivider: 20,
                      maxSize: 1920,
                      bitrate: 2000,
                      compressionMethod: "manual",
                      downloadProgress: (progress) => {
                        console.log('downloadProgress: ', progress);
                      },
                    },
                    (progress) => {
                      console.log('Compression Progress: ', progress);
                    }
                );
github-actions[bot] commented 12 months ago

👋 @serolgames Thanks for opening your issue here! If you find this package useful hit the star🌟!

serolgames commented 11 months ago

Any news ?

numandev1 commented 11 months ago

@serolgames i have many other issues in the list https://github.com/users/numandev1/projects/4 , hopefully i will fix it in one or two week

numandev1 commented 11 months ago

@serolgames I tested with 200000 and 800000 bitrates the results are change on my side, can you recheck

serolgames commented 11 months ago

My bad !

I tested with 2000 and 30 000 but I should have tried with 20 000 and 300 000... I got confused with the range of values...

BTW what is the default bitrate applied ?

Thank you

numandev1 commented 11 months ago

@serolgames default bitrate is 80% of current video bitrate

https://github.com/numandev1/react-native-compressor/blob/1af07eac21afe03fc4c3a13f059fad24b96e2586/ios/Video/VideoMain.swift#L234C48-L234C65

can you suggest the any good format of bitrate so I can modify according to best way

serolgames commented 11 months ago

Ok so, after more work with your package I found that it can be significantly better for video compression.

I explain :

I want to use a % of quality. And I think a lot of developer will want to use that with your package (100% is the exact same bitrate of the original video, 50% is half of the bitrate of the original video)

I found this calcul to retrieve the bitrate:

            const videoCompressionLevel = 80; //80%
            const originalVideoMetadata = await getVideoMetaData(videoUri);

           /*
              at this point originalVideoMetadata = 
                         {
                           "creationTime": "20231108T125410.000Z",
                           "height": "1920",
                           "width": "1080",
                           "extension": "mp4",
                           "duration": "5", //in reality the duration should be 5.914...
                           "size": "6029.0"
                        }

           */
            const originalBitrate : number = originalVideoMetadata.size / ((originalVideoMetadata.duration / 60) * 0.0075) // sizeInKb / (minutes * 0.0075)
            const targetBitrate : number = Math.round(originalBitrate * (1 - (videoCompressionLevel / 100))) //Math round is used to get a rounded bitrate without decimals

In the concept it's working as expected. But it reality, NO. Simply because the getVideoMetaData gives the duration in rounded second with no decimals. So the originalBitrate won't ever be correct. And after my test it can't work because the targetBitrate will be wrong with some videos.

There is a quick fix for that : make the getVideoMetaData method return milliseconds instead of second

I've not found any other package that return the duration in milliseconds for react native... So your package would save me

Thank you !

numandev1 commented 11 months ago

@serolgames I am a little busy now, why do you did not use auto compression with the combination of maxSize https://github.com/numandev1/react-native-compressor#maxsize-number-default-640

when I am free I will add the milliseconds functionality 🙏

serolgames commented 11 months ago

Because I want more control other the quality and for specific videos some general settings won't fit

Ok no problem ! I'll wait, thank you. With that functionnality it will be an even more complete package. Deserves to buy you a cofee ;)

numandev1 commented 11 months ago

@serolgames fixed in 1.8.16

serolgames commented 10 months ago

Thank you for your work !

I tried and it's working PERFECTLY.

The result are even better than what I thought. Even with 40% compression you can barely spot the difference of quality and you save A LOT of memory (from my test, the compression % is equivalent to how much you want to reduce the file size. At 50% my file size is / 2.

For those who wonder how to make a % compression level there is my code :

                const originalVideoMetada : VideoMetada = await getVideoMetaData(uri) as any;
                const targetBitrate : number = Math.round((originalVideoMetada.size) / ((originalVideoMetada.duration / 60) * 0.0075) * (1 - (videoCompressionLevel / 100)))

                const compressedVideo = await VideoCompressor.compress(
                    uri,
                    {
                        progressDivider: 20,
                        maxSize: 1920,
                        bitrate: targetBitrate,
                        compressionMethod: "manual",
                        downloadProgress: (progress) => {
                            console.log('downloadProgress: ', progress);
                        },
                    },
                    (progress) => {
                        console.log('Compression Progress: ', progress);
                    }
                );
krmao commented 6 months ago

Thank you for your work !

I tried and it's working PERFECTLY.

The result are even better than what I thought. Even with 40% compression you can barely spot the difference of quality and you save A LOT of memory (from my test, the compression % is equivalent to how much you want to reduce the file size. At 50% my file size is / 2.

For those who wonder how to make a % compression level there is my code :

                const originalVideoMetada : VideoMetada = await getVideoMetaData(uri) as any;
                const targetBitrate : number = Math.round((originalVideoMetada.size) / ((originalVideoMetada.duration / 60) * 0.0075) * (1 - (videoCompressionLevel / 100)))

                const compressedVideo = await VideoCompressor.compress(
                    uri,
                    {
                        progressDivider: 20,
                        maxSize: 1920,
                        bitrate: targetBitrate,
                        compressionMethod: "manual",
                        downloadProgress: (progress) => {
                            console.log('downloadProgress: ', progress);
                        },
                    },
                    (progress) => {
                        console.log('Compression Progress: ', progress);
                    }
                );

32MB video compressed to 85MB size