diff --git a/example/lib/main.dart b/example/lib/main.dart index 100e02d1..eaa34245 100644 --- a/example/lib/main.dart +++ b/example/lib/main.dart @@ -137,36 +137,34 @@ class _VideoEditorState extends State { // preset: VideoExportPreset.medium, // customInstruction: "-crf 17", onProgress: (stats, value) => _exportingProgress.value = value, + onError: (e, s) => _exportText = "Error on export video :(", onCompleted: (file) { _isExporting.value = false; if (!mounted) return; - if (file != null) { - final VideoPlayerController videoController = - VideoPlayerController.file(file); - videoController.initialize().then((value) async { - setState(() {}); - videoController.play(); - videoController.setLooping(true); - await showDialog( - context: context, - builder: (_) => Padding( - padding: const EdgeInsets.all(30), - child: Center( - child: AspectRatio( - aspectRatio: videoController.value.aspectRatio, - child: VideoPlayer(videoController), - ), + + final VideoPlayerController videoController = + VideoPlayerController.file(file); + videoController.initialize().then((value) async { + setState(() {}); + videoController.play(); + videoController.setLooping(true); + await showDialog( + context: context, + builder: (_) => Padding( + padding: const EdgeInsets.all(30), + child: Center( + child: AspectRatio( + aspectRatio: videoController.value.aspectRatio, + child: VideoPlayer(videoController), ), ), - ); - await videoController.pause(); - videoController.dispose(); - }); - _exportText = "Video success export!"; - } else { - _exportText = "Error on export video :("; - } + ), + ); + await videoController.pause(); + videoController.dispose(); + }); + _exportText = "Video success export!"; setState(() => _exported = true); Future.delayed(const Duration(seconds: 2), () => setState(() => _exported = false)); @@ -177,21 +175,18 @@ class _VideoEditorState extends State { void _exportCover() async { setState(() => _exported = false); await _controller.extractCover( + onError: (e, s) => _exportText = "Error on cover exportation :(", onCompleted: (cover) { if (!mounted) return; - if (cover != null) { - _exportText = "Cover exported! ${cover.path}"; - showDialog( - context: context, - builder: (_) => Padding( - padding: const EdgeInsets.all(30), - child: Center(child: Image.memory(cover.readAsBytesSync())), - ), - ); - } else { - _exportText = "Error on cover exportation :("; - } + _exportText = "Cover exported! ${cover.path}"; + showDialog( + context: context, + builder: (_) => Padding( + padding: const EdgeInsets.all(30), + child: Center(child: Image.memory(cover.readAsBytesSync())), + ), + ); setState(() => _exported = true); Future.delayed(const Duration(seconds: 2), diff --git a/lib/domain/bloc/controller.dart b/lib/domain/bloc/controller.dart index 9c4162dc..56b5240f 100644 --- a/lib/domain/bloc/controller.dart +++ b/lib/domain/bloc/controller.dart @@ -217,7 +217,7 @@ class VideoEditorController extends ChangeNotifier { _updateTrimRange(); } - generateDefaultCoverThumnail(); + generateDefaultCoverThumbnail(); notifyListeners(); } @@ -341,7 +341,7 @@ class VideoEditorController extends ChangeNotifier { } /// Generate cover at [startTrim] time in milliseconds - void generateDefaultCoverThumnail() async { + void generateDefaultCoverThumbnail() async { final defaultCover = await generateCoverThumbnail(timeMs: startTrim.inMilliseconds); updateSelectedCover(defaultCover); @@ -419,7 +419,9 @@ class VideoEditorController extends ChangeNotifier { /// Export the video using this edition parameters and return a `File`. /// - /// The [onCompleted] param must be set to retun the exported [File] video + /// The [onCompleted] param must be set to return the exported [File] video. + /// + /// The [onError] function provides the [Exception] and [StackTrace] that causes the exportation error. /// /// If the [name] is `null`, then it uses this video filename. /// @@ -442,7 +444,8 @@ class VideoEditorController extends ChangeNotifier { /// /// Set [isFiltersEnabled] to `false` if you do not want to apply any changes Future exportVideo({ - required void Function(File? file) onCompleted, + required void Function(File file) onCompleted, + void Function(Object, StackTrace)? onError, String? name, String? outDir, String format = "mp4", @@ -487,12 +490,19 @@ class VideoEditorController extends ChangeNotifier { final state = FFmpegKitConfig.sessionStateToString(await session.getState()); final code = await session.getReturnCode(); - final failStackTrace = await session.getFailStackTrace(); - - debugPrint( - "FFmpeg process exited with state $state and return code $code.${(failStackTrace == null) ? "" : "\\n$failStackTrace"}"); - onCompleted(code?.isValueSuccess() == true ? File(outputPath) : null); + if (code?.isValueSuccess() == true) { + onCompleted(File(outputPath)); + } else { + if (onError != null) { + onError( + Exception( + 'FFmpeg process exited with state $state and return code $code.\n${await session.getOutput()}'), + StackTrace.current, + ); + } + return; + } }, null, onProgress != null @@ -569,7 +579,9 @@ class VideoEditorController extends ChangeNotifier { /// Export this selected cover, or by default the first one, return an image [File]. /// - /// The [onCompleted] param must be set to retun the exported [File] cover + /// The [onCompleted] param must be set to return the exported [File] cover + /// + /// The [onError] function provides the [Exception] and [StackTrace] that causes the exportation error. /// /// If the [name] is `null`, then it uses this video filename. /// @@ -587,7 +599,8 @@ class VideoEditorController extends ChangeNotifier { /// /// Set [isFiltersEnabled] to `false` if you do not want to apply any changes Future extractCover({ - required void Function(File? file) onCompleted, + required void Function(File file) onCompleted, + void Function(Object, StackTrace)? onError, String? name, String? outDir, String format = "jpg", @@ -598,11 +611,14 @@ class VideoEditorController extends ChangeNotifier { }) async { final String tempPath = outDir ?? (await getTemporaryDirectory()).path; // file generated from the thumbnail library or video source - final String? coverPath = await _generateCoverFile( - quality: quality, - ); + final String? coverPath = await _generateCoverFile(quality: quality); if (coverPath == null) { - debugPrint("ERROR ON COVER EXTRACTION WITH VideoThumbnail LIBRARY"); + if (onError != null) { + onError( + Exception('VideoThumbnail library error while exporting the cover'), + StackTrace.current, + ); + } return; } name ??= path.basenameWithoutExtension(file.path); @@ -633,12 +649,19 @@ class VideoEditorController extends ChangeNotifier { final state = FFmpegKitConfig.sessionStateToString(await session.getState()); final code = await session.getReturnCode(); - final failStackTrace = await session.getFailStackTrace(); - - debugPrint( - "FFmpeg process exited with state $state and return code $code.${(failStackTrace == null) ? "" : "\\n$failStackTrace"}"); - onCompleted(code?.isValueSuccess() == true ? File(outputPath) : null); + if (code?.isValueSuccess() == true) { + onCompleted(File(outputPath)); + } else { + if (onError != null) { + onError( + Exception( + 'FFmpeg process exited with state $state and return code $code.\n${await session.getOutput()}'), + StackTrace.current, + ); + } + return; + } }, null, onProgress, diff --git a/lib/ui/cover/cover_viewer.dart b/lib/ui/cover/cover_viewer.dart index 7d9b10d2..a16f038b 100644 --- a/lib/ui/cover/cover_viewer.dart +++ b/lib/ui/cover/cover_viewer.dart @@ -63,7 +63,7 @@ class _CoverViewerState extends State { void _checkIfCoverIsNull() { if (widget.controller.selectedCoverVal!.thumbData == null) { - widget.controller.generateDefaultCoverThumnail(); + widget.controller.generateDefaultCoverThumbnail(); } }