如何获取 flutter ffmpeg 的输出视频 |不允许操作

how to get output video of flutter ffmpeg | operation not permitted

我正在使用 flutter ffmpeg 并尝试将输出视频保存在本地存储中,但出现错误,请帮助我,我尝试了太多解决方案,但 none 个都有效。感谢您 :)
通过 path_provider package

获取输出路径
code: String outputPath = (appDocDir.absolute.path + '/o.mp4').toString();

Performing hot restart...
Syncing files to device Pixel 5...
Restarted application in 1,451ms.
D/FilePickerDelegate( 8662): Selected type video/*
I/FilePickerUtils( 8662): Caching from URI: content://com.android.providers.media.documents/document/video%3A5332
I/OpenGLRenderer( 8662): Davey! duration=226847ms; Flags=1, FrameTimelineVsyncId=4722756, IntendedVsync=131408633604624, Vsync=131408633604624, InputEventId=0, HandleInputStart=131408633999713, AnimationStart=131408634002004, PerformTraversalsStart=131408634002733, DrawStart=131408634666067, FrameDeadline=131408716937954, FrameInterval=131408633989400, FrameStartTime=16666666, SyncQueued=131408636245702, SyncStart=131408636326588, IssueDrawCommandsStart=131408641269661, SwapBuffers=131408676689452, FrameCompleted=131635481327282, DequeueBufferDuration=3359323, QueueBufferDuration=676771, GpuCompleted=131635481327282, SwapBuffersCompleted=131408678665598, DisplayPresentTime=0, 
I/OpenGLRenderer( 8662): Davey! duration=226847ms; Flags=1, FrameTimelineVsyncId=4722756, IntendedVsync=131408633604624, Vsync=131408633604624, InputEventId=0, HandleInputStart=131408633999713, AnimationStart=131408634002004, PerformTraversalsStart=131408634002733, DrawStart=131408634666067, FrameDeadline=131408733604620, FrameInterval=131408633989400, FrameStartTime=16666666, SyncQueued=131408636245702, SyncStart=131408636326588, IssueDrawCommandsStart=131408641269661, SwapBuffers=131408676689452, FrameCompleted=131635481327282, DequeueBufferDuration=3359323, QueueBufferDuration=676771, GpuCompleted=131635481327282, SwapBuffersCompleted=131408678665598, DisplayPresentTime=0, 
D/FilePickerUtils( 8662): File loaded and cached at:/data/user/0/com.example.ffmpeg_sample/cache/file_picker/VID-20211221-WA0004.mp4
D/FilePickerDelegate( 8662): File path:[com.mr.flutter.plugin.filepicker.FileInfo@af3dcb6]
I/flutter ( 8662): new video path is: /data/user/0/com.example.ffmpeg_sample/cache/file_picker/VID-20211221-WA0004.mp4
D/flutter-ffmpeg( 8662): Running FFmpeg with arguments: [-i, /data/user/0/com.example.ffmpeg_sample/cache/file_picker/VID-20211221-WA0004.mp4, -vf, curves=vintage, -y, /data/user/0/com.example.ffmpeg_sample/app_flutter/o.mp4].
I/mobile-ffmpeg( 8662): ffmpeg version v4.4-dev-416
I/mobile-ffmpeg( 8662):  Copyright (c) 2000-2020 the FFmpeg developers
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):   built with Android (6454773 based on r365631c2) clang version 9.0.8 (https://android.googlesource.com/toolchain/llvm-project 98c855489587874b2a325e7a516b99d838599c6f) (based on LLVM 9.0.8svn)
I/mobile-ffmpeg( 8662):   configuration: --cross-prefix=aarch64-linux-android- --sysroot=/files/android-sdk/ndk/21.3.6528147/toolchains/llvm/prebuilt/linux-x86_64/sysroot --prefix=/home/taner/Projects/mobile-ffmpeg/prebuilt/android-arm64/ffmpeg --pkg-config=/usr/bin/pkg-config --enable-version3 --arch=aarch64 --cpu=armv8-a --cc=aarch64-linux-android21-clang --cxx=aarch64-linux-android21-clang++ --extra-libs='-L/storage/light/projects/mobile-ffmpeg/prebuilt/android-arm64/cpu-features/lib -lndk_compat' --target-os=android --enable-neon --enable-asm --enable-inline-asm --enable-cross-compile --enable-pic --enable-jni --enable-optimizations --enable-swscale --enable-shared --enable-v4l2-m2m --disable-outdev=fbdev --disable-indev=fbdev --enable-small --disable-openssl --disable-xmm-clobber-test --disable-debug --enable-lto --disable-neon-clobber-test --disable-programs --disable-postproc --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages --disable-static --disable-sndio --disable-schannel --disable-securetransport --disable-xlib --disable-cuda --disable-cuvid --disable-nvenc --disable-vaapi --disable-vdpau --disable-videotoolbox --disable-audiotoolbox --disable-appkit --disable-alsa --disable-cuda --disable-cuvid --disable-nvenc --disable-vaapi --disable-vdpau --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-gmp --enable-gnutls --enable-libmp3lame --enable-libass --enable-iconv --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libxml2 --enable-libopencore-amrnb --enable-libshine --enable-libspeex --enable-libwavpack --enable-libkvazaar --enable-libilbc --enable-libopus --enable-libsnappy --enable-libsoxr --enable-libaom --enable-libtwolame --disable-sdl2 --enable-libvo-amrwbenc --enable-zlib --enable-mediacodec
I/mobile-ffmpeg( 8662):   libavutil      56. 55.100 / 56. 55.100
I/mobile-ffmpeg( 8662):   libavcodec     58. 96.100 / 58. 96.100
I/mobile-ffmpeg( 8662):   libavformat    58. 48.100 / 58. 48.100
I/mobile-ffmpeg( 8662):   libavdevice    58. 11.101 / 58. 11.101
I/mobile-ffmpeg( 8662):   libavfilter     7. 87.100 /  7. 87.100
I/mobile-ffmpeg( 8662):   libswscale      5.  8.100 /  5.  8.100
I/mobile-ffmpeg( 8662):   libswresample   3.  8.100 /  3.  8.100
I/mobile-ffmpeg( 8662): Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/data/user/0/com.example.ffmpeg_sample/cache/file_picker/VID-20211221-WA0004.mp4':
I/mobile-ffmpeg( 8662):   Metadata:
I/mobile-ffmpeg( 8662):     major_brand     : 
I/mobile-ffmpeg( 8662): isom
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):     minor_version   : 
I/mobile-ffmpeg( 8662): 512
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):     compatible_brands: 
I/mobile-ffmpeg( 8662): isomiso2avc1mp41
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):     encoder         : 
I/mobile-ffmpeg( 8662): Lavf58.20.100
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):   Duration: 
I/mobile-ffmpeg( 8662): 00:00:02.10
I/mobile-ffmpeg( 8662): , start: 
I/mobile-ffmpeg( 8662): 0.000000
I/mobile-ffmpeg( 8662): , bitrate: 
I/mobile-ffmpeg( 8662): 551 kb/s
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):     Stream #0:0
I/mobile-ffmpeg( 8662): (und)
I/mobile-ffmpeg( 8662): : Video: h264 (avc1 / 0x31637661), yuv420p, 208x208, 547 kb/s
I/mobile-ffmpeg( 8662): , 
I/mobile-ffmpeg( 8662): 20 fps, 
I/mobile-ffmpeg( 8662): 20 tbr, 
I/mobile-ffmpeg( 8662): 10240 tbn, 
I/mobile-ffmpeg( 8662): 40 tbc
I/mobile-ffmpeg( 8662):  (default)
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):     Metadata:
I/mobile-ffmpeg( 8662):       handler_name    : 
I/mobile-ffmpeg( 8662): VideoHandler
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662): Stream mapping:
I/mobile-ffmpeg( 8662):   Stream #0:0 -> #0:0
I/mobile-ffmpeg( 8662):  (h264 (native) -> mpeg4 (native))
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662): Press [q] to stop, [?] for help
I/mobile-ffmpeg( 8662): frame=    0 fps=0.0 q=0.0 size=       0kB time=-577014:32:22.77 bitrate=  -0.0kbits/s speed=N/A    
W/mobile-ffmpeg( 8662): [graph 0 input from stream 0:0 @ 0x7a282228d0] sws_param option is deprecated and ignored
W/mobile-ffmpeg( 8662): [swscaler @ 0x7b989ee7f0] No accelerated colorspace conversion found from yuv420p to rgb24.
I/mobile-ffmpeg( 8662): Output #0, mp4, to '/data/user/0/com.example.ffmpeg_sample/app_flutter/o.mp4':
I/mobile-ffmpeg( 8662):   Metadata:
I/mobile-ffmpeg( 8662):     major_brand     : 
I/mobile-ffmpeg( 8662): isom
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):     minor_version   : 
I/mobile-ffmpeg( 8662): 512
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):     compatible_brands: 
I/mobile-ffmpeg( 8662): isomiso2avc1mp41
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):     encoder         : 
I/mobile-ffmpeg( 8662): Lavf58.48.100
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):     Stream #0:0
I/mobile-ffmpeg( 8662): (und)
I/mobile-ffmpeg( 8662): : Video: mpeg4 (mp4v / 0x7634706D), yuv420p, 208x208, q=2-31, 200 kb/s
I/mobile-ffmpeg( 8662): , 
I/mobile-ffmpeg( 8662): 20 fps, 
I/mobile-ffmpeg( 8662): 10240 tbn, 
I/mobile-ffmpeg( 8662): 20 tbc
I/mobile-ffmpeg( 8662):  (default)
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):     Metadata:
I/mobile-ffmpeg( 8662):       handler_name    : 
I/mobile-ffmpeg( 8662): VideoHandler
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):       encoder         : 
I/mobile-ffmpeg( 8662): Lavc58.96.100 mpeg4
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662):     Side data:
I/mobile-ffmpeg( 8662):       
I/mobile-ffmpeg( 8662): cpb: 
I/mobile-ffmpeg( 8662): bitrate max/min/avg: 0/0/200000 buffer size: 0 
I/mobile-ffmpeg( 8662): vbv_delay: N/A
I/mobile-ffmpeg( 8662): 
I/mobile-ffmpeg( 8662): frame=   42 fps=0.0 q=6.7 Lsize=      99kB time=00:00:02.05 bitrate= 394.4kbits/s speed=4.22x    
I/mobile-ffmpeg( 8662): video:98kB audio:0kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 
I/mobile-ffmpeg( 8662): 1.040646%
I/mobile-ffmpeg( 8662): 
D/flutter-ffmpeg( 8662): FFmpeg exited with rc: 0
I/flutter ( 8662): FFmpeg process exited with re: 0
I/flutter ( 8662): /data/user/0/com.example.ffmpeg_sample/app_flutter/o.mp4

更改了输出路径:
String outputPath = '/storage/emulated/0/video/o.mp4';

Launching lib\main.dart on Pixel 5 in debug mode...
Running Gradle task 'assembleDebug'...
√  Built build\app\outputs\flutter-apk\app-debug.apk.
Installing build\app\outputs\flutter-apk\app.apk...
Debug service listening on ws://127.0.0.1:54633/Ykc3Xz8Aoi8=/ws
Syncing files to device Pixel 5...
I/Gralloc4( 1550): mapper 4.x is not supported
W/Gralloc3( 1550): mapper 3.x is not supported
W/Gralloc4( 1550): allocator 4.x is not supported
W/Gralloc3( 1550): allocator 3.x is not supported
D/permissions_handler( 1550): No permissions found in manifest for: []22
D/permissions_handler( 1550): No permissions found in manifest for: []22
D/FilePickerDelegate( 1550): Selected type video/*
E/cutils-trace( 1550): Error opening trace file: No such file or directory (2)
D/CompatibilityChangeReporter( 1550): Compat change id reported: 78294732; UID 10229; state: DISABLED
I/FilePickerUtils( 1550): Caching from URI: content://com.android.providers.media.documents/document/video%3A5347
D/FilePickerUtils( 1550): File loaded and cached at:/data/user/0/com.example.ffmpeg_sample/cache/file_picker/VID-20211221-WA0010.mp4
D/FilePickerDelegate( 1550): File path:[com.mr.flutter.plugin.filepicker.FileInfo@bb9e260]
I/OpenGLRenderer( 1550): Davey! duration=36685ms; Flags=1, FrameTimelineVsyncId=4687973, IntendedVsync=130538053233976, Vsync=130538053233976, InputEventId=0, HandleInputStart=130538053733013, AnimationStart=130538053735357, PerformTraversalsStart=130538053736138, DrawStart=130538054754472, FrameDeadline=130538103233974, FrameInterval=130538053722076, FrameStartTime=16666666, SyncQueued=130538057200305, SyncStart=130538057291295, IssueDrawCommandsStart=130538059598899, SwapBuffers=130538096356295, FrameCompleted=130574739168052, DequeueBufferDuration=5764114, QueueBufferDuration=721302, GpuCompleted=130574739168052, SwapBuffersCompleted=130538098217336, DisplayPresentTime=4294967295, 
I/OpenGLRenderer( 1550): Davey! duration=36685ms; Flags=1, FrameTimelineVsyncId=4687973, IntendedVsync=130538053233976, Vsync=130538053233976, InputEventId=0, HandleInputStart=130538053733013, AnimationStart=130538053735357, PerformTraversalsStart=130538053736138, DrawStart=130538054754472, FrameDeadline=130538119900640, FrameInterval=130538053722076, FrameStartTime=16666666, SyncQueued=130538057200305, SyncStart=130538057291295, IssueDrawCommandsStart=130538059598899, SwapBuffers=130538096356295, FrameCompleted=130574739168052, DequeueBufferDuration=5764114, QueueBufferDuration=721302, GpuCompleted=130574739168052, SwapBuffersCompleted=130538098217336, DisplayPresentTime=4294967295, 
I/flutter ( 1550): new video path is: /data/user/0/com.example.ffmpeg_sample/cache/file_picker/VID-20211221-WA0010.mp4
D/flutter-ffmpeg( 1550): Running FFmpeg with arguments: [-i, /data/user/0/com.example.ffmpeg_sample/cache/file_picker/VID-20211221-WA0010.mp4, -vf, curves=vintage, -y, /storage/emulated/0/video/o.mp4].
I/mobile-ffmpeg( 1550): Loading mobile-ffmpeg.
I/mobile-ffmpeg( 1550): Loaded mobile-ffmpeg-full-arm64-v8a-4.4-lts-20210207.
D/mobile-ffmpeg( 1550): Callback thread started.
I/mobile-ffmpeg( 1550): ffmpeg version v4.4-dev-416
I/mobile-ffmpeg( 1550):  Copyright (c) 2000-2020 the FFmpeg developers
I/mobile-ffmpeg( 1550): 
I/mobile-ffmpeg( 1550):   built with Android (6454773 based on r365631c2) clang version 9.0.8 (https://android.googlesource.com/toolchain/llvm-project 98c855489587874b2a325e7a516b99d838599c6f) (based on LLVM 9.0.8svn)
I/mobile-ffmpeg( 1550):   configuration: --cross-prefix=aarch64-linux-android- --sysroot=/files/android-sdk/ndk/21.3.6528147/toolchains/llvm/prebuilt/linux-x86_64/sysroot --prefix=/home/taner/Projects/mobile-ffmpeg/prebuilt/android-arm64/ffmpeg --pkg-config=/usr/bin/pkg-config --enable-version3 --arch=aarch64 --cpu=armv8-a --cc=aarch64-linux-android21-clang --cxx=aarch64-linux-android21-clang++ --extra-libs='-L/storage/light/projects/mobile-ffmpeg/prebuilt/android-arm64/cpu-features/lib -lndk_compat' --target-os=android --enable-neon --enable-asm --enable-inline-asm --enable-cross-compile --enable-pic --enable-jni --enable-optimizations --enable-swscale --enable-shared --enable-v4l2-m2m --disable-outdev=fbdev --disable-indev=fbdev --enable-small --disable-openssl --disable-xmm-clobber-test --disable-debug --enable-lto --disable-neon-clobber-test --disable-programs --disable-postproc --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages --disable-static --disable-sndio --disable-schannel --disable-securetransport --disable-xlib --disable-cuda --disable-cuvid --disable-nvenc --disable-vaapi --disable-vdpau --disable-videotoolbox --disable-audiotoolbox --disable-appkit --disable-alsa --disable-cuda --disable-cuvid --disable-nvenc --disable-vaapi --disable-vdpau --enable-libfontconfig --enable-libfreetype --enable-libfribidi --enable-gmp --enable-gnutls --enable-libmp3lame --enable-libass --enable-iconv --enable-libtheora --enable-libvorbis --enable-libvpx --enable-libwebp --enable-libxml2 --enable-libopencore-amrnb --enable-libshine --enable-libspeex --enable-libwavpack --enable-libkvazaar --enable-libilbc --enable-libopus --enable-libsnappy --enable-libsoxr --enable-libaom --enable-libtwolame --disable-sdl2 --enable-libvo-amrwbenc --enable-zlib --enable-mediacodec
I/mobile-ffmpeg( 1550):   libavutil      56. 55.100 / 56. 55.100
I/mobile-ffmpeg( 1550):   libavcodec     58. 96.100 / 58. 96.100
I/mobile-ffmpeg( 1550):   libavformat    58. 48.100 / 58. 48.100
I/mobile-ffmpeg( 1550):   libavdevice    58. 11.101 / 58. 11.101
I/mobile-ffmpeg( 1550):   libavfilter     7. 87.100 /  7. 87.100
I/mobile-ffmpeg( 1550):   libswscale      5.  8.100 /  5.  8.100
I/mobile-ffmpeg( 1550):   libswresample   3.  8.100 /  3.  8.100
I/mobile-ffmpeg( 1550): Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/data/user/0/com.example.ffmpeg_sample/cache/file_picker/VID-20211221-WA0010.mp4':
I/mobile-ffmpeg( 1550):   Metadata:
I/mobile-ffmpeg( 1550):     major_brand     : 
I/mobile-ffmpeg( 1550): mp4v
I/mobile-ffmpeg( 1550): 
I/mobile-ffmpeg( 1550):     minor_version   : 
I/mobile-ffmpeg( 1550): 0
I/mobile-ffmpeg( 1550): 
I/mobile-ffmpeg( 1550):     compatible_brands: 
I/mobile-ffmpeg( 1550): mp4vmp42isom
I/mobile-ffmpeg( 1550): 
I/mobile-ffmpeg( 1550):   Duration: 
I/mobile-ffmpeg( 1550): 00:00:01.00
I/mobile-ffmpeg( 1550): , start: 
I/mobile-ffmpeg( 1550): 0.000000
I/mobile-ffmpeg( 1550): , bitrate: 
I/mobile-ffmpeg( 1550): 1587 kb/s
I/mobile-ffmpeg( 1550): 
I/mobile-ffmpeg( 1550):     Stream #0:0
I/mobile-ffmpeg( 1550): (und)
I/mobile-ffmpeg( 1550): : Video: h264 (avc1 / 0x31637661), yuv420p, 480x480 [SAR 1:1 DAR 1:1], 1581 kb/s
I/mobile-ffmpeg( 1550): , 
I/mobile-ffmpeg( 1550): 10 fps, 
I/mobile-ffmpeg( 1550): 10 tbr, 
I/mobile-ffmpeg( 1550): 10240 tbn, 
I/mobile-ffmpeg( 1550): 20 tbc
I/mobile-ffmpeg( 1550):  (default)
I/mobile-ffmpeg( 1550): 
E/mobile-ffmpeg( 1550): /storage/emulated/0/video/o.mp4: Operation not permitted
D/flutter-ffmpeg( 1550): FFmpeg exited with rc: 1
I/flutter ( 1550): FFmpeg process exited with re: 1
I/flutter ( 1550): /storage/emulated/0/video/o.mp4



我在 AndroidMainfest.xml

中添加了这些权限
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.READ_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />



ffmpeg_pi.dart

import 'dart:io';
import 'package:flutter/cupertino.dart';
import 'package:flutter_ffmpeg/flutter_ffmpeg.dart';
import 'package:path_provider/path_provider.dart';

edit(String videoPath) async {
  FlutterFFmpeg fFmpeg = FlutterFFmpeg();
  Directory appDocDir = await getApplicationDocumentsDirectory();
  String outputPath = (appDocDir.absolute.path + '/o.mp4').toString();
  String command = '-i $videoPath -vf curves=vintage -y $outputPath';

  await fFmpeg.execute(command).then((rc) {
    debugPrint("FFmpeg process exited with re: $rc");
  });
  debugPrint(outputPath);
}



select_file.dart

import 'dart:io';
import 'package:file_picker/file_picker.dart';
import 'package:flutter/material.dart';
import 'package:permission_handler/permission_handler.dart';
import 'ffmpeg_pi.dart';

class SelectFile extends StatefulWidget {
  const SelectFile({Key? key}) : super(key: key);

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

class _SelectFileState extends State<SelectFile> {
  File? video;
  String? videoPath;

  pickFile(BuildContext context) async {
    FilePickerResult? result =
        await FilePicker.platform.pickFiles(type: FileType.video);
    if (result != null) {
      setState(() {
        video = File(result.files.single.path!);
        videoPath = result.files.single.path!;
      });
      debugPrint("new video path is: " + videoPath!);
    }
  }

  getPermission() async {
    Permission.storage.request();
    Permission.manageExternalStorage.request();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        mainAxisAlignment: MainAxisAlignment.center,
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          TextButton(
            onPressed: () {
              getPermission();
            },
            child: const Text("get Permission"),
          ),
          const Text("select video"),
          const SizedBox(
            height: 50,
            width: double.infinity,
          ),
          ElevatedButton(
            onPressed: () async {
              await pickFile(context);
            },
            child: const Text("Select video"),
          ),
          const SizedBox(height: 50),
          Text(videoPath ?? "no file selected"),
          const SizedBox(height: 100),
          ElevatedButton(
            onPressed: () {
              edit(videoPath!);
            },
            child: const Text("edit"),
          ),
        ],
      ),
    );
  }
}

我得到了解决方案所以我在这里回答,问题不是 flutter_ffmpeg,问题是因为应用程序没有权限写入外部存储来解决这个添加 "MANAGE_EXTERNAL_STORAGE" in mainfest.xml 文件并设置输出路径为 File('storage/emulated/0/my_folder/o.mp4').path ,一切正常。

<uses-permission android:name="android.permission.MANAGE_EXTERNAL_STORAGE" /> 

String outputPath = File('storage/emulated/0/my_folder/o.mp4').path;