I have a very basic question regarding Android and ffmpeg. I obtained ffmpeg from http://bambuser.com/opensource and was able to compile it for ARM.
The results are the binaries (ffmpeg) as well as several libsomething.so files.
My question is: Is this enough to decode videos? How do I actually use ffmpeg then?
To load the library I have:
static {
System.load("/data/data/com.package/lib/libavcodec.so");
}
It loads fine. But what then?
More explanation: I saw other projects where people had their ffmpeg source in a JNI directory in the project. They also created some Android.mk files and some C code along with it. Would I need this as well? Why would I create the .so files first and then copy the ffmpeg source code again?
I know the NDK and how it should work but I've never seen an example of how one would actually call ffmpeg functions using it, because people seem to be hiding their implementations (which is sort of understandable) but not even giving useful pointers or examples.
Let's just say I wanted to decode a video file. Which kind of native methods would I need to implement? How do I run the project? Which data types need to be passed? etc. There are certainly a few people here who have at least done that, I know this from searching for hours and hours.
For your first question;
Just building is not enough for the proper use of the ffmpeg libraries. You should also wrap those so files in the right order because these so files NEED other libraries in the link time. You can display header information of the so file, by using.
objdump -x libavcodec.so | grep NEEDED
So you need to wrap these so files through Android.mk. You may check this link.
The second one;
You only need the header files from the ffmpeg project. The implementation will linked from the so libraries. Thats perhaps because, developers didn't bother to filter header files.
And the last one;
your thoughts seems right for the time being, most of the current developers are struggling to use ffmpeg but they lack of documentation and sample codes.
Related
I want to allow user to convert .mid files to .wav files in my Android app.
Actually, there is not plenty of information on the Net about any kind of midi to wav conversion, and so there is very litlle info about doing so in Android.
What should I do? Where to go?
TL;DR
Dependless on the way featured in this answer you pick, you'll have to include some c code in your project. And also you'll have to include lib lisenced under LGPL-2.1. You should really pay attention to both of these. Read this to understand it better. Really. Do read it. It IS important to understand.
Lazy option - use my lib
Better option - set FluidSynth up following either of the links (official github page guide and\or Medium article), include this snippet of code into your project and you're good to go. This code should be included into your project like it is explained in the Medium article listed above.
Very bad option - use Timidity++.
More detailed version
Not recommended option
There are two options when you convert mid files: FluidSynth and Timidity++. I wouldn't recommend you to use Timidity++ for purpose of converting .mid to raw audio. The lib is kind of old and it's not supported; docs and community are imposible to find. FluidSynth is a much better choice: it's newer, it's supported, it's gotta plenty of API docs, its community is kinda lil more alive than Timidity's is. I couldn't get Timidity working on Android.
Anyway, here are some links in case you'd like to use Timidity anyway.
somewhat usable timidity lib
example of converting mid to wav
a working app featuring timidity (I couldn't get anything going on in this code, but this app uses timidity and it's able to convert mid to wav, it's a fact)
It's not a complete list of timidity resources. Also, there are a few mysterious repos on the web that claim to be either timidity or some kind of timidity lib or even lib for android... But personally I never understood what was going on there, and so I don't recommend to go for timidity.
Lazy option
The laziest option is to use my own library. All the instructions are in the Github readme. Using my lib is not recommended way to do it, probably, since my implementation can have some big performance issues.
You can see examples of using this approach in the lib's readme.
Better option
The best option to convert .mid to .wav file is to use FluidSynth software synthesizer. This way you'll have to do some c codding. I told you.
The official github wiki got the instruction on how to set FluidSynth for Android, but I'd suggest you to read this Medium article about configuring this synthesizer instead, 'cause it's a lot more easier to follow and understand.
After you've set this thing up, you can do some neat .mid to .wav conversion. Here is the official docs for that. Gonna leave the code here in case the link goes down.
fluid_settings_t* settings;
fluid_synth_t* synth;
fluid_player_t* player;
fluid_file_renderer_t* renderer;
settings = new_fluid_settings();
// specify the file to store the audio to
// make sure you compiled fluidsynth with libsndfile to get a real wave file
// otherwise this file will only contain raw s16 stereo PCM
fluid_settings_setstr(settings, "audio.file.name", "/path/to/output.wav");
// use number of samples processed as timing source, rather than the system timer
fluid_settings_setstr(settings, "player.timing-source", "sample");
// since this is a non-realtime scenario, there is no need to pin the sample data
fluid_settings_setint(settings, "synth.lock-memory", 0);
synth = new_fluid_synth(settings);
// *** loading of a soundfont omitted ***
player = new_fluid_player(synth);
fluid_player_add(player, "/path/to/midifile.mid");
fluid_player_play(player);
renderer = new_fluid_file_renderer (synth);
while (fluid_player_get_status(player) == FLUID_PLAYER_PLAYING)
{
if (fluid_file_renderer_process_block(renderer) != FLUID_OK)
{
break;
}
}
// just for sure: stop the playback explicitly and wait until finished
fluid_player_stop(player);
fluid_player_join(player);
delete_fluid_file_renderer(renderer);
delete_fluid_player(player);
delete_fluid_synth(synth);
delete_fluid_settings(settings);
... and basically that is it. You can start converting .mid to .wav files right now.
Here is the example on how to integrate that code in your project.
Here is the example how to use this function in your android code.
I was given a task to merge an Image and Audio to make a video file out of them in android. I successfully finished the task by using javacv ffmpeg but after so much of compression my app size is still around 15mb. After analysing the apk, I've found that libavcodec.so is occupying 64% of the size. Since my app relies on that, I can't exclude the file.
So my question is "Is it feasible to complete this task with very less apk size? Like around < 5Mb?"
Yes you can. If you really want to use javacv than you can remove unnecessary parts from the sources and recompile them. More info in JavaCPP repo
As the easiest solluton of this problem you can just remove some unused .so files.
Finally, ffmpeg is not necessary here and you can find another solution. For example you can use an online service (I've found transloadit and it is free for small apps) or write your own native or java code. It is not easy but possible
I'm working on a feature in which I want to add picture over the video and save it to sd card.
in general, the user selects an image with semi-transparent background and puts that image above the video, after the user presses the save button he gets a new video but already with the image above the video.
I have heard about ffmpeg, and saw some commands that are provided by ffmpeg. but I don't know where I should initialize. can anyone provide me an example for the same?
Thank you.
One common approach is to use an ffmpeg wrapper to access ffmpeg functionality from your Android app.
There are several fairly well used wrappers available on GitHub - the ones below are particularly well featured and documented (note, I have not used these as they were not so mature when I was looking at this previously, but if I was doing something like this again now I would definitely build on one of these):
http://writingminds.github.io/ffmpeg-android-java/
https://github.com/guardianproject/android-ffmpeg
Using one of the well supported and used libraries will take care of some common issues that you might otherwise encounter - having to load different binaries for different processor types, and some tricky issues with native library reloading to avoid crashes on subsequent invocations of the wrapper.
Because this approach uses the standard ffmpeg cmd line syntax for commands it also means you should be able to search and find help easily on multiple different operations (as anyone using ffmpeg in 'normal' model will use the same syntax for the ffmpeg command itself).
For example, for your adding an image case here are some results from a quick search (ffmpeg syntax can change over time so it is worth doing a current check):
https://stackoverflow.com/a/32250369/334402
https://superuser.com/a/678171
I have a video(.mp4) file in my SDCard,I want to reduce a size of .mp4 file and upload this file to a server.
One way you can do this is to use ffmpeg.
There are several ways of using ffmpeg in an Android program:
use the native libraries directly from c using JNI
use a library which provides a wrapper around the 'ffmpeg' cmd line utility (also uses JNI in the wrapper library)
call ffmpeg cmd line via 'exec' from within you Android app
Of the three, I personally have used the wrapper approach in the past and found it worked well. IMHO, the documentation and examples available with the native libraries represented quite a steep learning curve.
Note, if you do use 'exec' there are some things it is worth being aware of - see bottom of this answer: https://stackoverflow.com/a/25002844/334402.
The wrapper does have limitations - at heart, the ffmpeg cmd line tool is not intended to be used this way and you have to keep that in mind, but it does work. There is an example project available on github which seems to have a reasonable user base - I did not use it myself but I did refer to it and found it useful, especially for an issue you will find if you need to call your ffmpeg wrapper more than once from the same activity or task:
https://github.com/jhotovy/android-ffmpeg
See this answer (and the questions and answers it is part if) for some more specifics on the 'calling ffmpeg two times' solution:
https://stackoverflow.com/a/28752190/334402
We need an Android app that can encode a folder of images to a video. I have been looking for solutions a while now, but cannot find anything good. The Android API does not support it. We are trying ffmpeg, but cannot get it to work. We need a working solution, using ffmpeg is not mandatory. A full Android Java solution is also a possibility, since this would work on all Android devices, possibly at the cost of some performance.
The app also needs to be able to add an audio track to the movie if the user chooses to do this.
Any help would be appreciated.
Kind regards,
AƤron
From the FFmpeg FAQ entry "How do I encode single pictures into movies?":
First, rename your pictures to follow a numerical sequence. For example, img1.jpg, img2.jpg, img3.jpg,... Then you may run:
ffmpeg -f image2 -i img%d.jpg /tmp/a.mpg
Adding an audio track should just involve add another input (e.g., -i audio.mp3), but could also require explicit -maping with older versions.