sbis04 / video_trimmer

Flutter video trimmer package
https://pub.dev/packages/video_trimmer
MIT License
434 stars 263 forks source link

Can not open file video from VideoThumbnail after trim video on IOS( iPhone 12 ). #204

Open commond140 opened 1 year ago

commond140 commented 1 year ago

I use video_thumbnail: ^0.5.3 and video_trimmer: ^2.0.1 It can not open file when edited video from video_trimmer. If open video but did not trim video and save. video_thumbnail can open the file.

some code from video_thumbnail

Future<Uint8List?> generateThumbnail(File file) async {
    final thumbnail = await VideoThumbnail.thumbnailData(
      video: file.path,
      imageFormat: ImageFormat.JPEG,
      maxHeight: 80,
      maxWidth: 80,
      quality: 5,
    );
    return thumbnail;
  }
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:get/get.dart';
import 'package:video_trimmer/video_trimmer.dart';
import 'package:wiz_build/constants/app_colors.dart';
import 'package:wiz_build/constants/app_icons.dart';
import 'package:wiz_build/widgets/common/app_icon_button.dart';

class ToReviewVideoTrimmer extends StatefulWidget {
  final File file;
  final Future<void> Function(String path, String type) onSaveFile;

  const ToReviewVideoTrimmer({
    super.key,
    required this.file,
    required this.onSaveFile,
  });

  @override
  State<ToReviewVideoTrimmer> createState() => _ToReviewVideoTrimmerState();
}

class _ToReviewVideoTrimmerState extends State<ToReviewVideoTrimmer> {
  final Trimmer _trimmer = Trimmer();

  double _startValue = 0.0;
  double _endValue = 0.0;

  bool _isPlaying = false;
  bool _progressVisibility = false;
  bool _showPlay = false;

  Future<String?> _saveVideo() async {
    String? _value;

    await _trimmer.saveTrimmedVideo(
      startValue: _startValue,
      endValue: _endValue,
      onSave: (outputPath) {
        setState(() {
          _progressVisibility = false;
          _value = outputPath;
          widget.onSaveFile(outputPath ?? '', 'Video');
        });
      },
    );

    return _value;
  }

  void _loadVideo() {
    _trimmer.loadVideo(videoFile: widget.file).then((value) {
      setState(() {
        _showPlay = true;
      });
    });
  }

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

    _loadVideo();
  }

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

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Builder(
        builder: (context) => Center(
          child: Container(
            padding: EdgeInsets.only(top: 30.spMin, bottom: 30.spMin),
            color: Colors.black,
            child: Stack(
              children: [
                VideoViewer(
                  trimmer: _trimmer,
                ),
                Positioned(
                  top: 4.sp,
                  left: 10.sp,
                  child: AppIconButton(
                    size: 50.spMin,
                    borderColor: Colors.white,
                    color: Colors.black,
                    borderRadius: 25.spMin,
                    icon: AppIcons.cross,
                    onTap: Get.back,
                  ),
                ),
                Padding(
                  padding: EdgeInsets.symmetric(vertical: 56.sp),
                  child: Column(
                    mainAxisAlignment: MainAxisAlignment.spaceBetween,
                    children: [
                      Center(
                        child: TrimViewer(
                          trimmer: _trimmer,
                          viewerHeight: 50.0,
                          viewerWidth: MediaQuery.of(context).size.width,
                          showDuration: true,
                          maxVideoLength: const Duration(seconds: 30),
                          onChangeStart: (value) => _startValue = value,
                          onChangeEnd: (value) => _endValue = value,
                          onChangePlaybackState: (value) =>
                              setState(() => _isPlaying = value),
                        ),
                      ),
                      Visibility(
                        visible: _showPlay,
                        child: AppIconButton(
                          size: 50.spMin,
                          borderColor: AppColors.primary,
                          color: AppColors.primary,
                          borderRadius: 25.spMin,
                          icon: _isPlaying ? AppIcons.pause : AppIcons.play,
                          iconHeight: 15.sp,
                          iconWidth: 13.sp,
                          onTap: () async {
                            final playbackState =
                                await _trimmer.videoPlaybackControl(
                              startValue: _startValue,
                              endValue: _endValue,
                            );
                            setState(() {
                              _isPlaying = playbackState;
                            });
                          },
                        ),
                      ),
                      AppIconButton(
                        size: 64.spMin,
                        borderColor: Colors.white,
                        color: Colors.black,
                        borderRadius: 32.spMin,
                        icon: AppIcons.tick,
                        onTap: _progressVisibility
                            ? null
                            : () async {
                                await _saveVideo().then((outputPath) {
                                  const snackBar = SnackBar(
                                      content:
                                          Text('Video Saved successfully'));
                                  ScaffoldMessenger.of(context).showSnackBar(
                                    snackBar,
                                  );
                                });
                              },
                      ),
                    ],
                  ),
                ),
              ],
            ),
          ),
        ),
      ),
    );
  }
}
programmermager commented 5 months ago

try to add ffmpegCommand: '-c:a aac -c:v copy', in parameter saveTrimmedVideo it works for me