We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
CropGridViewer.preview cutting video frames from edges vertically but if i use CropGridViewer.edit it working fine please.
here is my code
import 'dart:io';
import 'package:ffmpeg_kit_flutter_full_gpl/ffmpeg_kit.dart'; import 'package:ffmpeg_kit_flutter_full_gpl/log.dart'; import 'package:ffmpeg_kit_flutter_full_gpl/return_code.dart'; import 'package:ffmpeg_kit_flutter_full_gpl/statistics.dart'; import 'package:flutter/cupertino.dart'; import 'package:flutter/material.dart'; import 'package:flutter/services.dart'; import 'package:flutter/widgets.dart'; import 'package:fluttertoast/fluttertoast.dart'; import 'package:intl/intl.dart'; import 'package:media_scanner/media_scanner.dart'; import 'package:path_provider/path_provider.dart'; import 'package:video_editor/video_editor.dart'; import 'package:video_player/video_player.dart'; import 'package:videocutter/Tab/TabBarViewWidget.dart'; import 'package:videocutter/Trim/video_trim.dart';
class Trim extends StatefulWidget { const Trim({Key? key, required this.file}) : super(key: key);
final File file;
@OverRide State createState() => _TrimState(); }
class _TrimState extends State { late final VideoEditorController _controller; late VideoPlayerController _videoPlayerController;
int duration = 0;
String formatter(Duration duration) => [ duration.inMinutes.remainder(60).toString().padLeft(2, '0'), duration.inSeconds.remainder(60).toString().padLeft(2, '0') ].join(":");
final double height = 60; ValueNotifier progressNotifier = ValueNotifier(0);
@OverRide void initState() { super.initState(); videoPlayerController = VideoPlayerController.file(widget.file) ..initialize().then(() { setState(() { duration = _videoPlayerController.value.duration.inSeconds; }); });
_controller = VideoEditorController.file( File(widget.file.path), minDuration: const Duration(seconds: 10), maxDuration: Duration( seconds: 60), // Default value, can be updated later ); _controller.initialize(aspectRatio: 16 / 9).then((_) { setState(() { // Update maxDuration after _controller has been initialized _controller.maxDuration = Duration(seconds: duration > 0 ? duration : 60); }); }).catchError((error) { // handle minimum duration bigger than video duration error Navigator.pop(context); });
}
@OverRide void dispose() { _controller.dispose(); _videoPlayerController.dispose(); super.dispose(); }
/// Basic export video function /// Basic export video function
bool istrim = true; int progress = 0; String? fileName;
Future trimVideos() async {
try { Directory mainFolder = Directory('${(await getApplicationDocumentsDirectory()).path}/trim/cut/'); final String outputPath= '${mainFolder.path}/$fileName.mp4'; //final String outputPath = '/storage/emulated/0/Download/trim/cut/$fileName.mp4'; final String inputPath = widget.file.path; final Duration start = _controller.startTrim; final Duration end = _controller.endTrim; final command = '-ss ${formatter(start)} -t ${formatter(end - start)} -noaccurate_seek -i "$inputPath" -codec copy -avoid_negative_ts 1 "$outputPath"'; int totalVideoDuration = (end - start).inMilliseconds; int totalProgress = 0; // Execute FFmpeg command await FFmpegKit.executeAsync(command, (session) async { final returnCode = await session.getReturnCode(); print('The command is executed: $command'); if (ReturnCode.isSuccess(returnCode)) { print('working fine $returnCode'); progressNotifier.value = 100; Navigator.pushReplacement( context, MaterialPageRoute(builder: (context) => TabBarViewWidget(initialIndex: 0, showAppBar: true)), ); } }, (Log log) { // Log callback }, (Statistics statistics) { if (statistics == null) { return; } if (statistics.getTime() > 0) { // Calculate the percentage of completion totalProgress = (statistics.getTime() * 100) ~/ totalVideoDuration; progress = totalProgress; print('Progress: $progress%'); progressNotifier.value=progress; } }); // MediaScanner.loadMedia(path: outputPath); print('Execution completed successfully'); // Navigator.push( // context, // MaterialPageRoute( // builder: (context) => TabBarViewWidget(initialIndex: 1), // ), // ); } catch (e) { print('Error trimming video: $e'); }
Future _showFileNameDialog(BuildContext context) async { TextEditingController fileNameController = TextEditingController();
return showDialog<String>( context: context, builder: (BuildContext context) { return AlertDialog( title: Text('Enter Name'), content: TextField( controller: fileNameController, decoration: InputDecoration(hintText: '${DateFormat('yyyyMMdd_HHmmss').format(DateTime.now())}'), ), actions: <Widget>[ TextButton( onPressed: () async { Navigator.pop(context, fileNameController.text.trim()); if(fileNameController.text==null||fileNameController.text.isEmpty){ fileName= DateFormat('yyyyMMdd_HHmmss').format(DateTime.now()); print('The file name is $fileName'); }else{ fileName=fileNameController.text.trim(); print('The file name is $fileName'); } trimVideos(); }, child: Text('OK'), ), TextButton( onPressed: () { Navigator.pop(context, null); // Cancel }, child: Text('Cancel'), ), ], ); }, );
@override Widget build(BuildContext context) { SystemChrome.setPreferredOrientations([ DeviceOrientation.portraitUp, DeviceOrientation.portraitDown, ]); return Scaffold( appBar: AppBar( actions: [ Padding( padding: EdgeInsets.only(right: 30), ) ], centerTitle: true, title: Text('Trim video'), ), body: FutureBuilder( future: _controller.initialize(), builder: (context, snapshot) { if (snapshot.connectionState == ConnectionState.done) { return _buildTrimWidget(); } else { return Center(child: Column( mainAxisAlignment: MainAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.start, children: [ CircularProgressIndicator(), ], )); } }, ), ); } Widget _buildTrimWidget() { if (_controller.initialized) { return Column( mainAxisAlignment: MainAxisAlignment.center, children: [ Expanded( child: Stack( alignment: Alignment.center, children: [ Container( color: Colors.black, width: MediaQuery.of(context).size.width, height: MediaQuery.of(context).size.height, // Adjust height as desired child: CropGridViewer.edit( controller: _controller, ), ), AnimatedBuilder( animation: _controller.video, builder: (_, __) => AnimatedOpacity( opacity: _controller.isPlaying ? 0 : 1, duration: kThemeAnimationDuration, child: GestureDetector( onTap: _controller.video.play, child: Container( width: 40, height: 40, decoration: const BoxDecoration( color: Colors.white, shape: BoxShape.circle, ), child: const Icon( Icons.play_arrow, color: Colors.black, ), ), ), ), ), ], ), ), ElevatedButton( onPressed: (){ _showFileNameDialog(context); }, child: Text('Trim Now') ), ValueListenableBuilder<int>( valueListenable: progressNotifier, builder: (context, value, child) { return value < 100 ? Column( children: [ Text('Progress: $value%'), LinearProgressIndicator( value: value / 100, minHeight: 10, backgroundColor: Colors.grey, valueColor: AlwaysStoppedAnimation<Color>(Colors.green), ), ], ) : Container(); // Empty container when progress is finished }), ..._trimSlider(), ], ); } else { return const Center(child: CircularProgressIndicator()); } } List<Widget> _trimSlider() { return [ AnimatedBuilder( animation: Listenable.merge([ _controller, _controller.video, ]), builder: (_, __) { final int duration = _controller.videoDuration.inSeconds; final double pos = _controller.trimPosition * duration; return Padding( padding: EdgeInsets.symmetric(horizontal: height / 4), child: Row( children: [ Text('${formatter(Duration(seconds: pos.toInt()))}'), const Expanded(child: SizedBox()), AnimatedOpacity( opacity: _controller.isTrimming ? 1 : 0, duration: kThemeAnimationDuration, child: Row( mainAxisSize: MainAxisSize.min, children: [ Text(formatter(_controller.startTrim)), const SizedBox(width: 10), Text(formatter(_controller.endTrim)), ], ), ), ], ), ); }, ), Container( width: MediaQuery .of(context) .size .width, margin: EdgeInsets.symmetric(vertical: height / 4), child: TrimSlider( controller: _controller, height: height, horizontalMargin: height / 4, child: TrimTimeline( controller: _controller, padding: const EdgeInsets.only(top: 10), ), ), ), ]; }
The text was updated successfully, but these errors were encountered:
No branches or pull requests
CropGridViewer.preview cutting video frames from edges vertically but if i use CropGridViewer.edit it working fine please.
here is my code
import 'dart:io';
import 'package:ffmpeg_kit_flutter_full_gpl/ffmpeg_kit.dart';
import 'package:ffmpeg_kit_flutter_full_gpl/log.dart';
import 'package:ffmpeg_kit_flutter_full_gpl/return_code.dart';
import 'package:ffmpeg_kit_flutter_full_gpl/statistics.dart';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter/widgets.dart';
import 'package:fluttertoast/fluttertoast.dart';
import 'package:intl/intl.dart';
import 'package:media_scanner/media_scanner.dart';
import 'package:path_provider/path_provider.dart';
import 'package:video_editor/video_editor.dart';
import 'package:video_player/video_player.dart';
import 'package:videocutter/Tab/TabBarViewWidget.dart';
import 'package:videocutter/Trim/video_trim.dart';
class Trim extends StatefulWidget {
const Trim({Key? key, required this.file}) : super(key: key);
final File file;
@OverRide
State createState() => _TrimState();
}
class _TrimState extends State {
late final VideoEditorController _controller;
late VideoPlayerController _videoPlayerController;
int duration = 0;
String formatter(Duration duration) =>
[
duration.inMinutes.remainder(60).toString().padLeft(2, '0'),
duration.inSeconds.remainder(60).toString().padLeft(2, '0')
].join(":");
final double height = 60;
ValueNotifier progressNotifier = ValueNotifier(0);
@OverRide
void initState() {
super.initState();
videoPlayerController =
VideoPlayerController.file(widget.file)
..initialize().then(() {
setState(() {
duration = _videoPlayerController.value.duration.inSeconds;
});
});
}
@OverRide
void dispose() {
_controller.dispose();
_videoPlayerController.dispose();
super.dispose();
}
/// Basic export video function
/// Basic export video function
bool istrim = true;
int progress = 0;
String? fileName;
Future trimVideos() async {
}
Future _showFileNameDialog(BuildContext context) async {
TextEditingController fileNameController = TextEditingController();
}
}
The text was updated successfully, but these errors were encountered: