tanersener / flutter-ffmpeg

FFmpeg plugin for Flutter. Not maintained anymore. Superseded by FFmpegKit.
GNU Lesser General Public License v3.0
645 stars 132 forks source link

No such file or directory error after saving mp4 to application documents directory #161

Closed philalem closed 4 years ago

philalem commented 4 years ago

Description I am new to ffmpeg, and I am trying to allow a user to film a video and save it to their profile. However,before they save it to their profile, I am attempting to generate a png thumbnail from the previously filmed video using flutter-ffmpeg.

That being said, when I attempt to generate the thumbnail I run:

var arguments = [
      "-y",
      "-i",
      "${widget.paths[0]}",
      "-vframes",
      "1",
      "-an",
      "-s",
      "-ss",
      "1",
      "$thumbnailPath"
    ];
await _flutterFFmpeg
    .executeWithArguments(arguments)
    .then((rc) => print("FFmpeg process exited with rc $rc"));

but the ffmpeg command fails with exit code 1.

Per the logs below, it is clear that ffmpeg cannot recognize the file path; however, I create the path using path_provider as follows:

final Directory extDir = await getApplicationDocumentsDirectory();
final String dirPath = '${extDir.path}/${uid.uid.toString()}/user-posts';
await Directory(dirPath).create(recursive: true);
final String filePath = '$dirPath/${timestamp()}.mp4';
print("path to recording: " + filePath);

The strange thing about this is that I can play the videos using said path with the video_player package; however, there appears to be something wrong with reading the videos via the flutter-ffmpeg package. There might be some step I'm missing.

Logs

flutter: Was video upload successful: true
flutter: ffmpeg version git-2020-01-25-fd11dd500
flutter:  Copyright (c) 2000-2020 the FFmpeg developers
flutter:
flutter:   built with Apple LLVM version 7.3.0 (clang-703.0.31)
flutter:   configuration: --sysroot=/Applications/Xcode-v7.3.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk --prefix=/Users/taner/Projects/mobile-ffmpeg/prebuilt/ios-arm64-apple-darwin/ffmpeg --enable-version3 --arch=aarch64 --cpu=armv8 --target-os=darwin --ar=/Applications/Xcode-v7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar --cc=clang --cxx=clang++ --as='/Users/taner/Projects/mobile-ffmpeg/.tmp/gas-preprocessor.pl -arch aarch64 -- clang -arch arm64 -target aarch64-ios-darwin -march=armv8-a+crc+crypto -mcpu=generic -DMOBILE_FFMPEG_ARM64 -Wno-unused-function -Wno-deprecated-declarations -fstrict-aliasing -fembed-bitcode -DIOS -DMOBILE_FFMPEG_LTS -DMOBILE_FFMPEG_BUILD_DATE=20200125 -isysroot /Applications/Xcode-v7.3.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk -Oz -miphoneos-version-min=9.3 -I/Applications/Xcode-v7.3.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/usr/include' --ranlib=/Applications/Xcode-v7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib --strip=/Applications/Xcode-v7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip --enable-neon --enable-cross-compile --enable-pic --enable-asm --enable-inline-asm --enable-optimizations --enable-swscale --enable-static --disable-shared --enable-small --disable-v4l2-m2m --disable-outdev=v4l2 --disable-outdev=fbdev --disable-indev=v4l2 --disable-indev=fbdev --disable-openssl --disable-xmm-clobber-test --disable-debug --disable-neon-clobber-test --disable-programs --disable-postproc --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages --disable-sndio --disable-schannel --disable-securetransport --disable-xlib --disable-cuda --disable-cuvid --disable-nvenc --disable-vaapi --disable-vdpau --disable-appkit --disable-alsa --disable-cuda --disable-cuvid --disable-nvenc --disable-vaapi --disable-vdpau --enable-libx264 --enable-gpl --enable-libxvid --enable-gpl --enable-libx265 --enable-gpl --enable-libvidstab --enable-gpl --disable-sdl2 --enable-zlib --enable-audiotoolbox --enable-coreimage --enable-bzlib --enable-videotoolbox --enable-avfoundation --disable-iconv
flutter:   libavutil      56. 38.100 / 56. 38.100
flutter:   libavcodec     58. 65.102 / 58. 65.102
flutter:   libavformat    58. 35.101 / 58. 35.101
flutter:   libavdevice    58.  9.103 / 58.  9.103
flutter:   libavfilter     7. 70.101 /  7. 70.101
flutter:   libswscale      5.  6.100 /  5.  6.100
flutter:   libswresample   3.  6.100 /  3.  6.100
flutter: FFmpeg process exited with rc 1
flutter: /var/mobile/Containers/Data/Application/303B0-F45DB-993D-4F78DEDBB56E/Documents/1234/user-posts/1593224609203.mp4: No such file or directory
flutter: Was thumbnail upload successful: true

Environment Flutter doctor output

Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, v1.17.4, on Mac OS X 10.15.5 19F101, locale en-US)

[✓] Android toolchain - develop for Android devices (Android SDK version 29.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 11.5)
[✓] Android Studio (version 3.6)
[✓] IntelliJ IDEA Community Edition (version 2019.3.4)
[✓] VS Code (version 1.46.1)
[!] Connected device
    ! No devices available

! Doctor found issues in 1 category.
tanersener commented 4 years ago

Your command fails due to a syntax error. Can you try the following one?

var arguments = [
      "-y",
      "-i",
      "${widget.paths[0]}",
      "-vframes",
      "1",
      "-an",
      "-ss",
      "00:01:00",
      "$thumbnailPath"
    ];
philalem commented 4 years ago

Thanks @tanersener, but it is still failing with the same error.

Logs

lutter: ffmpeg version git-2020-01-25-fd11dd500
flutter:  Copyright (c) 2000-2020 the FFmpeg developers
flutter:
flutter:   built with Apple LLVM version 7.3.0 (clang-703.0.31)
flutter:   configuration: --sysroot=/Applications/Xcode-v7.3.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk --prefix=/Users/taner/Projects/mobile-ffmpeg/prebuilt/ios-arm64-apple-darwin/ffmpeg --enable-version3 --arch=aarch64 --cpu=armv8 --target-os=darwin --ar=/Applications/Xcode-v7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ar --cc=clang --cxx=clang++ --as='/Users/taner/Projects/mobile-ffmpeg/.tmp/gas-preprocessor.pl -arch aarch64 -- clang -arch arm64 -target aarch64-ios-darwin -march=armv8-a+crc+crypto -mcpu=generic -DMOBILE_FFMPEG_ARM64 -Wno-unused-function -Wno-deprecated-declarations -fstrict-aliasing -fembed-bitcode -DIOS -DMOBILE_FFMPEG_LTS -DMOBILE_FFMPEG_BUILD_DATE=20200125 -isysroot /Applications/Xcode-v7.3.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk -Oz -miphoneos-version-min=9.3 -I/Applications/Xcode-v7.3.1.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS9.3.sdk/usr/include' --ranlib=/Applications/Xcode-v7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/ranlib --strip=/Applications/Xcode-v7.3.1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/strip --enable-neon --enable-cross-compile --enable-pic --enable-asm --enable-inline-asm --enable-optimizations --enable-swscale --enable-static --disable-shared --enable-small --disable-v4l2-m2m --disable-outdev=v4l2 --disable-outdev=fbdev --disable-indev=v4l2 --disable-indev=fbdev --disable-openssl --disable-xmm-clobber-test --disable-debug --disable-neon-clobber-test --disable-programs --disable-postproc --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages --disable-sndio --disable-schannel --disable-securetransport --disable-xlib --disable-cuda --disable-cuvid --disable-nvenc --disable-vaapi --disable-vdpau --disable-appkit --disable-alsa --disable-cuda --disable-cuvid --disable-nvenc --disable-vaapi --disable-vdpau --enable-libx264 --enable-gpl --enable-libxvid --enable-gpl --enable-libx265 --enable-gpl --enable-libvidstab --enable-gpl --disable-sdl2 --enable-zlib --enable-audiotoolbox --enable-coreimage --enable-bzlib --enable-videotoolbox --enable-avfoundation --disable-iconv
flutter:   libavutil      56. 38.100 / 56. 38.100
flutter:   libavcodec     58. 65.102 / 58. 65.102
flutter:   libavformat    58. 35.101 / 58. 35.101
flutter:   libavdevice    58.  9.103 / 58.  9.103
flutter:   libavfilter     7. 70.101 /  7. 70.101
flutter:   libswscale      5.  6.100 /  5.  6.100
flutter:   libswresample   3.  6.100 /  3.  6.100
flutter: /var/mobile/Containers/Data/Application/BEF7-E137-4F04-CB/Documents/1234/user-posts/1593262205894.mp4: No such file or directory
flutter: FFmpeg process exited with rc 1
tanersener commented 4 years ago

What is ${widget.paths[0]} and $thumbnailPath in that test?

Also, did you repeat the same test on a simulator and check whether that file really exists or not?

philalem commented 4 years ago

${widget.paths[0]} is the path that ffmpeg cannot resolve. It is the path to a video that was recorded with the camera package. $thumbnailPath is the same path as ${widget.paths[0]} but with a different file name.

To answer your question, I know the file exists because I save it to google cloud storage with the following code and it works just fine:

final StorageUploadTask uploadTask = storageReferences[i].putFile(
   File(widget.paths[i]),
   StorageMetadata(
     contentType: 'videos/.mp4',
   ),
);

Also here is the code to generate ${widget.paths[0]}:

final Directory extDir = await getApplicationDocumentsDirectory();
final String dirPath = '${extDir.path}/${uid.uid.toString()}/user-posts';
await Directory(dirPath).create(recursive: true);
final String filePath = '$dirPath/${timestamp()}.mp4';

Code to generate $thumbnailPath:

// widget.directoryPath is equal to dirPath in the above code
String timestamp() => DateTime.now().millisecondsSinceEpoch.toString();
thumbnailPath = '${widget.directoryPath}/${timestamp()}_thumb.png';
thumbnailReference = FirebaseStorage.instance.ref().child(thumbnailPath);

My previous logs have been from an iPhone 8. I just ran the same test on an android emulator, and I got the same result:

D/flutter-ffmpeg(24905): Running FFmpeg with arguments: [-y, -i, /data/user/0/com.creaid.creaid/app_flutter/OPdK9EKA4lc02M8vszEQBV3NBSg2/user-posts/1593287569833.mp4, -vframes, 1, -an, -ss, 00:01:00, /data/user/0/com.creaid.creaid/app_flutter/OPdK9EKA4lc02M8vszEQBV3NBSg2/user-posts/1593287574118_thumb.png].
I/flutter (24905): ffmpeg version git-2020-01-25-fd11dd500
I/flutter (24905):  Copyright (c) 2000-2020 the FFmpeg developers
I/flutter (24905):
I/flutter (24905):   built with Android (5220042 based on r346389c) clang version 8.0.7 (https://android.googlesource.com/toolchain/clang b55f2d4ebfd35bf643d27dbca1bb228957008617) (https://android.googlesource.com/toolchain/llvm 3c393fe7a7e13b0fba4ac75a01aa683d7a5b11cd) (based on LLVM 8.0.7svn)
I/flutter (24905):   configuration: --cross-prefix=i686-linux-android- --sysroot=/files/android-sdk/ndk-bundle/toolchains/llvm/prebuilt/linux-x86_64/sysroot --prefix=/home/taner/Projects/mobile-ffmpeg/prebuilt/android-x86/ffmpeg --pkg-config=/usr/bin/pkg-config --enable-version3 --arch=i686 --cpu=i686 --cc=i686-linux-android16-clang --cxx=i686-linux-android16-clang++ --target-os=android --disable-neon --disable-asm --disable-inline-asm --enable-cross-compile --enable-pic --enable-jni --enable-optimizations --enable-swscale --enable-shared --disable-v4l2-m2m --disable-outdev=v4l2 --disable-outdev=fbdev --disable-indev=v4l2 --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 --di
I/flutter (24905):   libavutil      56. 38.100 / 56. 38.100
I/flutter (24905):   libavcodec     58. 65.102 / 58. 65.102
I/flutter (24905):   libavformat    58. 35.101 / 58. 35.101
I/flutter (24905):   libavdevice    58.  9.103 / 58.  9.103
I/flutter (24905):   libavfilter     7. 70.101 /  7. 70.101
I/flutter (24905):   libswscale      5.  6.100 /  5.  6.100
I/flutter (24905):   libswresample   3.  6.100 /  3.  6.100
D/flutter-ffmpeg(24905): FFmpeg exited with rc: 1
I/flutter (24905): FFmpeg process exited with rc 1
I/flutter (24905): /data/user/0/com.c.c/app_flutter/1234/user-posts/1593287569833.mp4: No such file or directory
tanersener commented 4 years ago

Can you check the file statistics just before running _flutterFFmpeg.executeWithArguments? I want to make sure that file is not a link and has a valid size.

import 'dart:io';
File file = new File(widget.paths[i]);

var statSync = file.statSync();
print("File: ${videoPath}, exists: ${file.existsSync()}, size: ${statSync.size}, mode: ${statSync.modeString()}, type: ${statSync.type}, lastModified: ${statSync.modified}");

I can't reproduce this issue locally. I'm using the same functions to generate file paths and they all work fine. However, the way I use to generate the input video is different. So, can you give me some details about how can I create and access the input video as you do in your app?

philalem commented 4 years ago

Here are the logs you requested:

flutter: File: /var/mobile/Containers/Data/Application/1DED5AF4-CE1A-21-B21B-32/Documents/1234/user-posts/1593351895519.mp4,
 exists: false,
 size: -1,
 mode: ---------,
 type: notFound,
 lastModified: 1970-01-01 00:00:00.000Z

I understand the above logs indicate that there is no file, but if that were the case, why does it save properly to firebase using the same File() widget?

To generally reproduce my code, you need the camera package and should do something like the following:

// you will probably need to do more initialization for the camera controller.
// I did not show it here to be more succinct
CameraController _controller = CameraController();

final Directory extDir = await getApplicationDocumentsDirectory();
final String dirPath = '${extDir.path}/${uid.uid.toString()}/user-posts';
await Directory(dirPath).create(recursive: true);
final String filePath = '$dirPath/${timestamp()}.mp4';
print("path to recording: " + filePath);

await _controller.startVideoRecording(filePath);
Timer(Duration(seconds: 3), () {
  print("Waiting three seconds to record something...");
});
await _controller.stopVideoRecording();
tanersener commented 4 years ago

Thanks. I don't know why your upload doesn't fail. You must have been doing something differently.

Btw, tested camera and flutter_ffmpeg plugins together by modifying the test application of camera. It worked fine without any errors. You can see its source code in this gist, camera_flutter_ffmpeg.dart. When video recording is stopped flutter_ffmpeg executes a video copy command using flutter_ffmpeg.

Source code of that test is very similar to your source code. I believe you can find what is is wrong with your app by comparing its source code with this gist.

philalem commented 4 years ago

Thanks for the gist. I figured out my issue. For some reason, I forgot that I deleted the file's sync before I generated the thumbnail. That's the reason why there was a "No such file or directory" error. 🤦🏻‍♂️ Thank's for all your help.