GithubHelp home page GithubHelp logo

numandev1 / react-native-compressor Goto Github PK

View Code? Open in Web Editor NEW
776.0 11.0 81.0 2.44 MB

🗜️Compress Image, Video, and Audio same like Whatsapp 🚀✨

License: MIT License

Java 3.52% JavaScript 1.28% TypeScript 18.11% C 0.04% Objective-C 0.68% Swift 32.26% Ruby 1.63% Objective-C++ 1.50% Shell 0.79% Kotlin 40.18%
compress compression react-native compress-images compress-videos compress-audio video audio image whatsapp

react-native-compressor's Introduction


GitHub Repo stars GitHub Repo stars GitHub Repo stars GitHub Repo stars npm

REACT-NATIVE-COMPRESSOR is a react-native package, which helps us to Compress Image, Video, and Audio before uploading, same like Whatsapp without knowing the compression algorithm

Auto/Manual Compression | Background Upload | Download File | Create Video Thumbnail


               

🗜️Compress Image, Video, and Audio same like Whatsapp

Why should we use react-native-compress over FFmpeg?

We should use react-native-compressor instead of FFmpeg because react-native-compressor gives you same compression of Whatsapp (Image, Video, and Audio) without knowing the algorithm of compression + it is lightweight only increase 50 KB Size Size in APK while FFmpeg increase ~> 9 MB Size in APK, and we have to give manual image/video/Audo size and quality as well as

If you find this package useful hit the star 🌟

Would you like to support me?


See the Benchmarks

Table of Contents

Open Table of Contents

Installation

yarn add react-native-compressor

you can give feedback on Discord channel

Managed Expo

expo install react-native-compressor

Add the Compressor plugin to your Expo config (app.json, app.config.json or app.config.js):

{
  "name": "my app",
  "plugins": ["react-native-compressor"]
}

Finally, compile the mods:

expo prebuild

To apply the changes, build a new binary with EAS:

eas build

Automatic linking (for React Native >= 0.60 only)

Automatic linking is supported for both Android and IOS

Linking (for React Native <= 0.59 only)

Note: If you are using react-native version 0.60 or higher you don't need to link this package.

react-native link react-native-compressor

Manual installation

iOS

  1. In XCode, open Podfile
  2. paste this line pod 'react-native-compressor', :path => '../node_modules/react-native-compressor' into Podfile
  3. run this command inside ios folder pod install
  4. Run your project (Cmd+R)<

Android

  1. Open up android/app/src/main/java/[...]/MainActivity.java
  • Add import com.reactnativecompressor.CompressorPackage; to the imports at the top of the file
  • Add new CompressorPackage() to the list returned by the getPackages() method
  1. Append the following lines to android/settings.gradle:
    include ':react-native-compressor'
    project(':react-native-compressor').projectDir = new File(rootProject.projectDir,'../node_modules/react-native-compressor/android')
    
  2. Insert the following lines inside the dependencies block in android/app/build.gradle:
      compile project(':react-native-compressor')
    

Usage

Image

Automatic Image Compression Like Whatsapp
import { Image } from 'react-native-compressor';

const result = await Image.compress('file://path_of_file/image.jpg');
// OR
const result = await Image.compress('https://path_of_file/image.jpg', {
  progressDivider: 10,
  downloadProgress: (progress) => {
    console.log('downloadProgress: ', progress);
  },
});

Here is this package comparison of images compression with WhatsApp

Manual Image Compression
import { Image } from 'react-native-compressor';

const result = await Image.compress('file://path_of_file/image.jpg', {
  compressionMethod: 'manual',
  maxWidth: 1000,
  quality: 0.8,
});

Video

Automatic Video Compression Like Whatsapp
import { Video } from 'react-native-compressor';

const result = await Video.compress(
  'file://path_of_file/BigBuckBunny.mp4',
  {},
  (progress) => {
    console.log('Compression Progress: ', progress);
  }
);

//OR

const result = await Video.compress(
  'https://example.com/video.mp4',
  {
    progressDivider: 10,
    downloadProgress: (progress) => {
      console.log('downloadProgress: ', progress);
    },
  },
  (progress) => {
    console.log('Compression Progress: ', progress);
  }
);

Here is this package comparison of video compression with WhatsApp

Manual Video Compression
import { Video } from 'react-native-compressor';

const result = await Video.compress(
  'file://path_of_file/BigBuckBunny.mp4',
  {
    compressionMethod: 'manual',
  },
  (progress) => {
    console.log('Compression Progress: ', progress);
  }
);
Cancel Video Compression
import { Video } from 'react-native-compressor';

let cancellationVideoId = '';

const result = await Video.compress(
  'file://path_of_file/BigBuckBunny.mp4',
  {
    compressionMethod: 'auto',
    // getCancellationId for get video id which we can use for cancel compression
    getCancellationId: (cancellationId) =>
      (cancellationVideoId = cancellationId),
  },
  (progress) => {
    if (backgroundMode) {
      console.log('Compression Progress: ', progress);
    } else {
      setCompressingProgress(progress);
    }
  }
);

// we can cancel video compression by calling cancelCompression with cancel video id which we can get from getCancellationId function while compression
Video.cancelCompression(cancellationVideoId);

Audio

import { Audio } from 'react-native-compressor';

const result = await Audio.compress(
  'file://path_of_file/file_example_MP3_2MG.wav', // recommended wav file but can be use mp3 file
  { quality: 'medium' }
);

// OR

const result = await Audio.compress(
  'file://path_of_file/file_example_MP3_2MG.wav', // recommended wav file but can be use mp3 file
  {
    bitrate: 64000,
    samplerate: 44100,
    channels: 1,
  }
);

Background Upload

import { backgroundUpload } from 'react-native-compressor';

const headers = {};

const uploadResult = await backgroundUpload(
  url,
  fileUrl,
  { httpMethod: 'PUT', headers },
  (written, total) => {
    console.log(written, total);
  }
);

//OR

const uploadResult = await backgroundUpload(
  url,
  fileUrl,
  { uploadType: UploadType.MULTIPART, httpMethod: 'POST', headers },
  (written, total) => {
    console.log(written, total);
  }
);

Cancel Background Upload

for cancellation Upload, there is two ways

  1. by calling, cancelUpload function
  2. by calling abort function
cancelUpload (support single and all)
import { cancelUpload, backgroundUpload } from 'react-native-compressor';

// if we will call without passing any param then it will remove last pushed uploading
cancelUpload()

// if you pass true as second param then it will cancel all the uploading
cancelUpload("",true)

// if there is multiple files are uploading, and you wanna cancel specific uploading then you pass specific video id like this
let videoId=''
const uploadResult = await backgroundUpload(
  url,
  fileUrl,
  { httpMethod: 'PUT',  getCancellationId: (cancellationId) =>(videoId = cancellationId), },
  (written, total) => {
    console.log(written, total);
  }
);
cancelUpload(videoId)
cancel by calling abort
import { backgroundUpload } from 'react-native-compressor';

const abortSignalRef = useRef(new AbortController());

const uploadResult = await backgroundUpload(
  url,
  fileUrl,
  { httpMethod: 'PUT' },
  (written, total) => {
    console.log(written, total);
  },
  abortSignalRef.current.signal
);

abortSignalRef.current?.abort(); // this will cancel uploading

Download File

import { download } from 'react-native-compressor';

const downloadFileUrl = await download(url, (progress) => {
  console.log('downloadProgress: ', progress);
});

Video Thumbnail

import { createVideoThumbnail, clearCache } from 'react-native-compressor';

const thumbnail = await createVideoThumbnail(videoUri);

await clearCache(); // this will clear cache of thumbnails cache directory

API

Image

ImageCompressor

  • compress(value: string, options?: CompressorOptions): Promise<string>

    Compresses the input file URI or base-64 string with the specified options. Promise returns a string after compression has completed. Resizing will always keep the original aspect ratio of the image, the maxWidth and maxHeight are used as a boundary.

CompressorOptions

  • compressionMethod: compressionMethod (default: "auto")

    if you want to compress images like whatsapp then make this prop auto. Can be either manual or auto, defines the Compression Method.

  • downloadProgress?: (progress: number) => void;

    it is callback, only trigger when we pass image url from server

  • progressDivider?: number (default: 0)

    we uses it when we use downloadProgress

  • maxWidth: number (default: 1280)

    The maximum width boundary used as the main boundary in resizing a landscape image.

  • maxHeight: number (default: 1280)

    The maximum height boundary used as the main boundary in resizing a portrait image.

  • quality: number (default: 0.8)

    The quality modifier for the JPEG and PNG file format, if your input file is JPEG and output file is PNG then compressed size can be increase

  • input: InputType (default: uri)

    Can be either uri or base64, defines the contentents of the value parameter.

  • output: OutputType (default: jpg)

    The quality modifier for the JPEG file format, can be specified when output is PNG but will be ignored. if you wanna apply quality modifier then you can enable disablePngTransparency:true, Note: if you png image have no transparent background then enable disablePngTransparency:true modifier is recommended

  • disablePngTransparency: boolean (default: false)

    when user add output:'png' then by default compressed image will have transparent background, and quality will be ignored, if you wanna apply quality then you have to disablePngTransparency like disablePngTransparency:true, it will convert transparent background to white

  • returnableOutputType: ReturnableOutputType (default: uri)

    Can be either uri or base64, defines the Returnable output image format.

if you wanna get image metadata (exif) then read this

Video

  • compress(url: string, options?: videoCompresssionType , onProgress?: (progress: number)): Promise<string>
  • cancelCompression(cancellationId: string): void

    we can get cancellationId from getCancellationId which is the callback method of compress method options

  • activateBackgroundTask(onExpired?: (data: any) => void): Promise<any>

    if you wanna compress video while app is in backgroup then you should call this method before compression

  • deactivateBackgroundTask(): Promise<any>

    if you call activateBackgroundTask method, then after video compression, you should call deactivateBackgroundTask for disable background task mode.

  • getCancellationId: function

    getCancellationId is a callback function that gives us compress video id, which can be used in Video.cancelCompression method to cancel the compression

videoCompresssionType

  • compressionMethod: compressionMethod (default: "manual")

    if you want to compress videos like whatsapp then make this prop auto. Can be either manual or auto, defines the Compression Method.

  • downloadProgress?: (progress: number) => void;

    it is callback, only trigger when we pass image url from server

  • progressDivider?: number (default: 0)

    we uses it when we use downloadProgress/onProgress

  • maxSize: number (default: 640)

    The maximum size can be height in case of portrait video or can be width in case of landscape video.

  • bitrate: number

    bitrate of video which reduce or increase video size. if compressionMethod will auto then this prop will not work

  • minimumFileSizeForCompress: number (default: 0)

    previously default was 16 but now it is 0 by default. 0 mean 0mb. This is an offset, which you can set for minimumFileSizeForCompress will allow this package to dont compress less than or equal to minimumFileSizeForCompress ref #26

if you wanna get video metadata then read this

Audio

  • compress(url: string, options?: audioCompresssionType): Promise<string>
    Android: recommended to use wav file as we convert mp3 to wav then apply bitrate

audioCompresssionType

  • quality?: qualityType (default: medium)

    we can also control bitrate through quality. qualityType can be low | medium | high

  • bitrate?: number Range [64000-320000]

    we can control bitrate of audio through bitrate, it should be in the range of 64000-320000

  • samplerate?: number Range [44100 - 192000]

    we can control samplerate of audio through samplerate, it should be in the range of 44100 - 192000

  • channels?: number Typically 1 or 2

    we can control channels of audio through channels, Typically 1 or 2

Background Upload

  • backgroundUpload: (url: string, fileUrl: string, options: UploaderOptions, onProgress?: ((writtem: number, total: number) => void) | undefined) => Promise< any >
  • UploaderOptions
export enum UploadType {
  BINARY_CONTENT = 0,
  MULTIPART = 1,
}

export enum UploaderHttpMethod {
  POST = 'POST',
  PUT = 'PUT',
  PATCH = 'PATCH',
}

export declare type HTTPResponse = {
  status: number;
  headers: Record<string, string>;
  body: string;
};

export declare type HttpMethod = 'POST' | 'PUT' | 'PATCH';

export declare type UploaderOptions = (
  | {
      uploadType?: UploadType.BINARY_CONTENT;
      mimeType?: string;
    }
  | {
      uploadType: UploadType.MULTIPART;
      fieldName?: string;
      mimeType?: string;
      parameters?: Record<string, string>;
    }
) & {
  headers?: Record<string, string>;
  httpMethod?: UploaderHttpMethod;
  getCancellationId?: (cancellationId: string) => void;
};

Note: some of the uploader code is borrowed from Expo I tested file uploader on this backend Nodejs-File-Uploader

Cancel Background Upload

for cancellation Upload, there is two ways, you can use one of it

  • cancelUpload: ( uuid?: string, shouldCancelAll?: boolean) => void
    1. If we call without passing any param then it will remove the last pushed uploading
    2. If you pass true as the second param then it will cancel all the uploading
    3. if there is multiple files are uploading, and you wanna cancel specific uploading then you pass a specific video ID like this
  • we can use AbortController in backgroundUpload Usage

    const abortSignalRef = useRef(new AbortController());

    abortSignalRef.current?.abort();

Download

  • download: ( fileUrl: string, downloadProgress?: (progress: number) => void, progressDivider?: number ) => Promise< string >

Create Video Thumbnail and Clear Cache

  • createVideoThumbnail( fileUrl: string, options: {header:Object} ): Promise<{ path: string;size: number; mime: string; width: number; height: number; }>

    it will save the thumbnail of the video into the cache directory and return the thumbnail URI which you can display

  • clearCache(cacheDir?: string): Promise< string >

    it will clear the cache that was created from createVideoThumbnail, in future this clear cache will be totally customized

Get Metadata Of Video

if you want to get metadata of video than you can use this function

import { getVideoMetaData } from 'react-native-compressor';

const metaData = await getVideoMetaData(filePath);
{
	"duration": 20.11,
	"extension": "mp4",
	"height": 1080,
	"size": 16940.0,
	"width": 1920
}
  • getVideoMetaData(path: string)

Get Metadata Of Image

if you want to get metadata of video than you can use this function

import { getImageMetaData } from 'react-native-compressor';

const metaData = await getImageMetaData(filePath);
{
  "ImageWidth": 4032,
  "ImageHeight": 3024,
  "Orientation": 3,
  "size": 4127057,
  "extension": "jpg",
  "exif":{...}
}
  • getImageMetaData(path: string)

Get Real Path

if you want to convert

  • content:// to file:/// for android
  • ph:// to file:/// for IOS

then you can call getRealPath function like this

import { getRealPath } from 'react-native-compressor';

const realPath = await getRealPath(fileUri, 'video'); //   file://file_path.extension
  • getRealPath(path: string, type: string = 'video'|'image')

Get Temp file Path

if you wanna make random file path in cache folder then you can use this method like this

import { generateFilePath } from 'react-native-compressor';

const randomFilePathForSaveFile = await generateFilePath('mp4'); //   file://file_path.mp4
  • generateFilePath(fileextension: string)

Benchmark

Whatsapp: compresses Images,Videos and Audios in every effect way



Contributing

See the contributing guide to learn how to contribute to the repository and the development workflow.

License

MIT

react-native-compressor's People

Contributors

alariej avatar atultiwaree avatar cd-butterfly avatar closetothe avatar harwindersingh15 avatar luizaugustoventura avatar madou90 avatar mlecoq avatar murat-mehmet avatar numandev1 avatar parlinsqe avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-native-compressor's Issues

Error: Native module not found

I have an issue with Video Compressor.

const result = await Video.compress('./853.mp4');
console.log('dfff', result);

Result - Error: Native module not found

The following Swift pods cannot yet be integrated as static libraries:

The Swift pod react-native-compressor depends upon React-Core, which does not define modules. To opt into those targets generating module maps (which is necessary to import them from Swift when building as static libraries), you may set use_modular_headers! globally in your Podfile, or specify :modular_headers => true for particular dependencies.

Above error throws when installing pod for ios

Getting error while image compression.

Please check below attached screenshot for more details and also i added my code.

Image.compress(path, {
maxWidth:width,
maxHeight:.height,
input: 'uri',
output: 'jpg',
quality: 0.5,
returnableOutputType: 'uri',
})
.then(async (compressedFileUri) => {
console.log('===========image compressed=============' + JSON.stringify(detail, null, 2))

        const detail = await getFileInfo(compressedFileUri);
      })
      .catch((e) => {
        console.log( '==============error in compression===================');
      });

Simulator Screen Shot - iPhone 12 Pro Max - 2021-06-23 at 18 08 02

Video compression not working

Image Compression is working fine but video compression is returning error null. I tried different size videos but every videos is giving nulll error

Return compressed video metadata

Currently, implementation return only compressed video uri, this work well in most situation but in some situation, video extra metadata like width, height, size, duration, extension and more are required when user need those metadata to control video base on them.

Is any plan to expose metadata for video?

Is it possible to cancel a ongoing video compression?

Hello,

I would like to allow the user to cancel the video compression progress.

example use case: the user selected the wrong video and wants to select a different one. We don't want him to wait for the whole compression time.

thank you in advance!

Can't upload compressed video to the server

I am getting compressed video file path as "file://data/user/0/com.ikonikgolf.ikonik/cache/88a6b03a-23c2-4810-9158-15be29c99105.mp4",
When I tried to upload this file as a multipart form. I am getting No network error.

I can upload the original video file with URI : content://com.miui.gallery.open/raw/%2Fstorage%2Femulated%2F0%2FDCIM%2FCamera%2FVID_20210904_102656.mp4

Error: Network Error
at createError (createError.js:16)
at EventTarget.handleError (xhr.js:84)
at EventTarget.dispatchEvent (event-target-shim.js:818)
at EventTarget.setReadyState (XMLHttpRequest.js:575)
at EventTarget.__didCompleteResponse (XMLHttpRequest.js:389)
at XMLHttpRequest.js:502
at RCTDeviceEventEmitter.emit (EventEmitter.js:189)
at MessageQueue.__callFunction (MessageQueue.js:425)
at MessageQueue.js:112
at MessageQueue.__guard (MessageQueue.js:373)

unable to find compressed image file location on my android emulator.

1-i went through the installation process and successfully installed the package and compressed my image.
2-After compression i am getting the response uri : file:///data/user/0/com.mob.innerdots/cache/b45c035e-155e-4b05-8c1e-908cd338fad3.jpg

my issue:
i am not able to get to this uri location in my android emulator. i want to check the properties of compressed image and export it to other file location.

kindly suggest some idea to get this image.

[SUGGESTION ] - Replace VideoSlimer as video compressor on Android

https://github.com/zolad/VideoSlimmer seems like not work well with video with modern aspect ratios.

If you do various tests on various video aspect ratios, the module works well with traditional ratios like 4:3 or 16:9.

While rotating video on a modern ratio like 18:9 on 1920x1080. This also happens in the test video by the module author.

Author compress video with 1920x1080 and output becomes 200x360, The video actually reversed.
Screen Shot 2022-01-09 at 1 46 04 AM

Cannot read property 'compress' of undefined

const result = await Video.compress(
res.uri, // video uri
{
compressionMethod: 'auto',
},
(progress) => {
if (backgroundMode) {
console.log('Compression Progress: ', progress);
} else {
setCompressingProgress(progress);
}
}
);

Crash when compress video select from galery [iOS]

When I am trying to compress video from the gallery the app crash suddenly. but when I record video from the camera it's working well.
this happens only on iOS

dataUri pick from gallery:
file:///private/var/mobile/Containers/Data/Application/F2A6A75C-B834-427A-A565-EAD9E47DBE21/tmp/react-native-image-crop-picker/8C70B1F1-D253-42D0-B6F6-E236B283E475.mp4

dataUri take from camera:
file:///var/mobile/Containers/Data/Application/F2A6A75C-B834-427A-A565-EAD9E47DBE21/Library/Caches/Camera/BA027EA2-6AA0-4698-A50A-BC456FA4230E.mov

"react-native": "^0.63.4",
"react-native-image-crop-picker": "^0.36.0",
"react-native-compressor": "^0.5.2",
"react-native-camera": "^4.0.0",

index.d.ts for videoCompressorType is missing maxSize field in 1.0.3

I'm adding the maxSize parameter to the options field for Video.compress, but looking at the Typescript declarations for that type in the 1.0.3 release on npm, maxSize is missing:

declare type videoCompresssionType = {
    bitrate?: number;
    compressionMethod?: compressionMethod;
};

Possible the declarations are stale from the last release?

Resolution fail!

Hello

I select portrait video,
file after compression is landscape video

Compression value is empty

im getting this error in the image compressor
image

these are the args i pass to the compress function:

      const res = await ImageCompress.compress(img.path, {
        compressionMethod: 'auto',
      });
      setCompressed(res);

what is the "Compression value" that i need to input? where?

Video is not resizing

Hi! I am having troubles with video compression

"react-native-compressor": "1.2.0"
"react-native": "0.66.1"

Video.compress(file.path, {
        // compressionMethod: 'manual',
        //minimumFileSizeForCompress: 10,
        maxSize: 100,
      })
        .then(res => {...})
        .catch(console.log);

original file
original file is 42mb 1080 × 1920 30 sec
compressed always 3.2 mb 360 × 568

i need to do something to make video 600x1000
i have tried all params from doc but nothing changes( mb i am doing something wrong
and i tried different video

onProgress callback for images

Hey folks, firstly thanks for creating this library 🤙🏼 Do you have any plans on adding the onProgress callback to image-compression, aswell? Would be pretty useful imo.

Video not compressing below 10 mb

Hi, first of all I appreciate your effort for making this package. Gone through your excel for video compress, can you do the compression for video below 10 mb? or else can you refer some other package for the same?

App crashes automatically after selecting video

The crash is happening when we select compressionMethod: 'manual'
await Video.compress(
imgData.path,
{
compressionMethod: 'manual',
maxSize: imgData.height,
bitrate: 450000,
},
progress => {
console.log('prog===>', progress);
},
);
java.lang.RuntimeException: An error occurred while executing doInBackground()
at android.os.AsyncTask$4.done(AsyncTask.java:399)
at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:383)
at java.util.concurrent.FutureTask.setException(FutureTask.java:252)
at java.util.concurrent.FutureTask.run(FutureTask.java:271)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
at java.lang.Thread.run(Thread.java:919)
Caused by: java.lang.IllegalStateException: Failed to stop the muxer
at android.media.MediaMuxer.nativeStop(Native Method)
at android.media.MediaMuxer.stop(MediaMuxer.java:466)
at com.zolad.videoslimmer.VideoSlimEncoder.releaseCoder(VideoSlimEncoder.java:622)
at com.zolad.videoslimmer.VideoSlimEncoder.convertVideo(VideoSlimEncoder.java:391)
at com.zolad.videoslimmer.VideoSlimTask.doInBackground(VideoSlimTask.java:30)
at com.zolad.videoslimmer.VideoSlimTask.doInBackground(VideoSlimTask.java:11)
at android.os.AsyncTask$3.call(AsyncTask.java:378)
at java.util.concurrent.FutureTask.run(FutureTask.java:266)
at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:289) 
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) 
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) 
at java.lang.Thread.run(Thread.java:919) 
2021-07-27 18:51:03.330 25348-25644/com.dt.thanthiwhistle E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #3

Auto Video compression Method not working getting "Native module not found" error

Auto Video compression Method not working getting "Native module not found" error

Video compression working with this version:
"react": "17.0.1",
"react-native": "0.64.2",
"react-native-compressor": "^0.5.3",

Video compression not working with this version:
"react": "17.0.2",
"react-native": "0.66.1",
"react-native-compressor": "^1.1.1"

This is the code which we are using:

await Video.compress(filePath,
                { compressionMethod: 'auto' },
                (progress) => { isCompress = true }
            ).then((path) => {
                console.log(path, 'compressed path');
                
            }).catch((err) => { alert("err: "+err); })

Attached the error screenshot also:

WhatsApp Image 2021-12-11 at 12 02 32 PM

"Error: Native module not found" when uuid package gets called

We currently have the problem that when we call the Video.compress of your package we are getting a Error: Native Module not found error. Solution was to install the react-native-get-random-values dependency on our own.

According to uuidjs/uuid#570 this issue can be solved by moving react-native-get-random-values in your package.json from the dependencies to the peer-dependencies.

I created a pull-request with the suggested change: #60

Error while compressing video from android image picker

I am getting error while calling Video.compress() method.

const result = await Video.compress(
path,
{
compressionMethod: 'auto',
},
(progress) => {
console.log('Compression Progress: ', progress);
}
);

I have tried to pass uri and fileName to the compress method, which I am getting from react native image picker response(Video selected from Android galley)
{
"fileName": "/storage/emulated/0/DCIM/Camera/VID_20210926_150538.mp4",
"duration": 4,
"fileSize": 9501100,
"uri": "content://com.miui.gallery.open/raw/%2Fstorage%2Femulated%2F0%2FDCIM%2FCamera%2FVID_20210926_150538.mp4"
}

Error :

Error: null
at Object.promiseMethodWrapper [as compress] (C:\Users\GOKULDAS\Desktop\Subin\ikonik\Ikonik-react-native\node_modules\react-native\Libraries\BatchedBridge\NativeModules.js:103)
at compress$ (C:\Users\GOKULDAS\Desktop\Subin\ikonik\Ikonik-react-native\node_modules\react-native-compressor\src\Video\index.tsx:108)
at tryCatch (C:\Users\GOKULDAS\Desktop\Subin\ikonik\Ikonik-react-native\node_modules\regenerator-runtime\runtime.js:45)
at Generator.invoke [as _invoke] (C:\Users\GOKULDAS\Desktop\Subin\ikonik\Ikonik-react-native\node_modules\regenerator-runtime\runtime.js:274)
at Generator.prototype. [as next] (C:\Users\GOKULDAS\Desktop\Subin\ikonik\Ikonik-react-native\node_modules\regenerator-runtime\runtime.js:97)
at tryCatch (C:\Users\GOKULDAS\Desktop\Subin\ikonik\Ikonik-react-native\node_modules\regenerator-runtime\runtime.js:45)
at invoke (C:\Users\GOKULDAS\Desktop\Subin\ikonik\Ikonik-react-native\node_modules\regenerator-runtime\runtime.js:135)
at C:\Users\GOKULDAS\Desktop\Subin\ikonik\Ikonik-react-native\node_modules\regenerator-runtime\runtime.js:170
at tryCallTwo (C:\Users\GOKULDAS\Desktop\Subin\ikonik\Ikonik-react-native\node_modules\promise\setimmediate\core.js:45)
at doResolve (C:\Users\GOKULDAS\Desktop\Subin\ikonik\Ikonik-react-native\node_modules\promise\setimmediate\core.js:200)

Error: width and height must be > 0

I have facing this issue, Can you please Help me out.

Error: width and height must be > 0
promiseMethodWrapper@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:2568:45
compress@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:120311:40
compressVideoFile$
tryCatch@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:24265:23
invoke@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:24435:32
tryCatch@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:24265:23
invoke@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:24337:30
http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:24367:19
tryCallTwo@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:28951:9
doResolve@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:29115:25
Promise@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:28974:14
callInvokeWithMethodAndArg@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:24366:33
enqueue@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:24371:157
http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:24386:69

tryCallOne@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:28942:16
http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:29043:27
http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:29634:26
_callTimer@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:29530:17
_callReactNativeMicrotasksPass@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:29569:17
callReactNativeMicrotasks@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:29779:44
__callReactNativeMicrotasks@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:3049:46
http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:2827:45
__guard@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:3032:15
flushedQueue@http://localhost:8082/index.bundle?platform=android&dev=true&minify=false&app=com.instapoc&modulesOnly=false&runModule=true:2826:21
flushedQueue@[native code]
invokeCallbackAndReturnFlushedQueue@[native code]

Device: One plus 7

IOS 14 compressed url is not exist

After compressing photo, the result url is not exist.

This is log:

WARN Could not find image file://private/var/mobile/Containers/Data/Application/9AD81D94-BF91-4398-BC1D-280B5C864A9B/tmp/98F1A7FE-F2AA-41E7-859B-86AFE1D6E392.jpg

[IOS] Failed to use "ph:://" image uri

Current behavior

Throw error with cannot read file
Error processing request body: Error Domain=NSCocoaErrorDomain Code=260 "Не удалось открыть файл «C25D1B52-2740-494B-9FDC-6E69449B7DF0.jpg», так как такого файла не существует." UserInfo={NSFilePath=/private/var/mobile/Containers/Data/Application/711CAA50-1640-46E5-8E0A-86B9C439414E/tmp/C25D1B52-2740-494B-9FDC-6E69449B7DF0.jpg, NSUnderlyingError=0x2829d3660 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}

example uri ph://3740F77F-A886-4BEA-8B2C-47D8030A06CD/L0/001

Expected behavior

Read and compress file

Platform

  • iOS

React Native Version

"react-native": "^0.66.4",

React Native Compressor Version

"react-native-compressor": "^1.2.1",

Reproduction

  1. Take image from "@react-native-community/cameraroll" on IOS with uri like "ph:://"
  2. Pass that uri in compress with { compressionMethod: 'auto' } params

Getting crash when compressing video in iOS

I'm facing a crash in iOS after selecting a video in the camera roll. It's happening for all videos.

The library i'm using for Cameraroll is @react-native-community/cameraroll.

The uri path that I'm passing to the compressVideo method is of the form ph://1ABDEA26-31B1-4EB0-B579-A7B8D8B49EED/L0/001. I even tried to use react-native-fs to use the path /var/mobile/Containers/Data/Application/4AF55096-E2CA-4BE1-93D5-2D252D226886/Library/Caches/IMG_1294.mp4 and the same crash still happens.

It's crashing at getFileSize method in VideoCompressor.swift file.

// crash happened here due to nil value for fileSizeValue
try? fileSizeValue = (fileURL?.resourceValues(forKeys: [URLResourceKey.fileSizeKey]).allValues.first?.value as! Double?)!  
   func getfileSize(forURL url: Any) -> Double {
        var fileURL: URL?
        var fileSize: Double = 0.0
        if (url is URL) || (url is String)
        {
            if (url is URL) {
                fileURL = url as? URL
            }
            else {
                fileURL = URL(fileURLWithPath: url as! String)
            }
            var fileSizeValue = 0.0
            try? fileSizeValue = (fileURL?.resourceValues(forKeys: [URLResourceKey.fileSizeKey]).allValues.first?.value as! Double?)!  // <-- crash happened here due to nil value for fileSizeValue

            if fileSizeValue > 0.0 {
                fileSize = (Double(fileSizeValue) / (1024 * 1024))
            }
        }
        return fileSize
    }

What's the expected path we should be passing to compressVideo assuming we are not using react-native-image-picker like in your example?

my react-native is v0.63, I'm using 0.5.9 version of the library.

[Unhandled promise rejection: TypeError: null is not an object (evaluating 'NativeVideoCompressor.compress')]

Hi,
I thank you very much for this library, I tried to use it on an mp4 file after a cam record, but I got this message in the title:
[Unhandled promise rejection: TypeError: null is not an object (evaluating 'NativeVideoCompressor.compress')]

my function component
const takeVideo = async () => {

if(camera){
    const data = await camera.recordAsync({
        quality : Camera.Constants.VideoQuality['16:9'],
        videoBitrate : 2*1000*1000,
        maxDuration : 120,
        maxFileSize : 40*1000*1000,
        mute: false

    })
    setRecord(data.uri);

    console.log(data.uri);
  try{  
    const result = await Video.compress(
     data.uri,
      {
        compressionMethod: 'auto',
      },
      (progress) => {
        
        console.log('Compression Progress Front: ', progress);
        
      }
    );

  } catch (err) {
    console.log('Error:', err);
  }

}
}

Error after adding module and starting expo project

Current behavior

Invariant Violation: Native module cannot be null.
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:104:6 in reportException
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:172:19 in handleException
at node_modules/react-native/Libraries/Core/setUpErrorHandling.js:24:6 in handleError
at node_modules/@react-native/polyfills/error-guard.js:49:36 in ErrorUtils.reportFatalError
at node_modules/metro-runtime/src/polyfills/require.js:204:6 in guardedLoadModule
at http://192.168.31.95:19000/index.bundle?platform=ios&dev=true&hot=false&minify=false:264912:3 in global code

Expected behavior

App starts

Platform

  • iOS (Android not tested)

React Native Version

Expo 44 and RN 0.64.3

React Native Compressor Version

1.5.0

Reproducible Steps And Demo

Install via yarn add or expo cli
Check that the app.json has been updated with the plugin property
Restart via expo start

Here is the full error message

Invariant Violation: Native module cannot be null.
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:104:6 in reportException
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:172:19 in handleException
at node_modules/react-native/Libraries/Core/setUpErrorHandling.js:24:6 in handleError
at node_modules/@react-native/polyfills/error-guard.js:49:36 in ErrorUtils.reportFatalError
at node_modules/metro-runtime/src/polyfills/require.js:204:6 in guardedLoadModule
at http://192.168.31.95:19000/index.bundle?platform=ios&dev=true&hot=false&minify=false:264912:3 in global code

Invariant Violation: "main" has not been registered. This can happen if:
* Metro (the local dev server) is run from the wrong folder. Check if Metro is running, stop it and restart it in the current project.
* A module failed to load due to an error and `AppRegistry.registerComponent` wasn't called.
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:104:6 in reportException
at node_modules/react-native/Libraries/Core/ExceptionsManager.js:172:19 in handleException
at node_modules/react-native/Libraries/Core/setUpErrorHandling.js:24:6 in handleError
at node_modules/@react-native/polyfills/error-guard.js:49:36 in ErrorUtils.reportFatalError

I don't import the library in any file
If i remove the plugin property, app starts. As soon as i import the library in a component the error raises again

error in compressing video in react native v0.65.1

1-earlier i was using react native 0.61.5 and used this library for video and image compression. it was working as expected.
2- I have upgraded react native version to 0.65.1 and now image compression is working as expected but in video compression i am having errors.
3- i am sharing the screenshot of my code and error kindly suggest some idea to resolve it.
toshob3
toshob

Video compressionMethod manual don't work

Video compressionMethod manual don't work

"react-native": "0.63.4",
"react-native-compressor": "^1.1.1",

const result = await VideoCompressor.compress(
				video.path,
				{
				},
				(progress) => {
				```

iOS Xcode build error after manual installation

Current behavior

After doing the iOS manual setup(I'm on bare workflow btw, just ejected expo), running in xcode gives following build error:

error opening input file '/Users/......../node_modules/react-native-compressor/ios/Video/Compressor-Bridging-Header.h' (No such file or directory)

It looks like the react-native-compressor/ios/Video/ directory doesn't have Compressor-bridging-Header.h
So I copied Compressor-bridging-Header.h from react-native-compressor/ios/ to Video directory. then I get

/Users/.........../node_modules/react-native-compressor/ios/Video/Compressor-Bridging-Header.h:4:9: 'React/RCTBridgeModule.h' file not found

and

failed to emit precompiled header '/Users/........../Library/Developer/Xcode/DerivedData/.............../PrecompiledHeaders/Compressor-Bridging-Header-swift_2FUMZMGWGJN5S-clang_1UF3F5AFOI7VT.pch' for bridging header '/Users/.................node_modules/react-native-compressor/ios/Video/Compressor-Bridging-Header.h'

Expected behavior

Able to run on simulator without having build errors

Platform

  • iOS

React Native Version

0.63

React Native Compressor Version

0.5.11

Reproducible Steps And Demo

Yarn add the library and go through steps 1-4 of iOS manual installation.

VideoCompressEventEmitter.removeSubscription is not a function while compress a video file

Hello,

Im getting this error while compress video in auto compression mode.
here is my code, where

url = 'file:///data/user/0/com.qlandemo/cache/c850b3e6-6e20-49d2-a844-6102dd7243e8.mp4'

note - it's going in catch part every time & give me the error - VideoCompressEventEmitter.removeSubscription is not a function

can anyone help me to resolve it?

Thanks in advance.

Video.compress(
      url,
      {
        compressionMethod: 'auto',
      },
      progress => {
        if (backgroundMode) {
          console.log('ok');
        } else {
          console.log('progress', progress);
        }
      },
    )
      .then(res => console.log('res', res))
      .catch(error => console.log('err', error));

App getting crashed, if we upload a video of more than 20 minutes.

If we upload a video of more than 20 minutes, app is getting crashed, we have tested the video of duration 30 sec, 01 minute, 05 minutes, 10 minutes and 15 minutes, it's compressing fine, the video more than of 20 minutes is not compressing and giving us this log (I'm attaching the log of the RN-Debugger that we get, if we try to compress the 20min video). Kindly have a look into this.

-----------Debugger Logs---------------------------------
Failed to convert base64: Cannot Open
VideoCompressionScreen.js:91 error TypeError: Cannot read property 'path' of undefined
at _callee3$ (VideoCompressionScreen.js:80)
at tryCatch (runtime.js:63)
at Generator.invoke [as _invoke] (runtime.js:294)
at Generator.next (runtime.js:119)
at tryCatch (runtime.js:63)
at invoke (runtime.js:155)
at runtime.js:165
at tryCallOne (core.js:37)
at core.js:123
at JSTimers.js:248

Crash of video compression on Samsung J5

We are currently facing an error with the compression on a Samsung J5 device. It runs into an IllegalStateException in the VideoSlimmer.convertVideo() call.

We get the following stacktrace:

    android.media.MediaCodec.native_stop MediaCodec.java
    android.media.MediaCodec.stop MediaCodec.java:2251
    com.zolad.videoslimmer.VideoSlimEncoder.releaseCoder VideoSlimEncoder.java:613
    com.zolad.videoslimmer.VideoSlimEncoder.convertVideo VideoSlimEncoder.java:391
    com.zolad.videoslimmer.VideoSlimTask.doInBackground VideoSlimTask.java:30
    com.zolad.videoslimmer.VideoSlimTask.doInBackground VideoSlimTask.java:11
    android.os.AsyncTask$3.call AsyncTask.java:394
    java.util.concurrent.FutureTask.run FutureTask.java:266
    android.os.AsyncTask$SerialExecutor$1.run AsyncTask.java:305
    java.util.concurrent.ThreadPoolExecutor.runWorker ThreadPoolExecutor.java:1167
    java.util.concurrent.ThreadPoolExecutor$Worker.run ThreadPoolExecutor.java:641
    java.lang.Thread.run Thread.java:923

We found out, that in the com.zolad.videoslimmer package the releaseCoder() method has no proper exception handling if an encoder is already released. This results in the exception bubbling up into the react-native-compressor package.

Is there any chance that we can fix this in this library?

[Android] Throw error while compressing image

When compressing image with path follow: content://media/external/images/media/78550

It throw a error: [Error: Attempt to invoke virtual method 'int android.graphics.Bitmap.getWidth()' on a null object reference]

It look like content://media/external/images/media/78550 is not identified.

Division by zero crash in iOS when resolution is smaller than the specified output resolution

Calling compress on a source video of size 848x480 (as output by Ray-Ban Stories glasses) with a desired output of 1280x720 will yield a division by zero error in the makeVideoBitrate function. Specifically this line:

var remeasuredBitrate:Int = originalBitrate / (min(originalHeight/height,originalWidth/width))

Since originalHeight is an int, and height is a larger int, the result will be 0 (cuz we're doing integer division), so we'll end up dividing originalBitrate by 0 and creating a rift in time and space as we know it.

Actually, the entire function is doing some integer math that might have some issues, like:

let compressFactor:Float = 0.8
// a few lines later
remeasuredBitrate = remeasuredBitrate*Int(compressFactor)

Coercing compressFactor into an int is essentially a floor function - the decimal gets rounded down to zero. So this will always guarantee that the remeasuredBitrate is 0.

I'd be pleased to help advise how to fix this up, but as it's not really documented what this function is supposed to do, it's a bit tricky to tell what needs to happen solo. Happy to discuss more!

Color issues with HDR video on iOS

HDR videos (such as those recorded by the default camera on iOS) do not display correctly after compression on iOS. They look right on macos, but I'm assuming that's because I do not have an HDR display on my mac but the iPhone 13 Pro and Pixel 4a are trying to display as HDR. The colors are incorrect.

I used this sample video https://img.photographyblog.com/reviews/apple_iphone_13/sample_images/4K_60fps.mov (from https://www.photographyblog.com/reviews/apple_iphone_13_review) and got this output https://www.dropbox.com/s/4v54u393dfca80p/IMG_0022.MP4?dl=0.

Using ffprobe it looks like maybe the color space metadata of the video is transferred over to the compressed video but maybe the data is not HDR? I'm not sure about that, though.

Using the latest version of react-native-compressor (1.3.4) and react-native 0.66.3.

base64 on Android returns image path

There is some issue on android method to return base64 image and not the image path. On iOS it works like a charm. I was using "react-native-compressor": "^1.0.0" I've updated it to 1.0.3 but no luck with it

for (const image of images) {
    const compressed = await Image.compress(image.uri, {
      returnableOutputType: 'base64',
      compressionMethod: 'auto',
    })
  
    compressedImages.push({
      image: compressed,
      height: image.height,
      width: image.width,
    })
  }
  console.log(compressedImages)
...

return:

[{
  height: 2612,
  image: "file:///data/user/0/com.myapp/cache/e013a0a3-773c-4155-9001-746b456407a0.jpg",
  width: 1958
]}

It happens only with compressionMethod: 'auto'

Stretching resolution for potrait video with ratio of 18:9

The latest android device camera has support for 18:9. when a device uses this aspect ratio the video is rendered in portrait mode which is better for video reels platforms like TikTok.

When you need to compress down, on Android Video stretch and final resolution become landscape.

I have done this test for final compression resolution

https://github.com/Shobbak/react-native-compressor/blob/master/android/src/main/java/com/reactnativecompressor/Video/AutoVideoCompression/AutoVideoCompression.java#L39


   const actualWidth =1080
   const actualHeight = 1920
   const maxSize = 640
   
   
     const scale = actualWidth > actualHeight ? maxSize / actualWidth : maxSize / actualHeight;


     const resultWidth = Math.round(actualWidth * scale / 2) * 2;


     const resultHeight = Math.round(actualHeight * scale / 2) * 2;


     console.log({resultHeight,resultWidth}) // { resultHeight: 640, resultWidth: 360 }
     
    

Resolution is scaled perfect but when you pass to VideoSlimer it swaps width to height.

So final video become

 { resultHeight: 360, resultWidth: 640 }

@nomi9995 Try to record video in portrait mode probably at 18:9. There's a possibility that this new aspect ratio is not supported by https://github.com/zolad/VideoSlimmer

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.