Code Monkey home page Code Monkey logo

videocompress's Introduction

video_compress

Compress videos, remove audio, manipulate thumbnails, and make your video compatible with all platforms through this lightweight and efficient library. 100% native code was used, we do not use FFMPEG as it is very slow, bloated and the GNU license is an obstacle for commercial applications. In addition, google chrome uses VP8/VP9, safari uses h264, and most of the time, it is necessary to encode the video in two formats, but not with this library. All video files are encoded in an MP4 container with AAC audio that allows 100% compatibility with safari, mozila, chrome, android and iOS.

Works on ANDROID, IOS and desktop (just MacOS for now).

Table of Contents

Lets Get Started

1. Depend on it

Add this to your package's pubspec.yaml file:

dependencies:
  video_compress: ^3.1.0

2. Install it

You can install packages from the command line:

with pub:

$  pub get

3. Import it

Now in your Dart code, you can use:

import 'package:video_compress/video_compress.dart';

How to use

Imports

import 'package:video_compress/video_compress.dart';
    

Video compression

MediaInfo mediaInfo = await VideoCompress.compressVideo(
  path,
  quality: VideoQuality.DefaultQuality, 
  deleteOrigin: false, // It's false by default
);

Check compress state

VideoQuality.isCompressing

Get memory thumbnail from VideoPath

final uint8list = await VideoCompress.getByteThumbnail(
  videopath,
  quality: 50, // default(100)
  position: -1 // default(-1)
);

Get File thumbnail from VideoPath

final thumbnailFile = await VideoCompress.getFileThumbnail(
  videopath,
  quality: 50, // default(100)
  position: -1 // default(-1)
);

Get media information

final info = await VideoCompress.getMediaInfo(videopath);

delete all cache files

  • Delete all files generated by this will delete all files located at 'video_compress', you shoule ought to know what are you doing.
await VideoCompress.deleteAllCache()

Listen the compression progress

class _Compress extends State<Compress> {

  Subscription _subscription;

  @override
  void initState() {
    super.initState();
    _subscription =
        VideoCompress.compressProgress$.subscribe((progress) {
      debugPrint('progress: $progress');
    });
  }

  @override
  void dispose() {
    super.dispose();
    _subscription.unsubscribe();
  }
}

TODO

  • Add the trim video function
  • Add cancel function to Android

Methods

Functions Parameters Description Returns
getByteThumbnail String path[video path], int quality(1-100)[thumbnail quality], int position[Get a thumbnail from video position] get thumbnail from video path Future<Uint8List>
getFileThumbnail String path[video path], int quality(1-100)[thumbnail quality], int position[Get a thumbnail from video position] get thumbnail file from video path Future<File>
getMediaInfo String path[video path] get media information from video path Future<MediaInfo>
compressVideo String path[video path], VideoQuality quality[compressed video quality], bool deleteOrigin[delete the origin video], int startTime[compression video start time], int duration[compression video duration from start time], bool includeAudio[is include audio in compressed video], int frameRate[compressed video frame rate] compression video at origin video path Future<MediaInfo>
cancelCompression none cancel compressing Future<void>
deleteAllCache none Delete all files generated by 'video_compress' will delete all files located at 'video_compress' Future<bool>

Subscriptions

Subscriptions Description Stream
compressProgress$ Subscribe the compression progress steam double progress

Contribute

Contributions are always welcome!

acknowledgment

Inspired by the flutter_ffmpeg library. https://github.com/rurico/flutter_video_compress

videocompress's People

Contributors

allcontributors[bot] avatar arjanaswal avatar ayman-barghout avatar crtl avatar efraespada avatar felixmomo avatar jamesdixon avatar jinthislife avatar jonasn5 avatar jonataslaw avatar kaiquegazola avatar khainhero avatar leynier avatar marcobraghim avatar martibis avatar miloskarakas avatar mostafaabdelazim avatar neelansh-creatorstack avatar neelansh-ns avatar ppornkitpras-agoda avatar pranavo72bex avatar serdnad avatar snowb1shop avatar stark8912 avatar trustmefelix avatar vbuberen avatar victoruvarov avatar voronovalexander avatar yanivshaked avatar zazo032 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

videocompress's Issues

Compression crashes

I tried compressing video both on emulator and real device running Android 10 and it keeps on crashing. What am I doing wrong? Below is my code.

` void getVideo() async {
final picker = ImagePicker();

final pickedFile = await picker.getVideo(source: ImageSource.camera,maxDuration: Duration(seconds: 10));
File file = File(pickedFile.path);
MediaInfo mediaInfo = await VideoCompress.compressVideo(
  file.path,
  quality: VideoQuality.DefaultQuality,
  deleteOrigin: false,
  includeAudio: true,// It's false by default
);
// print('Our picked video is: ${mediaInfo.path}');

if(mediaInfo!=null){
  file = mediaInfo.file;

  // await compressAndGetFile(file).then((thumbnail) {
  setState(() {
    widget.onVideoIconSelected(file);
  });
}


// });

}`

and log:

I/DefaultVideoStrategy(29098): Input width&height: 720x1280 I/DefaultVideoStrategy(29098): Output width&height: 720x1280 V/Engine (29098): Duration (us): 27230860000 V/Engine (29098): new step: 0 I/OMXClient(29098): IOmx service obtained I/OMXClient(29098): IOmx service obtained I/OMXClient(29098): IOmx service obtained W/OMXUtils(29098): do not know color format 0x7f000789 = 2130708361 I/ACodec (29098): setupAVCEncoderParameters with [profile: Baseline] [level: Level41] I/ACodec (29098): [OMX.google.h264.encoder] cannot encode color aspects. Ignoring. I/ACodec (29098): [OMX.google.h264.encoder] cannot encode HDR static metadata. Ignoring. I/ACodec (29098): setupVideoEncoder succeeded W/OMXUtils(29098): do not know color format 0x7f000789 = 2130708361 D/HostConnection(29098): HostConnection::get() New Host Connection established 0xc74c5b60, tid 29695 D/HostConnection(29098): HostComposition ext ANDROID_EMU_CHECKSUM_HELPER_v1 ANDROID_EMU_native_sync_v2 ANDROID_EMU_native_sync_v3 ANDROID_EMU_native_sync_v4 ANDROID_EMU_dma_v1 ANDROID_EMU_direct_mem ANDROID_EMU_host_composition_v1 ANDROID_EMU_host_composition_v2 ANDROID_EMU_vulkan ANDROID_EMU_deferred_vulkan_commands ANDROID_EMU_vulkan_null_optional_strings ANDROID_EMU_vulkan_create_resources_with_requirements ANDROID_EMU_YUV420_888_to_NV21 ANDROID_EMU_YUV_Cache ANDROID_EMU_async_unmap_buffer ANDROID_EMU_vulkan_free_memory_sync ANDROID_EMU_vulkan_shader_float16_int8 ANDROID_EMU_vulkan_async_queue_submit GL_OES_EGL_image_external_essl3 GL_OES_vertex_array_object GL_KHR_texture_compression_astc_ldr ANDROID_EMU_gles_max_version_3_0 D/eglCodecCommon(29098): setVertexArrayObject: set vao to 0 (0) 0 0 D/EGL_emulation(29098): eglCreateContext: 0xf777fd00: maj 3 min 0 rcv 3 D/EGL_emulation(29098): eglMakeCurrent: 0xf777fd00: ver 3 0 (tinfo 0xc7601590) I/OMXClient(29098): IOmx service obtained E/EGL_emulation(29098): eglQueryContext 32c0 EGL_BAD_ATTRIBUTE E/EGL_emulation(29098): tid 29695: eglQueryContext(1902): error 0x3004 (EGL_BAD_ATTRIBUTE) D/SurfaceUtils(29098): connecting to surface 0xc72b1008, reason connectToSurface I/MediaCodec(29098): [OMX.google.h264.decoder] setting surface generation to 29796358 D/SurfaceUtils(29098): disconnecting from surface 0xc72b1008, reason connectToSurface(reconnect) D/SurfaceUtils(29098): connecting to surface 0xc72b1008, reason connectToSurface(reconnect) E/ACodec (29098): [OMX.google.h264.decoder] setPortMode on output to DynamicANWBuffer failed w/ err -1010 I/VideoFrameDropper(29098): inFrameRateReciprocal:0.041666666666666664 outFrameRateReciprocal:0.041666666666666664 D/MediaCodec(29098): [OMX.google.h264.decoder] setting dataspace on output surface to #104 V/Engine (29098): new step: 1 I/AudioEngine(29098): process - time stretching - decoderDurationUs:0 encoderDeltaUs:0 stretchFactor:NaN I/AudioEngine(29098): process - totalInputSize:160 processedTotalInputSize:0 outputSize:2048 inputSize:160 W/AudioEngine(29098): ensureTempBuffer1 - desiredSize:0 W/AudioEngine(29098): ensureTempBuffer1 - creating new buffer. W/AudioEngine(29098): ensureTempBuffer2 - desiredSize:0 W/AudioEngine(29098): ensureTempBuffer2 - creating new buffer. V/VideoFrameDropper(29098): RENDERING (first frame) - frameRateReciprocalSum:0.041666666666666664 D/SoftwareRenderer(29098): setting dataspace on output surface to #104 V/VideoDecoderOutput(29098): New frame available D/ACodec (29098): dataspace changed to 0x10c10000 (R:2(Limited), P:1(BT709_5), M:1(BT709_5), T:3(SMPTE170M)) (R:2(Limited), S:1(BT709), T:3(SMPTE_170M)) V/Engine (29098): new step: 2 I/DefaultDataSinkChecks(29098): Output H.264 profile: Baseline Profile V/DefaultDataSink(29098): Added track #0 with video/avc to muxer V/DefaultDataSink(29098): Added track #1 with audio/mp4a-latm to muxer I/MPEG4Writer(29098): limits: 4294967295/0 bytes/us, bit rate: -1 bps and the estimated moov size 3192 bytes V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 3 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 4 I/MPEG4Writer(29098): setStartTimestampUs: 10 I/MPEG4Writer(29098): Earliest track starting time: 10 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 5 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 6 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 7 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 8 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 9 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): getTrackProgress - readUs:27230824422, totalUs:27230860000 V/Engine (29098): getTrackProgress - readUs:27230824422, totalUs:27230860000 V/Engine (29098): progress - video:0.9999986934676319 audio:0.9999986934676319 V/Engine (29098): new step: 10 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 11 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 12 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 13 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 14 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 15 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 16 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 17 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 18 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 19 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): getTrackProgress - readUs:27230824422, totalUs:27230860000 V/Engine (29098): getTrackProgress - readUs:27230824422, totalUs:27230860000 V/Engine (29098): progress - video:0.9999986934676319 audio:0.9999986934676319 V/Engine (29098): new step: 20 V/VideoFrameDropper(29098): RENDERING - frameRateReciprocalSum:0.041666666666666664 V/VideoDecoderOutput(29098): New frame available V/Engine (29098): new step: 21 V/Engine (29098): new step: 22 V/Engine (29098): new step: 23 V/Engine (29098): new step: 24 V/Engine (29098): new step: 25 V/Engine (29098): new step: 26 V/Engine (29098): new step: 27 E/MPEG4Writer(29098): The number of recorded samples is 0 E/MPEG4Writer(29098): 0 frames to dump timeStamps in Audio track W/MPEG4Writer(29098): 0-duration samples found: 1 W/MPEG4Writer(29098): 0-duration samples found: 1 I/MPEG4Writer(29098): Received total/0-length (20/1) buffers and encoded 20 frames. - Video I/MPEG4Writer(29098): Received total/0-length (0/1) buffers and encoded 0 frames. - Audio I/MPEG4Writer(29098): Audio track drift time: 0 us D/MPEG4Writer(29098): Video track stopping. Stop source D/MPEG4Writer(29098): Video track source stopping D/MPEG4Writer(29098): Video track source stopped D/MPEG4Writer(29098): Video track stopped. Stop source D/MPEG4Writer(29098): Audio track stopping. Stop source D/MPEG4Writer(29098): Audio track source stopping D/MPEG4Writer(29098): Audio track source stopped D/MPEG4Writer(29098): Audio track stopped. Stop source D/MPEG4Writer(29098): Duration from tracks range is [0, 27230859622] us D/MPEG4Writer(29098): Stopping writer thread D/MPEG4Writer(29098): 0 chunks are written in the last batch D/MPEG4Writer(29098): Writer thread stopped E/Surface (29098): getSlotFromBufferLocked: unknown buffer: 0x0 D/SurfaceUtils(29098): disconnecting from surface 0xc72b1008, reason disconnectFromSurface E/MediaMuxer(29098): stop() is called in invalid state 3 W/DefaultDataSink(29098): Failed to release the muxer. W/DefaultDataSink(29098): java.lang.IllegalStateException: Failed to stop the muxer W/DefaultDataSink(29098): at android.media.MediaMuxer.nativeStop(Native Method) W/DefaultDataSink(29098): at android.media.MediaMuxer.stop(MediaMuxer.java:466) W/DefaultDataSink(29098): at android.media.MediaMuxer.release(MediaMuxer.java:706) W/DefaultDataSink(29098): at com.otaliastudios.transcoder.sink.DefaultDataSink.release(DefaultDataSink.java:189) W/DefaultDataSink(29098): at com.otaliastudios.transcoder.engine.Engine.transcode(Engine.java:394) W/DefaultDataSink(29098): at com.otaliastudios.transcoder.Transcoder$1.call(Transcoder.java:134) W/DefaultDataSink(29098): at com.otaliastudios.transcoder.Transcoder$1.call(Transcoder.java:124) W/DefaultDataSink(29098): at java.util.concurrent.FutureTask.run(FutureTask.java:266) W/DefaultDataSink(29098): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) W/DefaultDataSink(29098): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) W/DefaultDataSink(29098): at java.lang.Thread.run(Thread.java:919) E/Transcoder(29098): Fatal error while transcoding, this might be invalid format or bug in engine or Android. E/Transcoder(29098): java.lang.IllegalStateException: Failed to stop the muxer E/Transcoder(29098): at android.media.MediaMuxer.nativeStop(Native Method) E/Transcoder(29098): at android.media.MediaMuxer.stop(MediaMuxer.java:466) E/Transcoder(29098): at com.otaliastudios.transcoder.sink.DefaultDataSink.stop(DefaultDataSink.java:183) E/Transcoder(29098): at com.otaliastudios.transcoder.engine.Engine.transcode(Engine.java:388) E/Transcoder(29098): at com.otaliastudios.transcoder.Transcoder$1.call(Transcoder.java:134) E/Transcoder(29098): at com.otaliastudios.transcoder.Transcoder$1.call(Transcoder.java:124) E/Transcoder(29098): at java.util.concurrent.FutureTask.run(FutureTask.java:266) E/Transcoder(29098): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167) E/Transcoder(29098): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641) E/Transcoder(29098): at java.lang.Thread.run(Thread.java:919)

Any help or pointers would be greatly appreciated.

Compression crash (v2.1.1)

Hi,
On IOS, picking a video from library; then trying to compress it crash app

final MediaInfo mediaInfo = await VideoCompress.compressVideo(
widget.path, 
quality: VideoQuality.MediumQuality, 
deleteOrigin: false, 
includeAudio: true);
Error : Invalid argument(s) (path): Must not be null 

i double check, path is never null and exists.
adding some logging show that

At some point, data is erased, and it remain only ::
{"isCancel":false}

v2.1.1 should correct this according some issue, but its not my case.
Thanks, Nelson

Edit:
Video is picked from library (https://github.com/CaiJingLong/flutter_photo_manager).
It worked when video is record from camera, but crash when picking from library

Feature request: compress gif & convert to video

Since you already use the com.otaliastudios package to compress videos in Android, I can write a PR to integrate GIF compression with https://github.com/natario1/GIFCompressor, IF someone can write a counterpart for iOS.
Who could do that?

The getter 'length' was called on null.

Hi,

I'm actually running your example code. Here's the flutter version i'm using

Flutter 1.16.3 • channel master • https://github.com/flutter/flutter.git
Framework • revision be3a4b37b3 (4 weeks ago) • 2020-03-26 18:08:05 -0700
Engine • revision b2bdeb3f0f
Tools • Dart 2.8.0 (build 2.8.0-dev.17.0 1402e8e1a4)

And i get this exception when video compression starts.

E/Transcoder( 5243): Fatal error while transcoding, this might be invalid format or bug in engine or Android.
E/Transcoder( 5243): java.lang.UnsupportedOperationException: Output channel count (6) not supported.
E/Transcoder( 5243): 	at com.otaliastudios.transcoder.transcode.internal.AudioEngine.<init>(AudioEngine.java:83)
E/Transcoder( 5243): 	at com.otaliastudios.transcoder.transcode.AudioTrackTranscoder.onDecoderOutputFormatChanged(AudioTrackTranscoder.java:56)
E/Transcoder( 5243): 	at com.otaliastudios.transcoder.transcode.BaseTrackTranscoder.drainDecoder(BaseTrackTranscoder.java:240)
E/Transcoder( 5243): 	at com.otaliastudios.transcoder.transcode.BaseTrackTranscoder.transcode(BaseTrackTranscoder.java:165)
E/Transcoder( 5243): 	at com.otaliastudios.transcoder.engine.Engine.transcode(Engine.java:373)
E/Transcoder( 5243): 	at com.otaliastudios.transcoder.Transcoder$1.call(Transcoder.java:134)
E/Transcoder( 5243): 	at com.otaliastudios.transcoder.Transcoder$1.call(Transcoder.java:124)
E/Transcoder( 5243): 	at java.util.concurrent.FutureTask.run(FutureTask.java:266)
E/Transcoder( 5243): 	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
E/Transcoder( 5243): 	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
E/Transcoder( 5243): 	at java.lang.Thread.run(Thread.java:764)
E/flutter ( 5243): [ERROR:flutter/lib/ui/ui_dart_state.cc(157)] Unhandled Exception: NoSuchMethodError: The getter 'length' was called on null.
E/flutter ( 5243): Receiver: null
E/flutter ( 5243): Tried calling: length
E/flutter ( 5243): #0      Object.noSuchMethod (dart:core-patch/object_patch.dart:53:5)
E/flutter ( 5243): #1      _parseJson (dart:convert-patch/convert_patch.dart:30:28)
E/flutter ( 5243): #2      JsonDecoder.convert (dart:convert/json.dart:505:36)
E/flutter ( 5243): #3      JsonCodec.decode (dart:convert/json.dart:153:41)
E/flutter ( 5243): #4      VideoCompress.compressVideo (package:video_compress/src/video_compressor.dart:159:26)
E/flutter ( 5243): <asynchronous suspension>
E/flutter ( 5243): #5      _MyHomePageState.build.<anonymous closure> (package:video_compress_example/main.dart:101:44)
E/flutter ( 5243): <asynchronous suspension>
E/flutter ( 5243): #6      _MyHomePageState.build.<anonymous closure> (package:video_compress_example/main.dart)
E/flutter ( 5243): #7      _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:779:19)
E/flutter ( 5243): #8      _InkResponseState.build.<anonymous closure> (package:flutter/src/material/ink_well.dart:862:36)
E/flutter ( 5243): #9      GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:182:24)
E/flutter ( 5243): #10     TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:504:11)
E/flutter ( 5243): #11     BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:282:5)
E/flutter ( 5243): #12     BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:254:7)
E/flutter ( 5243): #13     GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:156:27)
E/flutter ( 5243): #14     GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:222:20)
E/flutter ( 5243): #15     GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:198:22)
E/flutter ( 5243): #16     GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:156:7)
E/flutter ( 5243): #17     GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:102:7)
E/flutter ( 5243): #18     GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:86:7)
E/flutter ( 5243): #19     _rootRunUnary (dart:async/zone.dart:1159:13)
E/flutter ( 5243): #20     _CustomZone.runUnary (dart:async/zone.dart:1048:19)
E/flutter ( 5243): #21     _CustomZone.runUnaryGuarded (dart:async/zone.dart:950:7)
E/flutter ( 5243): #22     _invoke1 (dart:ui/hooks.dart:275:10)
E/flutter ( 5243): #23     _dispatchPointerDataPacket (dart:ui/hooks.dart:184:5)
E/flutter ( 5243): 

MediaInfo duration is integer not double

Hi. I am using video_compress: ^2.1.0 and on running "compressVideo" function it returns MediaInfo instance.

class MediaInfo {
  String path;
  String title;
  String author;
  int width;
  int height;

  /// [Android] API level 17
  int orientation;

  /// bytes
  int filesize; // filesize
  /// microsecond
  double duration;
  bool isCancel;
  File file;

  MediaInfo({
    @required this.path,
    this.title,
    this.author,
    this.width,
    this.height,
    this.orientation,
    this.filesize,
    this.duration,
    this.isCancel,
    this.file,
  });

in this class it says that it returns duration as double/microsecond
but when I upload the video on firebase parsing those data it seems that it returns duration as integer with millisecond unit.
could you check if is it a bug?

desktop support

I was wondering if the ffmpeg version works with desktop ?

if it does then we could use that for desktop.

[Clarification] Android status

Hi, thanks for sharing this library! I noticed that the README says "TODO: Finish methods on android". Does this mean some features available to iOS aren't currently implemented on Android, and if so, which ones?

App crashes on some videos on iOS

EDIT TWO:
This might be the fix: https://github.com/rurico/flutter_video_compress/pull/61/files I created a pull request based on this

Description

On iOS (possibly on Android too, but not tested extensively enough), with certain video files the app crashes. Is this the behavior if it finds a file it can not compress? If so, would it be possible to share a list with the video types that are supported?

EDIT: Just tested on Android the problem does not persist.

Platform

IOS

More info

The file with following media info does not work on iOS (complete different on phone as I transferred it to my desktop):

General
Complete name : C:\Users\Msi\Desktop\F910ADD0-059A-4592-9303-B22A0B810922.MP4
Format : MPEG-4
Format profile : Base Media
Codec ID : isom (isom/iso2/avc1/mp41)
File size : 6.38 MiB
Duration : 1 min 10 s
Overall bit rate mode : Variable
Overall bit rate : 754 kb/s
Encoded date : UTC 2015-04-27 16:53:10
Tagged date : UTC 2015-04-27 16:53:10
Writing application : Lavf52.62.0
Comment : FlixEngine_8.1.0.2

Video
ID : 1
Format : AVC
Format/Info : Advanced Video Codec
Format profile : Baseline@L3
Format settings, CABAC : No
Format settings, ReFrames : 1 frame
Format settings, GOP : M=1, N=60
Codec ID : avc1
Codec ID/Info : Advanced Video Coding
Duration : 1 min 10 s
Bit rate : 655 kb/s
Width : 270 pixels
Height : 480 pixels
Display aspect ratio : 0.563
Frame rate mode : Variable
Frame rate : 30.000 FPS
Minimum frame rate : 29.412 FPS
Maximum frame rate : 30.303 FPS
Color space : YUV
Chroma subsampling : 4:2:0
Bit depth : 8 bits
Scan type : Progressive
Bits/(Pixel*Frame) : 0.168
Stream size : 5.51 MiB (86%)
Encoded date : UTC 2015-04-27 16:53:10
Tagged date : UTC 2015-04-27 16:53:10

Audio
ID : 2
Format : AAC
Format/Info : Advanced Audio Codec
Format profile : LC
Codec ID : 40
Duration : 1 min 10 s
Bit rate mode : Variable
Bit rate : 96.0 kb/s
Channel(s) : 2 channels
Channel positions : Front: L R
Sampling rate : 48.0 kHz
Frame rate : 46.875 FPS (1024 spf)
Compression mode : Lossy
Stream size : 832 KiB (13%)
Encoded date : UTC 2015-04-27 16:53:10
Tagged date : UTC 2015-04-27 16:53:10

iOS, Android - frameRate control not working

Setting frameRate Control not working in both iOS and Android. Tested on real devices.

For example: setting the frameRate to 10 has no noticeable change in fileSize and video quality

Android, IOS - green and Blurry lines

For a vertical aspect ratio video, the blurry/green lines appear on the right side of the video from top to bottom

For a horizontal based aspect ratio, the blurry/green lines appear on the bottom of the video spanning from left to the right

Issue only appears in VideoPlay plugin, works fine when viewing the file in Chrome from firebase storage.

Sending a video from Android to Android where the quality is set to LowQuality has a blurry line. And also sending Android to IOS has blurry lines shown

Other quality presets, it is working fine.

Sending video compressed with iOS device(can be sent from iOS simulator as well), to an Android device shows a green line instead of blurry line.

When compressed on iOS, depending on the quality preset the green line gets bigger. For example using LowQuality preset shows a much bigger green line disturbance on video.

It works fine when viewing on Chrome from firebase storage.

Viewing the video on iOS device works great

iOS - Audio not included by default

Audio is not included by default

Have to include:

includeAudio: true

example:

MediaInfo _compressedVideo = await videoCompress.compressVideo(originalVideoPath, includeAudio: true,);

Compressing Video Takes Too Long

I don't know if its just me but compressing videos takes over like 10 minutes for me.

Doctor summary (to see all details, run flutter doctor -v):
[√] Flutter (Channel stable, v1.17.5, on Microsoft Windows [Version 10.0.18362.900], locale en-US)

[√] Android toolchain - develop for Android devices (Android SDK version 29.0.3)
[√] Android Studio (version 3.6)
[√] VS Code (version 1.46.1)
[√] Connected device (1 available)

• No issues found!

Feature Request: support for dart apps, not just Flutter

I need to do some video conversions in the server app I'm writing in Dart. I'd like to use your library to simplify things. Is there a reason your library is only usable in Flutter on iOS and Android? Would it be hard to add support for using your library in server apps?

My plan is to use Process.run() to run the required ffmpeg command (after making sure ffmpeg is installed on the server), but of course I would prefer to use a library like yours.

Include Audio on Android

Hey,

Thanks for the library!

I've just checked that setting includeAudio: false doesn't do anything in the compressed video on Android.
I've looked on Android's implementation and I think that includeAudio parameter is not used, am I right? Maybe I'm missing something.

Cheers!

cancelCompression now work

hi VideoCompress.cancelCompression not work please fix

my code

main() async {
  runApp(
    MyApp(),
  );
}

class MyApp extends StatefulWidget {
  @override
  _MyAppState createState() => _MyAppState();
}

class _MyAppState extends State<MyApp> {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: MyHomePage(),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key}) : super(key: key);

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  Subscription _subscription;

  @override
  void initState() {
    super.initState();
    _subscription = VideoCompress.compressProgress$.subscribe((progress) {
      debugPrint('progress: $progress');
    });
  }

  @override
  void dispose() {
    super.dispose();
    _subscription.unsubscribe();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,
      body: Center(
          child: Column(
        children: [
          SizedBox(
            height: 200,
          ),
          FlatButton(
              onPressed: () async {
                print("t");
                VideoCompress.cancelCompression();
              },
              child: Text(
                "Stop",
                style: TextStyle(fontSize: 50),
              ))
        ],
      )),
      floatingActionButton: FloatingActionButton(
        onPressed: () async {
          MediaInfo mediaInfo = await VideoCompress.compressVideo(
            "/storage/emulated/0/3.mp4",
            quality: VideoQuality.LowQuality,
            deleteOrigin: false,
            includeAudio: true,
          );

          print("Compressor =  " + mediaInfo.path);
          setState(() {});
        },
        tooltip: 'Increment',
        child: Icon(Icons.add),
      ),
    );
  }
}

The mp4 file will not be streamable

After the compression, I get this message inside the logs

Video track stopped. Stop source
D/MPEG4Writer(11324): Duration from tracks range is [18517334, 18566622] us
D/MPEG4Writer(11324): Stopping writer thread
D/MPEG4Writer(11324): 0 chunks are written in the last batch
D/MPEG4Writer(11324): Writer thread stopped
I/MPEG4Writer(11324): Ajust the moov start time from 10 us -> 10 us
I/MPEG4Writer(11324): The mp4 file will not be streamable.
D/SurfaceUtils(11324): disconnecting from surface 0x75ced6b010, reason disconnectFromSurface
D/MPEG4Writer(11324): Video track stopping. Stop source
D/MPEG4Writer(11324): Audio track stopping. Stop source

Is there a way to upload this video on a server and stream it ?

Watermarking or stitching?

You've got a great package! Wondering how I could go about adding a watermark to the video? Also is it possible to prepend or append an image or video and stitch them together?
Thanks!

Plugin has conflicts with firebase firebase_messaging how to solve this?

E/MethodChannel#plugins.flutter.io/firebase_messaging(29702): Failed to handle method call
E/MethodChannel#plugins.flutter.io/firebase_messaging(29702): java.lang.IllegalStateException: registrar.activity() must not be null
E/MethodChannel#plugins.flutter.io/firebase_messaging(29702): at com.example.video_compress.VideoCompressPlugin$Companion.registerWith(VideoCompressPlugin.kt:132)
E/MethodChannel#plugins.flutter.io/firebase_messaging(29702): at com.example.video_compress.VideoCompressPlugin.registerWith(VideoCompressPlugin.kt)
E/MethodChannel#plugins.flutter.io/firebase_messaging(29702): at io.flutter.plugins.GeneratedPluginRegistrant.registerWith(GeneratedPluginRegistrant.java:65)
E/MethodChannel#plugins.flutter.io/firebase_messaging(29702): at com.devbits.camiotalk.Application.registerWith(Application.kt:17)
E/MethodChannel#plugins.flutter.io/firebase_messaging(29702): at io.flutter.plugins.firebasemessaging.FlutterFirebaseMessagingService.startBackgroundIsolate(FlutterFirebaseMessagingService.java:164)
E/MethodChannel#plugins.flutter.io/firebase_messaging(29702): at io.flutter.plugins.firebasemessaging.FirebaseMessagingPlugin.onMethodCall(FirebaseMessagingPlugin.java:176)

I/flutter (29702): [2020-08-09 15:28:36.205762 | ConsoleHandler | INFO] PlatformException(error, registrar.activity() must not be null, null)
I/flutter (29702): [2020-08-09 15:28:36.205901 | ConsoleHandler | INFO]
I/flutter (29702): [2020-08-09 15:28:36.207027 | ConsoleHandler | INFO] ------- STACK TRACE -------
I/flutter (29702): [2020-08-09 15:28:36.265416 | ConsoleHandler | INFO] #0 StandardMethodCodec.decodeEnvelope (package:flutter/src/services/message_codecs.dart:569:7)
I/flutter (29702): [2020-08-09 15:28:36.265869 | ConsoleHandler | INFO] #1 MethodChannel._invokeMethod (package:flutter/src/services/platform_channel.dart:156:18)
I/flutter (29702): [2020-08-09 15:28:36.266165 | ConsoleHandler | INFO]
I/flutter (29702): [2020-08-09 15:28:36.266441 | ConsoleHandler | INFO] #2 MethodChannel.invokeMethod (package:flutter/src/services/platform_channel.dart:329:12

Can we introduce a "High" quality?

This scenario is on an iOS Device with ~10 second video.

The Medium/Default quality compresses a 100mb video to ~1mb video. The resolution is just a little blurry. The next available quality is "Highest" which will return a ~45mb video, which way too large. To get something that even gets down to the single digit mbs I have to lower the frameRate to less than 10, which also damages the resolution.

I need something in the middle, anyway to do this?

part of phone compress fail

@jonataslaw
when i use Redmi 6A compress the video fail. it is always compress。i use the image_pick to select the video when compress video output the follow logs

Engine: getTrackProgress - readUs:208979, totalUs:12074000 Engine: getTrackProgress - readUs:208979, totalUs:12074000 Engine: progress - video:0.01730818287228756 audio:0.01730818287228756 Engine: new step: 7300 Engine: new step: 7301 Engine: new step: 7302 Engine: new step: 7303 Engine: new step: 7304 Engine: new step: 7305 Engine: new step: 7306 Engine: new step: 7307 Engine: new step: 7308 Engine: new step: 7309 Engine: getTrackProgress - readUs:208979, totalUs:12074000 Engine: getTrackProgress - readUs:208979, totalUs:12074000 Engine: progress - video:0.01730818287228756 audio:0.01730818287228756

`lg@LGdeMacBook-Pro raintalk2 % flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.17.5, on Mac OS X 10.15.4 19E287, locale zh-Hans-CN)

[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.2)
[✓] Xcode - develop for iOS and macOS (Xcode 11.5)
[✓] Android Studio (version 4.0)
[✓] Connected device (4 available)

! Doctor found issues in 1 category.
`
Android version :9

iOS - crash while compressing video

iOS crashes when compressing a video with real device and iOS simulator

Potential fix:
Getting the MediaInfo of the original File before compressing the video

MediaInfo _originalInfo = await videoCompress.getMediaInfo(originalVideoPath);
MediaInfo _compressedVideo = await videoCompress.compressVideo(originalVideoPath);

VideoQuality enum "DefaultQuality" and "MediumQuality" have the same sizes

First of all: Thanks for your good work! This is a lighweight package to video resizing. But I notice an elementar issue.
The enum VideoQuality.HighestQuality and VideoQuality.HighestQuality seems to output the absolutely same resolution. If I try to compress a video with my iPhone 11 and check the video width after compressing, I can see the following sizes:

VideoQuality.LowQuality : 224 Pixels
VideoQuality.DefaultQuality : 568 Pixels
VideoQuality.MediumQuality : 568 Pixels
VideoQuality.HighestQuality : 1280 Pixels

Why DefaultQuality and MediumQuality have the same sizes? Is this a known bug? I understand that more than 1280 pixels is not possible here because this are apple presets, but are this the real values regarding the video width of a landscape video?

Additional information: Before each try I called await VideoCompress.deleteAllCache(); to be sure that there is nothing in cache.

My code:

for (int i = 0; i < videos.length; i++) {
  var path = videos[i]["videoPath"];
  final MediaInfo compressedVideo = await VideoCompress.compressVideo(path,
      quality: VideoQuality.HighestQuality);
  print(compressedVideo.width);
}

Thanks in advance for your information about this!

getFileThumbnail does not work for Android 10

I am trying to pick a custom thumbnail for a video

Sample Code:

 thumbnailFile = await VideoCompress.getFileThumbnail(
      rawVideoFile.path,
      quality: 100, // default(100)
      position: _controller.value.position.inSeconds -1, // default(-1)
    );

This always picks up the default frame(the first frame) for Android 10 devices while for other devices it takes up the custom frame where the VideoController is. Any resolution to this?

Logs:

V/Engine  ( 9656): new step: 10322
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23219 encoderDeltaUs:23219 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10323
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/Engine  ( 9656): new step: 10324
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/Engine  ( 9656): new step: 10325
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/Engine  ( 9656): new step: 10326
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10327
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10328
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10329
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/Engine  ( 9656): getTrackProgress - readUs:240024671, totalUs:240327000
V/Engine  ( 9656): getTrackProgress - readUs:240024671, totalUs:240327000
V/Engine  ( 9656): progress - video:0.9987420098449197 audio:0.9987420098449197
V/Engine  ( 9656): new step: 10330
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10331
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10332
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10333
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/Engine  ( 9656): new step: 10334
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/Engine  ( 9656): new step: 10335
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/Engine  ( 9656): new step: 10336
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10337
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10338
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10339
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/Engine  ( 9656): getTrackProgress - readUs:240256870, totalUs:240327000
V/Engine  ( 9656): getTrackProgress - readUs:240256870, totalUs:240327000
V/Engine  ( 9656): progress - video:0.9997081892588016 audio:0.9997081892588016
V/Engine  ( 9656): new step: 10340
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/Engine  ( 9656): new step: 10341
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10342
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10343
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10344
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23219 encoderDeltaUs:23219 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10345
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10346
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10347
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/VideoFrameDropper( 9656): RENDERING - frameRateReciprocalSum:0.04
V/VideoDecoderOutput( 9656): New frame available
V/Engine  ( 9656): new step: 10348
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/Engine  ( 9656): new step: 10349
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/Engine  ( 9656): getTrackProgress - readUs:240320000, totalUs:240327000
V/Engine  ( 9656): getTrackProgress - readUs:240320000, totalUs:240327000
V/Engine  ( 9656): progress - video:0.9999708730188451 audio:0.9999708730188451
V/Engine  ( 9656): new step: 10350
I/AudioEngine( 9656): process - time stretching - decoderDurationUs:23220 encoderDeltaUs:23220 stretchFactor:1.0
I/AudioEngine( 9656): process - totalInputSize:2048 processedTotalInputSize:2048 outputSize:2048 inputSize:2048
W/AudioEngine( 9656): ensureTempBuffer1 - desiredSize:2048
W/AudioEngine( 9656): ensureTempBuffer2 - desiredSize:2048
V/Engine  ( 9656): new step: 10351
V/Engine  ( 9656): new step: 10352
V/Engine  ( 9656): new step: 10353
I/MPEG4Writer( 9656): Received total/0-length (6008/1) buffers and encoded 6008 frames. - Video
D/MPEG4Writer( 9656): Video track stopping. Stop source
I/MPEG4Writer( 9656): Received total/0-length (10348/1) buffers and encoded 10348 frames. - Audio
D/MPEG4Writer( 9656): Video track source stopping
I/MPEG4Writer( 9656): Audio track drift time: 0 us
D/MPEG4Writer( 9656): Video track source stopped
D/MPEG4Writer( 9656): Video track stopped. Stop source
D/MPEG4Writer( 9656): Audio track stopping. Stop source
D/MPEG4Writer( 9656): Audio track source stopping
D/MPEG4Writer( 9656): Audio track source stopped
D/MPEG4Writer( 9656): Audio track stopped. Stop source
D/MPEG4Writer( 9656): Duration from tracks range is [240303310, 240320000] us
D/MPEG4Writer( 9656): Stopping writer thread
D/MPEG4Writer( 9656): 0 chunks are written in the last batch
D/MPEG4Writer( 9656): Writer thread stopped
I/MPEG4Writer( 9656): Ajust the moov start time from 10 us -> 10 us
I/MPEG4Writer( 9656): The mp4 file will not be streamable.
E/Surface ( 9656): getSlotFromBufferLocked: unknown buffer: 0x0
D/SurfaceUtils( 9656): disconnecting from surface 0xb65af008, reason disconnectFromSurface
D/MPEG4Writer( 9656): Video track stopping. Stop source
D/MPEG4Writer( 9656): Audio track stopping. Stop source

Can't compress video

This is a really great plugin.
It's stable until today, and i don't know why.
Here's the logs.

E/MethodChannel#video_compress( 7633): Failed to handle method call
E/MethodChannel#video_compress( 7633): kotlin.KotlinNullPointerException
E/MethodChannel#video_compress( 7633): at com.example.video_compress.VideoCompressPlugin.onMethodCall(VideoCompressPlugin.kt:83)
E/MethodChannel#video_compress( 7633): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
E/MethodChannel#video_compress( 7633): at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:85)
E/MethodChannel#video_compress( 7633): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:692)
E/MethodChannel#video_compress( 7633): at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#video_compress( 7633): at android.os.MessageQueue.next(MessageQueue.java:326)
E/MethodChannel#video_compress( 7633): at android.os.Looper.loop(Looper.java:163)
E/MethodChannel#video_compress( 7633): at android.app.ActivityThread.main(ActivityThread.java:6732)
E/MethodChannel#video_compress( 7633): at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#video_compress( 7633): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
E/MethodChannel#video_compress( 7633): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
I/flutter ( 7633): Error from VideoCompress:
I/flutter ( 7633): Method: compressVideo
I/flutter ( 7633): PlatformException(error, null, null, kotlin.KotlinNullPointerException
I/flutter ( 7633): at com.example.video_compress.VideoCompressPlugin.onMethodCall(VideoCompressPlugin.kt:83)
I/flutter ( 7633): at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
I/flutter ( 7633): at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:85)
I/flutter ( 7633): at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:692)
I/flutter ( 7633): at android.os.MessageQueue.nativePollOnce(Native Method)
I/flutter ( 7633): at android.os.MessageQueue.next(MessageQueue.java:326)
I/flutter ( 7633): at android.os.Looper.loop(Looper.java:163)
I/flutter ( 7633): at android.app.ActivityThread.main(ActivityThread.java:6732)
I/flutter ( 7633): at java.lang.reflect.Method.invoke(Native Method)
I/flutter ( 7633): at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)
I/flutter ( 7633): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:858)
I/flutter ( 7633): )
E/flutter ( 7633): [ERROR:flutter/lib/ui/ui_dart_state.cc(177)] Unhandled Exception: NoSuchMethodError: The getter 'file' was called on null.
E/flutter ( 7633): Receiver: null
E/flutter ( 7633): Tried calling: file
E/flutter ( 7633): #0 Object.noSuchMethod (dart:core-patch/object_patch.dart:51:5)
E/flutter ( 7633): #1 _RemarkContainerState._onPressedAddAttachment.. (package:home_companion/widgets/remark_container.dart:150:28)
E/flutter ( 7633):
E/flutter ( 7633): #2 _RemarkContainerState._onPressedAddAttachment.. (package:home_companion/widgets/remark_container.dart)
E/flutter ( 7633): #3 _InkResponseState._handleTap (package:flutter/src/material/ink_well.dart:993:19)
E/flutter ( 7633): #4 _InkResponseState.build. (package:flutter/src/material/ink_well.dart:1111:38)
E/flutter ( 7633): #5 GestureRecognizer.invokeCallback (package:flutter/src/gestures/recognizer.dart:183:24)
E/flutter ( 7633): #6 TapGestureRecognizer.handleTapUp (package:flutter/src/gestures/tap.dart:598:11)
E/flutter ( 7633): #7 BaseTapGestureRecognizer._checkUp (package:flutter/src/gestures/tap.dart:287:5)
E/flutter ( 7633): #8 BaseTapGestureRecognizer.acceptGesture (package:flutter/src/gestures/tap.dart:259:7)
E/flutter ( 7633): #9 GestureArenaManager.sweep (package:flutter/src/gestures/arena.dart:157:27)
E/flutter ( 7633): #10 GestureBinding.handleEvent (package:flutter/src/gestures/binding.dart:362:20)
E/flutter ( 7633): #11 GestureBinding.dispatchEvent (package:flutter/src/gestures/binding.dart:338:22)
E/flutter ( 7633): #12 RendererBinding.dispatchEvent (package:flutter/src/rendering/binding.dart:267:11)
E/flutter ( 7633): #13 GestureBinding._handlePointerEvent (package:flutter/src/gestures/binding.dart:295:7)
E/flutter ( 7633): #14 GestureBinding._flushPointerEventQueue (package:flutter/src/gestures/binding.dart:240:7)
E/flutter ( 7633): #15 GestureBinding._handlePointerDataPacket (package:flutter/src/gestures/binding.dart:213:7)
E/flutter ( 7633): #16 _rootRunUnary (dart:async/zone.dart:1206:13)
E/flutter ( 7633): #17 _CustomZone.runUnary (dart:async/zone.dart:1100:19)
E/flutter ( 7633): #18 _CustomZone.runUnaryGuarded (dart:async/zone.dart:1005:7)
E/flutter ( 7633): #19 _invoke1 (dart:ui/hooks.dart:265:10)
E/flutter ( 7633): #20 _dispatchPointerDataPacket (dart:ui/hooks.dart:174:5)
E/flutter ( 7633):

Could anybody help me to solve it?

Set video Compress output file path to Application Document Directory.

Can you advise me if we can set the video compress path?
By default, it is creating the videos under this folder.

/storage/emulated/0/Android/data/com.example.test/files/video_compress/VID_2020-06-15 11-43-21.mp4

I want to change it to the application directory.

final Directory extDir = await getApplicationDocumentsDirectory();
        final String dirPath = '${extDir.path}/Videos/My_App';

cancelCompression doesn't work on iOS (v2.1.1)

I made a small demo of the issue (see below). Issue is related to iOS platform

If you don't cancel the process everything seems to be working just fine.

ezgif-5-b0d4fe3c1797

But if you stop the process (using VideoCompress.cancelCompression method) and immediately try to start compression again (same video or another, doesn't matter) you will get error:

flutter: Bad state: VideoCompress Error: 
      Method: compressVideo
      Already have a compression process, you need to wait for the process to finish or stop it

ezgif-5-228fe397d84c

At the same time if you stop the process (VideoCompress.cancelCompression ) and wait enough for video compression to complete you will see that starting new compression works as expected.

Source code: video_compress_bug.zip

Everything related to this bug happens in viewer.dart file

Rotação da mídia original

Fala Guri, tudo certo?

Se eu pego um vídeo criado pela camera do aparelho este vídeo é criado com rotação de 90 graus. Depois de feita a compressão essa rotação é perdida.

Atributo: MediaInfo.orientation

Obrigado pelo package show de bola, abraço

Compression for Live Video Call

Hi,
Can I compress via VP9 for SVC in WebRTC streaming in video-call or video conference?
If yes, please gimme a hint on how. I'm a totally beginner on this.

includeAudio & sharing intent issue (iOS)

This issue is related to iOS only.

My app is taking file from sharing intent (example) and compressing it using video_compress library. If includeAudio=true everything works as expected. But when it is false compression fails with error:

flutter: Invalid argument(s) (path): Must not be null

During debugging in Xcode I have found that json object in line below has only one field "isCancel":

And this is happening because below line hits return:

guard let track = avController.getTrack(asset) else { return [:] }

Using the HighestQuality increases the video size

I can't understand what this package is doing. When I use the Medium Quality it outputs my video with a smaller resolution. This is not compression is just downsampling. When I use the Highest Quality my video increases in size.

Crash ios

Hello, I can't compress video on ios only !

video_compress: ^2.1.1
Flutter 1.20.4

No logs, my app closing just

Any idea ?
thx 😇

file not found #import <video_compress/video_compress-Swift.h>

ios
/Users/dongjieqiu/Downloads/flutter/.pub-cache/hosted/pub.flutter-io.cn/video_compress-2.0.0/ios/Classes/VideoCompressPlugin.m:2:9: fatal error: 'video_compress/video_compress-Swift.h' file not found
#import <video_compress/video_compress-Swift.h>

Incorrect Duration Units

In MediaInfo there is the following code:

  /// microsecond
  double duration;

It seems to imply duration is in microseconds. Instead, the units appear to be milliseconds.

Doesn't work on Android 11.

Hi, I'm use this package, and with a Pixel 2 XL physical device with Android 11, the package doesn't work, I'm test in Android 10 emulator, and iOS 14 and works fine, but Android 11 is the problem.

i'm try to compress video with all settings in default, with Image_Picker package and File_Picker to select the file from gallery or camera, the error is on both.

final info = await VideoCompress.compressVideo(path );`

The log

D/MediaScannerConnection( 5017): Scanned /storage/emulated/0/Android/data/MYAPPP/files/Pictures/0cec8741-c89d-4c75-97e8-d056d9d860e13536652757187323447.mp4 to null
I/flutter ( 5017): VideoCompress: You can try to subscribe to the
I/flutter ( 5017):       compressProgress$ stream to know the compressing state.
E/MethodChannel#video_compress( 5017): Failed to handle method call
E/MethodChannel#video_compress( 5017): kotlin.KotlinNullPointerException
E/MethodChannel#video_compress( 5017): 	at com.example.video_compress.VideoCompressPlugin.onMethodCall(VideoCompressPlugin.kt:83)
E/MethodChannel#video_compress( 5017): 	at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
E/MethodChannel#video_compress( 5017): 	at io.flutter.embedding.engine.dart.DartMessenger.handleMessageFromDart(DartMessenger.java:85)
E/MethodChannel#video_compress( 5017): 	at io.flutter.embedding.engine.FlutterJNI.handlePlatformMessage(FlutterJNI.java:692)
E/MethodChannel#video_compress( 5017): 	at android.os.MessageQueue.nativePollOnce(Native Method)
E/MethodChannel#video_compress( 5017): 	at android.os.MessageQueue.next(MessageQueue.java:335)
E/MethodChannel#video_compress( 5017): 	at android.os.Looper.loop(Looper.java:183)
E/MethodChannel#video_compress( 5017): 	at android.app.ActivityThread.main(ActivityThread.java:7656)
/MethodChannel#video_compress( 5017): 	at java.lang.reflect.Method.invoke(Native Method)
E/MethodChannel#video_compress( 5017): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
E/MethodChannel#video_compress( 5017): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)
I/flutter ( 5017): Error from VideoCompress:
I/flutter ( 5017):       Method: compressVideo
I/flutter ( 5017):       PlatformException(error, null, null, kotlin.KotlinNullPointerException
I/flutter ( 5017): 	at com.example.video_compress.VideoCompressPlugin.onMethodCall(VideoCompressPlugin.kt:83)
I/flutter ( 5017): 	at io.flutter.plugin.common.MethodChannel$IncomingMethodCallHandler.onMessage(MethodChannel.java:233)
I/flutter ( 5017): 	at android.os.MessageQueue.nativePollOnce(Native Method)
I/flutter ( 5017): 	at android.app.ActivityThread.main(ActivityThread.java:7656)
I/flutter ( 5017): 	at java.lang.reflect.Method.invoke(Native Method)
I/flutter ( 5017): 	at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:592)
I/flutter ( 5017): 	at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:947)

Cannot compress more than one video, getting error

I cannot compress more videos after compressing the 1st one I get that error

Bad state: Stream has already been listened to.

This happens whenever I go back to a page inside the ''initState'' method

Video compress failed on LG g8x android 10

I/flutter ( 9573): VideoCompress: You can try to subscribe to the
I/flutter ( 9573): compressProgress$ stream to know the compressing state.
V/LGCodecAdapter( 9573): convertMetaDataToMessage MetaDataBase
V/LGCodecOSAL( 9573): Called LGCodeConvertMetaDataBaseToMessage
V/LGCodecAdapter( 9573): convertMetaDataToMessage MetaDataBase
V/LGCodecOSAL( 9573): Called LGCodeConvertMetaDataBaseToMessage
E/Transcoder( 9573): Fatal error while transcoding, this might be invalid format or bug in engine or Android.
E/Transcoder( 9573): java.lang.IllegalArgumentException
E/Transcoder( 9573): at android.media.MediaMetadataRetriever.setDataSource(MediaMetadataRetriever.java:183)
E/Transcoder( 9573): at com.otaliastudios.transcoder.source.UriDataSource.applyRetriever(UriDataSource.java:33)
E/Transcoder( 9573): at com.otaliastudios.transcoder.source.DefaultDataSource.ensureMetadata(DefaultDataSource.java:41)
E/Transcoder( 9573): at com.otaliastudios.transcoder.source.DefaultDataSource.getLocation(DefaultDataSource.java:138)
E/Transcoder( 9573): at com.otaliastudios.transcoder.engine.Engine.transcode(Engine.java:316)
E/Transcoder( 9573): at com.otaliastudios.transcoder.Transcoder$1.call(Transcoder.java:134)
E/Transcoder( 9573): at com.otaliastudios.transcoder.Transcoder$1.call(Transcoder.java:124)
E/Transcoder( 9573): at java.util.concurrent.FutureTask.run(FutureTask.java:266)
E/Transcoder( 9573): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
E/Transcoder( 9573): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
E/Transcoder( 9573): at java.lang.Thread.run(Thread.java:919)

Height and width differs on Android and iOS

Here you can see a capture of how I am currently getting the aspect ratio, with the videocompress plugin. Basically the width and the height are not the same in ios and android. I might as well be doing something wrong, please let me know.

Capture d’écran 2020-05-19 à 10 49 48

Thank You - Note to creator of plugin

This is a brilliant plug-in. I was using FFMPEG which works fine the way i figured out the balance of quality/compression speed and final compressed output file size.

This plugin is very lightweight and saves me about 7.5 MB for final APK size(Very good!)

Obviously I found many issues but I think you can fix them very easily. Some could be related to how Video_Player plugin from google displays the video because on Chrome it works very good across the board.

again very nice job to you and thank you for bringing this to the flutter community by porting it.

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.