Skip to content
New issue

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

[ReactNative] FFmpegKitConfig.getSafParameterForWrite return -1.unknown with absolute path #205

Closed
iclassPeter opened this issue Oct 26, 2021 · 6 comments
Assignees
Labels
android Affect Android platform enhancement New feature or request fixed-in-v4.5.1 flutter Affect flutter platform react-native Affect react-native platform saf Issue about storage access framework v4.5 Affects v4.5 release

Comments

@iclassPeter
Copy link

Description
Doing React Native video conversion, I reckon path conversion is needed for android. Failed to convert video with absolute path (maybe I was using wrong absolute path syntax for android?)

For inputPath, I am able to convert successfully as the original path is get from file system and tested and used inputSafUrl on FFprobeKit.getMediaInformationAsync.

However I fail to do the same for outputPath as I am using absolute path?

Expected behavior
Convert path to saf path so ffmpeg can read.

Current behavior
saf:-1.unknown is returned from FFmpegKitConfig.getSafParameterForWrite

To Reproduce
For context, video conversion using FFmpegKit.executeAsync with argument:
-y -i ${inputPath} -map 0 -c:v libx264 -crf 18 -c:a copy ${outputPath}"

The part including FFmpegKitConfig.getSafParameterForWrite:

prepareVideoConversion = (inputRawPath:string, duration:number, inputSafPath?:string) => {

    let inputPath = inputSafPath || inputRawPath;
    
    let outputName = `${new Date().toISOString().slice(0, 19)}.mp4`;
    let outputDir = `${RNFS.DocumentDirectoryPath}/temp/`;
    let outputRawPath = outputDir + outputName;

    // conversion would fail if dir not exist
    RNFS.mkdir(outputDir).then( 
        (res)=>{
            console.log('outputDir created/existed:',outputDir)
            if (Platform.OS === 'ios') {
                outputRawPath = 'file://' + outputRawPath;
                this.convertVideo(inputRawPath, outputRawPath, duration);
            } else if (Platform.OS === "android") {
                let androidOutputPath = outputRawPath;
                // console.log('Test whether output need content://.');androidOutputPath = 'content:/' + outputRawPath
                // console.log('Test using inputpath as output path.'); androidOutputPath = 'inputRawPath';
                FFmpegKitConfig.getSafParameterForWrite(androidOutputPath).then(outputSafUrl => {
                    this.convertVideo(inputRawPath, outputRawPath, duration, inputSafPath, outputSafUrl);
                });
            }
        },
        (reason)=>{
            console.log('error on mkdir:', reason);
        }
    );
}

Screenshots
Capture1

Logs

Environment

  • Platform: React Native
  • Architecture: Android simulator Google Pixel 4a on Window 10
  • Version (if applicable) v4.5
  • Android Studio version (if applicable) 11.0.10+0-b96-7249189 amd64
@tanersener
Copy link
Collaborator

FFmpegKitConfigs getSafParameter methods support URIs created by SAF only. If the URI passed to those methods is created manually, the result is unpredictable. Most of the time, conversion fails and invalid paths are created. As far as I see, this is what happens in your case too.

@tanersener tanersener added react-native Affect react-native platform v4.5 Affects v4.5 release saf Issue about storage access framework labels Oct 26, 2021
@iclassPeter
Copy link
Author

iclassPeter commented Oct 27, 2021

I was stuggling what casued returnCode -1 when I was using manually created absolute path as outpath (worked for ios), so tried to use getSafParameter for output path.
Now I remember not giving logCallBack will print more info to debug and tried using back absolute path for output, somehow it seems the error was from input path using saf... saf:96.mp4: Bad file descriptor

log

 -----Convert video-----
[Wed Oct 27 2021 18:11:45.712]  LOG      inputPath: saf:96.mp4
[Wed Oct 27 2021 18:11:45.712]  LOG      outputPath: /data/user/0/com.packagename/cache/temp2021-10-27T10:11:41.mp4
[Wed Oct 27 2021 18:11:45.712]  LOG      FFmpeg process started with arguments:
'-i saf:96.mp4 -map 0 -c:v libx264 -crf 18 -c:a copy /data/user/0/com.packagename/cache/temp2021-10-27T10:11:41.mp4"'.
[Wed Oct 27 2021 18:11:45.986]  LOG      saf:96.mp4: Bad file descriptor
[Wed Oct 27 2021 18:11:45.986]  LOG      returnCode: 1
[Wed Oct 27 2021 18:11:45.986]  LOG      conversion - ERROR
[Wed Oct 27 2021 18:11:45.987]  LOG      FailStackTrace: {"_U": 0, "_V": 0, "_W": null, "_X": null}
[Wed Oct 27 2021 18:11:45.987]  LOG      state: {"_U": 0, "_V": 0, "_W": null, "_X": null}

@tanersener
Copy link
Collaborator

Would you mind sharing something we can use to reproduce this? Hard to say what is wrong by just looking at logs. Also, we don't see any issues with the current implementation in the test applications we have under ffmpeg-kit-test.

@iclassPeter
Copy link
Author

Here is a minified repo which could reproduce the issue. Mainly converting HEVC to AVC. Code related are in ~/VideoActivity (sorry in advance if my codes looks messy). Video files used to test are collected from online https://x265.com/hevc-video-files/ and downloaded inside emulator.

Platform: React Native
Architecture: Android simulator Google Pixel 4a
Version (if applicable) v4.5 with 'full-gpl-lts'
Android Studio version (if applicable) 11.0.10+0-b96-7249189 amd64

@tanersener tanersener added the documentation-bug Documentation is missing or wrong label Oct 29, 2021
@tanersener tanersener self-assigned this Oct 29, 2021
@tanersener tanersener added all-platforms android Affect Android platform flutter Affect flutter platform react-native Affect react-native platform and removed react-native Affect react-native platform all-platforms labels Oct 29, 2021
@tanersener
Copy link
Collaborator

Thanks.

saf protocol urls created by FFmpegKit.getSafParameter methods are single-use, they can be used only once. You're using the input URL twice in your app, first in FFprobeKit.getMediaInformationAsync() and then again in FFmpegKit.executeAsync. That's the problem.

I noticed we haven't documented this behaviour properly in the docs & README. So, I mark this issue as documentation-bug. Thanks for reporting it.

@tanersener tanersener added enhancement New feature or request fixed-on-development Fixed on the development branch. Not released yet. and removed documentation-bug Documentation is missing or wrong labels Nov 10, 2021
@tanersener tanersener added fixed-in-v4.5.1 and removed fixed-on-development Fixed on the development branch. Not released yet. labels Jan 3, 2022
@tanersener
Copy link
Collaborator

In v4.5.1, we implemented saf protocol urls that can be re-used. So, it won't create problems anymore.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
android Affect Android platform enhancement New feature or request fixed-in-v4.5.1 flutter Affect flutter platform react-native Affect react-native platform saf Issue about storage access framework v4.5 Affects v4.5 release
Projects
None yet
Development

No branches or pull requests

2 participants