hamoid / video_export_processing

Processing library that interfaces with ffmpeg to export video files
http://funprogramming.org/VideoExport-for-Processing/
GNU General Public License v2.0
116 stars 19 forks source link

Include FFmpeg in exported application? #67

Open philipp-lehmann opened 3 years ago

philipp-lehmann commented 3 years ago

Hey there

Thanks for the effort putting together this awesome library. I ran into troubles when exporting a standalone application from processing.

Can you include FFmpeg into the export, so that you don't have to install it separately when distributing the app? I see that you can change the location, would it be possible to install ffmpeg within the data folder and point to this location? Do you have other ideas?

Best Philipp

hamoid commented 3 years ago

Oh good point! Gee... I never considered exporting the application.

The library looks for its config file inside the Processing libraries folder, under VideoExport/settings.json That file contains the path to ffmpeg. But I have no idea currently what happens with an exported app. I guess it still searches for that same file? Can you look if there is such a file in your exported app which you could edit?

hamoid commented 3 years ago

I see that after running the exported application once, a settings file is created in the same folder. You could try to put ffmpeg in a subfolder and then edit that settings.json file to point to it. A relative path might work.

philipp-lehmann commented 3 years ago

Yes, I had the same idea, but couldn't fully test it yet. Here's what i have observed so far with exported applications:

Win 10 The dialog pops up and asks for the file to be located, then the program runs correctly. I'm not sure if this is also the case if the Environmental Variables (https://timrodenbroeker.de/processing-tutorial-video-export) haven't been set up correctly.

Mac OS If FFmpeg is installed in the default directory, everything works as expected. If not the application crashes. No dialogue.

I'll let you know if the relative paths work.

hamoid commented 3 years ago

I hope that by setting the path in settings.json the Environmental Variables are not needed.

Yes let me know how it goes. If it does I could add it to the readme :)

philipp-lehmann commented 3 years ago

Hey there

Windows Works with relative paths, even without the Environmental Variables.

philipp-lehmann commented 3 years ago

MacOS

I think i have found a way. You can include the binaries in the exported app. But the path in the settings.json has to be absolute, relative never worked for me.

Since the path changes when you move the App (or a different person installs it), I update the settings file when launching the App. Therefore I made a Settings.pde file with these functions.

void updateSettings() {
    String AppName = "App";
    String ffmpegPath = sketchPath(AppName + ".app/Contents/bin/ffmpeg");
    JSONObject json = loadJSONObject("settings.json");
    json.setString("ffmpeg_path", ffmpegPath);
    saveJSONObject(json, AppName + ".app/Contents/settings.json");
}

public String sketchPath(String where) {
    if (sketchPath() == null) {
        return where;
    }
    try {
        if (new File(where).isAbsolute()) return where;
    } catch (Exception e) {}
    return sketchPath() + File.separator + where;
}
Bildschirmfoto 2021-05-11 um 15 24 58
philipp-lehmann commented 3 years ago

The updateSettings function could definitely be nicer and the appname is hardcoded at the moment. But it works!

philipp-lehmann commented 3 years ago

And when testing the sketch it creates a folder 'App.app/Contents' - not so nice.

gritschu commented 3 years ago

I am happy to find that I am not the only person who needs this. @philipp-lehmann thanks for your solution for Mac. However this doesn't seem to work for me. I am not sure why yet. The creation of the absolute path seems to work fine, but I think for me the call loadJSONObject("settings.json") seems to fail, thus I am not able to change the content of the json file via code at the moment. The folder structure is the same as in your screenshot if I don't miss something. Does someone have any idea? Thank you!

gritschu commented 3 years ago

I have hacked around my problem (in a messy way) and I am now able to change the absolute ffmpeg path in my settings.json file via code as described above. However if I move my app to another folder / another computer and update the absolute path in the settings.json via my function accordingly, the path inside the file looks correct, but the dialogue window pops up anyway before the movie export starts to choose the ffmpeg location. My big problem is now that on newer Mac OS systems the dialogue window will not pop up and the application will freeze, because Apple somehow prevents the dialogue to show up at all (some application access restrictions). I know this is rather a Mac OS issue than specifically relatd to this, but I wonder why the dialogue pops up at all even though the path is correctly set inside the json file. Any ideas?

philipp-lehmann commented 3 years ago

Hey there

Clarifying on my earlier answer: There are two settings.json files. One is in the Data folder. On start I get the contents of this file as JSON, update the current app path, and the save it directly as a separate file into the App Folder.

void updateSettings() {
    updateAppPath();
    updateTargetPath();
}

// App path and ffmpeg location
void updateAppPath() {
    JSONObject ffmpgJSON = loadJSONObject("settings.json");
    String ffmpegPath = sketchPath(AppName + ".app/Contents/bin/ffmpeg");
    ffmpgJSON.setString("ffmpeg_path", ffmpegPath);
    saveJSONObject(ffmpgJSON, AppName + ".app/Contents/settings.json");
}

public String sketchPath(String where) {
    if (sketchPath() == null) {
        return where;
    }
    try {
        if (new File(where).isAbsolute()) return where;
    } catch (Exception e) {}
    return sketchPath() + File.separator + where;
}

// Target folder
void updateTargetPath() {
    JSONObject targetJSON = loadJSONObject("target.json");
    println("Target: " + targetJSON.getString("target_folder"));
    targetFolder = targetJSON.getString("target_folder");
}

void setTargetFolder() {
    selectFolder("Select a folder to write to:", "folderSelected");
}

void folderSelected(File selection) {
    if (selection == null) {
        println("No folder selected...");
    } else {
        // Apply target folder variable
        targetFolder = selection.getAbsolutePath() + "/";
        println("Target: " + targetFolder);

        // Create and save new target json
        JSONObject targetJSON = new JSONObject();
        targetJSON.setString("target_folder", targetFolder);
        targetJSON.setString("Test", "testvalue");
        saveJSONObject(targetJSON,  AppName + ".app/Contents/Java/data/target.json");
    }
}
philipp-lehmann commented 3 years ago

I remember I also had the Issue, that the dialogue was hidden. And as you can see my current version is different, so I probably adressed this.

gritschu commented 3 years ago

@philipp-lehmann thank you so much! I understand everything concerning the settings.json now.

However, I don't see a crucial difference in your current version from the one before which shall prevent the reappearing popup asking for selection of the ffmpeg path even though it has been updated inside the settings.json file.

The additional parts about the target path using the target.json has nothing to do with the issue, or does it? If so, I don't understand where the original target.json file is coming from.

gritschu commented 3 years ago

Further observation: If I change the path in the json file manually (open in editor, change, save) I don't have the problem. I also don't have the problem, when I change the path in the json via code, then close my app, then reopen and export the movie. The popup doesn't appear anymore and everything is fine. Only if I change the path via saveJSONObject(ffmpgJSON, AppName + ".app/Contents/settings.json"); and then try to export immediately after the popup opens again (which I want to prevent).

philipp-lehmann commented 3 years ago

Yes, the target.json is a directory where I export the movies to. This is not related to the ffmpeg import.