Skip to content

Commit

Permalink
fix: gif exportation #134
Browse files Browse the repository at this point in the history
  • Loading branch information
LeGoffMael committed Feb 10, 2023
1 parent fb0a068 commit 3159092
Show file tree
Hide file tree
Showing 6 changed files with 79 additions and 44 deletions.
11 changes: 6 additions & 5 deletions example/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,9 @@ PODS:
- libwebp/mux (1.2.3):
- libwebp/demux
- libwebp/webp (1.2.3)
- path_provider_ios (0.0.1):
- path_provider_foundation (0.0.1):
- Flutter
- FlutterMacOS
- video_player_avfoundation (0.0.1):
- Flutter
- video_thumbnail (0.0.1):
Expand All @@ -30,7 +31,7 @@ DEPENDENCIES:
- ffmpeg_kit_flutter_min_gpl (from `.symlinks/plugins/ffmpeg_kit_flutter_min_gpl/ios`)
- Flutter (from `Flutter`)
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
- path_provider_ios (from `.symlinks/plugins/path_provider_ios/ios`)
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/ios`)
- video_player_avfoundation (from `.symlinks/plugins/video_player_avfoundation/ios`)
- video_thumbnail (from `.symlinks/plugins/video_thumbnail/ios`)

Expand All @@ -46,8 +47,8 @@ EXTERNAL SOURCES:
:path: Flutter
image_picker_ios:
:path: ".symlinks/plugins/image_picker_ios/ios"
path_provider_ios:
:path: ".symlinks/plugins/path_provider_ios/ios"
path_provider_foundation:
:path: ".symlinks/plugins/path_provider_foundation/ios"
video_player_avfoundation:
:path: ".symlinks/plugins/video_player_avfoundation/ios"
video_thumbnail:
Expand All @@ -59,7 +60,7 @@ SPEC CHECKSUMS:
Flutter: f04841e97a9d0b0a8025694d0796dd46242b2854
image_picker_ios: b786a5dcf033a8336a657191401bfdf12017dabb
libwebp: 60305b2e989864154bd9be3d772730f08fc6a59c
path_provider_ios: 14f3d2fd28c4fdb42f44e0f751d12861c43cee02
path_provider_foundation: 37748e03f12783f9de2cb2c4eadfaa25fe6d4852
video_player_avfoundation: e489aac24ef5cf7af82702979ed16f2a5ef84cff
video_thumbnail: c4e2a3c539e247d4de13cd545344fd2d26ffafd1

Expand Down
1 change: 1 addition & 0 deletions example/lib/main.dart
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ class _VideoEditorState extends State<VideoEditor> {
_isExporting.value = true;
// NOTE: To use `-crf 1` and [VideoExportPreset] you need `ffmpeg_kit_flutter_min_gpl` package (with `ffmpeg_kit` only it won't work)
await _controller.exportVideo(
// format: 'gif',
// preset: VideoExportPreset.medium,
// customInstruction: "-crf 17",
onProgress: (stats, value) => _exportingProgress.value = value,
Expand Down
90 changes: 60 additions & 30 deletions example/lib/widgets/export_result.dart
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,18 @@ import 'dart:typed_data';

import 'package:flutter/material.dart';
import 'package:fraction/fraction.dart';
import 'package:path/path.dart' as path;
import 'package:video_player/video_player.dart';

Future<void> _getImageDimension(File file,
{required Function(Size) onResult}) async {
var decodedImage = await decodeImageFromList(file.readAsBytesSync());
onResult(Size(decodedImage.width.toDouble(), decodedImage.height.toDouble()));
}

String _fileMBSize(File file) =>
' ${(file.lengthSync() / (1024 * 1024)).toStringAsFixed(1)} MB';

class VideoResultPopup extends StatefulWidget {
const VideoResultPopup({super.key, required this.video});

Expand All @@ -15,23 +25,41 @@ class VideoResultPopup extends StatefulWidget {
}

class _VideoResultPopupState extends State<VideoResultPopup> {
late VideoPlayerController _controller;
VideoPlayerController? _controller;
FileImage? _fileImage;
Size _fileDimension = Size.zero;
late final bool _isGif =
path.extension(widget.video.path).toLowerCase() == ".gif";
late String _fileMbSize;

@override
void initState() {
super.initState();
_controller = VideoPlayerController.file(widget.video);
_controller.initialize().then((_) {
setState(() {});
_controller.play();
_controller.setLooping(true);
});
if (_isGif) {
_getImageDimension(
widget.video,
onResult: (d) => setState(() => _fileDimension = d),
);
} else {
_controller = VideoPlayerController.file(widget.video);
_controller?.initialize().then((_) {
_fileDimension = _controller?.value.size ?? Size.zero;
setState(() {});
_controller?.play();
_controller?.setLooping(true);
});
}
_fileMbSize = _fileMBSize(widget.video);
}

@override
void dispose() {
_controller.pause();
_controller.dispose();
if (_isGif) {
_fileImage?.evict();
} else {
_controller?.pause();
_controller?.dispose();
}
super.dispose();
}

Expand All @@ -44,21 +72,25 @@ class _VideoResultPopupState extends State<VideoResultPopup> {
alignment: Alignment.bottomLeft,
children: [
AspectRatio(
aspectRatio: _controller.value.aspectRatio,
child: VideoPlayer(_controller),
aspectRatio: _fileDimension.aspectRatio == 0
? 1
: _fileDimension.aspectRatio,
child:
_isGif ? Image.file(widget.video) : VideoPlayer(_controller!),
),
Positioned(
bottom: 0,
child: FileDescription(
description: {
'Video path': widget.video.path,
'Video duration':
'${(_controller.value.duration.inMilliseconds / 1000).toStringAsFixed(2)}s',
'Video ratio':
Fraction.fromDouble(_controller.value.aspectRatio)
.reduce()
.toString(),
'Video size': _controller.value.size.toString(),
if (!_isGif)
'Video duration':
'${((_controller?.value.duration.inMilliseconds ?? 0) / 1000).toStringAsFixed(2)}s',
'Video ratio': Fraction.fromDouble(_fileDimension.aspectRatio)
.reduce()
.toString(),
'Video dimension': _fileDimension.toString(),
'Video size': _fileMbSize,
},
),
),
Expand All @@ -80,20 +112,17 @@ class CoverResultPopup extends StatefulWidget {

class _CoverResultPopupState extends State<CoverResultPopup> {
late final Uint8List _imagebytes = widget.cover.readAsBytesSync();
Size? _fileSize;
Size? _fileDimension;
late String _fileMbSize;

@override
void initState() {
super.initState();
_readFileData();
}

Future<void> _readFileData() async {
var decodedImage = await decodeImageFromList(_imagebytes);
setState(() {
_fileSize =
Size(decodedImage.width.toDouble(), decodedImage.height.toDouble());
});
_getImageDimension(
widget.cover,
onResult: (d) => setState(() => _fileDimension = d),
);
_fileMbSize = _fileMBSize(widget.cover);
}

@override
Expand All @@ -110,10 +139,11 @@ class _CoverResultPopupState extends State<CoverResultPopup> {
description: {
'Cover path': widget.cover.path,
'Cover ratio':
Fraction.fromDouble(_fileSize?.aspectRatio ?? 0)
Fraction.fromDouble(_fileDimension?.aspectRatio ?? 0)
.reduce()
.toString(),
'Cover size': _fileSize.toString(),
'Cover dimension': _fileDimension.toString(),
'Cover size': _fileMbSize,
},
),
),
Expand Down
7 changes: 4 additions & 3 deletions example/pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,11 @@ dependencies:
video_editor:
path: ../

helpers: ^1.1.4
image_picker: ^0.8.6
video_player: ^2.4.10
fraction: ^4.1.4
helpers: ^1.1.4
image_picker: ^0.8.6+1
path: ^1.8.2
video_player: ^2.5.1

flutter:
uses-material-design: true
Expand Down
8 changes: 5 additions & 3 deletions lib/domain/bloc/controller.dart
Original file line number Diff line number Diff line change
Expand Up @@ -508,7 +508,7 @@ class VideoEditorController extends ChangeNotifier {
if (!isFiltersEnabled) return "";

// CALCULATE FILTERS
final String gif = videoFormat != "gif" ? "" : "fps=10 -loop 0";
final bool isGif = videoFormat?.toLowerCase() == "gif";
final String scaleInstruction =
scale == 1.0 ? "" : "scale=iw*$scale:ih*$scale";

Expand All @@ -517,10 +517,12 @@ class VideoEditorController extends ChangeNotifier {
_getCrop(),
scaleInstruction,
_getRotation(),
gif
isGif ? "fps=10" : "",
];
filters.removeWhere((item) => item.isEmpty);
return filters.isNotEmpty ? "-vf '${filters.join(",")}'" : "";
return filters.isNotEmpty
? "-vf '${filters.join(",")}'${isGif ? " -loop 0" : ""}"
: "";
}

/// Export the video using this edition parameters and return a `File`.
Expand Down
6 changes: 3 additions & 3 deletions pubspec.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,11 @@ dependencies:
sdk: flutter

ffmpeg_kit_flutter_min_gpl: ^5.1.0
path_provider: ^2.0.11
video_player: ^2.4.10
video_thumbnail: ^0.5.3
path: ^1.8.0 # update to `1.8.1` causes #79
path_provider: ^2.0.12
transparent_image: ^2.0.0 # show fade-in placeholder in thumbnails generation
video_player: ^2.5.1
video_thumbnail: ^0.5.3

dev_dependencies:
flutter_test:
Expand Down

0 comments on commit 3159092

Please sign in to comment.