This question already has answers here:
How to concatenate two MP4 files using FFmpeg?
(29 answers)
Closed 4 years ago.
I have a couple of M4A (sound) files. I want to combine into a single sound file. Can this using ffmpeg library in android.
I tried this way.
public void myFunctionMergeAudioFiles(ShellCallback sc,List<String> mListFiles, String outPath) throws IOException, InterruptedException
{
ArrayList<String> cmd = new ArrayList<String>();
cmd = new ArrayList<String>();
cmd.add(ffmpegBin);
cmd.add("f");
cmd.add("concat");
cmd.add("-i");
for(int i=0;i<mListFiles.size();i++){
cmd.add(new File(mListFiles.get(i)).getCanonicalPath());
}
cmd.add("-c");
cmd.add("-acodec");
cmd.add("aac");
cmd.add("copy");
File fileOut = new File(outPath);
cmd.add(fileOut.getCanonicalPath());
execFFMPEG(cmd, sc);
}
My Log:-
01-23 15:32:17.841: D/FFMPEG(12678): /data/app-lib/com.apps.messagingapp-1/libffmpeg.so f concat -i /storage/emulated/0/MGOApp/Temp/Recording #1_0.m4a /storage/emulated/0/MGOApp/Temp/Recording #1_1.m4a /storage/emulated/0/MGOApp/Temp/Recording #1_2.m4a -c -acodec aac copy /storage/emulated/0/MGOApp/Recording #1.m4a
But i am not getting any error.
Thanks in advance.
I believe you've got to create a text file and use it as your input. The text file needs to look like this:
file 'file1.m4a'
file 'file2.m4a'
Then run the following command line should be like:
ffmpeg -f concat -i "Path\To\MyList.txt" -c copy concatOutput.m4a
That works for me.
You should be able to create the list text file on the fly in your code and delete it after you've run your FFMPEG command line.
More info on this guide
Related
I need to merge (concatenate) two audio files in a Flutter app.
I am trying to use Flutter_ffmpeg package .
https://pub.dev/packages/flutter_ffmpeg
Ffmpeg is powerful tool for audio and video.
flutter_cache_manager package to store the files that came from https
https://pub.dev/packages/flutter_cache_manager
And path provided to deal with the paths
https://pub.dev/packages/path_provider
For the part of caching I already made some successful tests,
But, I need your help to understand how can I use ffmpeg package.
According to the readme I need to do something like
import 'package:flutter_ffmpeg/flutter_ffmpeg.dart';
final FlutterFFmpeg _flutterFFmpeg = new FlutterFFmpeg();
var fileCached1 = await DefaultCacheManager().getSingleFile(url1);
var fileCached2 = await DefaultCacheManager().getSingleFile(url2);
var arguments = ["-i", "concat:fileCached1.wav|fileCached2.wav", "-c copy", "output.way"];
_flutterFFmpeg.executeWithArguments(arguments ).then((rc) => print("FFmpeg process exited with rc $rc"));
How can I have access to the output.wav to play? How can I use the path_provider?
I really need you help. :)
There is little information about flutter_ffmpeg. This question might be useful for someone else to.
Thanks in advance,
Ricardo
The path_provider package let you to access appDir & temp directory of your application, let say that you want to access the application documents directory :
Directory appDocumentDir = await getApplicationDocumentsDirectory();
String rawDocumentPath = appDocumentDir.path;
and if your output's file name is "output.wav"
String outputPath = Strings.concatAll([rawDocumentPath, "/output.wav"]);
now outputPath contain the path to output file that will be generated by FFMPEG and you can use it later when you want to play/copy/upload or whatever you want to.
but in the FFMPEG part, the command line for concat two input file is:
ffmpeg -i input1.wav -i input2.wav -filter_complex '[0:0][1:0]concat=n=2:v=0:a=1[out]' -map '[out]' output.wav
If you want to have 3 input files, use n=3 and change the other parts in command.
usage of Flutter_ffmpeg will be something like this:
import 'package:flutter_ffmpeg/flutter_ffmpeg.dart';
final FlutterFFmpeg _flutterFFmpeg = new FlutterFFmpeg();
_flutterFFmpeg.execute("-i input1.wav -i input2.wav -filter_complex '[0:0][1:0]concat=n=2:v=0:a=1[out]' -map '[out]' output.wav").then((rc) => print("FFmpeg process exited with rc $rc"));
ideally we want to use outputPath here so do something like this :
String commandToExecute = Strings.concatAll(["-i input1.wav -i input2.wav -filter_complex '[0:0][1:0]concat=n=2:v=0:a=1[out]' -map '[out]' ", outputPath]);
and your final statement for executing the process will be :
_flutterFFmpeg.execute(commandToExecute).then((rc) => print("FFmpeg process exited with rc $rc"));
after execution you can check execution output. Zero represents successful execution, non-zero values represent failure :
final FlutterFFmpegConfig _flutterFFmpegConfig = new FlutterFFmpegConfig();
_flutterFFmpegConfig.getLastReturnCode().then((rc) => print("Last rc: $rc"));
_flutterFFmpegConfig.getLastCommandOutput().then((output) => print("Last command output: $output"));
so in case of failure or getting error, you can check the command output for fixing bugs
you can find more information about flutter_ffmpeg in here :
https://pub.dev/packages/flutter_ffmpeg
also for using ffmpeg and find more about filters you can check this out :
https://ffmpeg.org/ffmpeg-filters.html
First get the directory
final appDirectory = await getExternalStorageDirectory();
Then in the execute commands append the output file with directory.
_flutterFFmpeg.execute("-i $videoURL -i $audioURL -c copy ${appDirectory?.path}/output.mp4");
I guess command is not working properly here.
I am using this project
-y -i /storage/emulated/0/DCIM/Camera/VID_20190623_153948.mp4 -vf "drawtext=fontfile=/usr/share/fonts/truetype/DejaVuSans.ttf: text='Stack' " /storage/emulated/0/DCIM/Camera/output2.mp4
The result expected is the video which I am giving as input should be processed and it should contain text Stack in it
drawText's fontfile should have an absolute path of the font file. Your command says the font file's path is /usr/share/fonts/truetype/DejaVuSans.ttf, I believe that's not the case as you running from android. It should be some file from android storage.
Example:
drawtext=fontfile=/storage/emulated/0/fonts/truetype/DejaVuSans.ttf
if DejaVuSans.ttf file is under /storage/emulated/0/fonts/truetype/ directory in your android device.
I am using ffmpeg to cut video via android, all working fine but only issue come when if the source directory contain space the command is not working by saying file not found
-i /storage/emulated/0/ISave Videos/Br0gv9anKKg.mp4 -acodec copy -vcodec copy -ss 00:00:10 -t 00:00:20 /storage/emulated/0/1547813275685ChunkClip.mp4
file not found is Like"File not found -i /storage/emulated/0/ISave"
But for other path no issue and all works fine only if space is there in file path the issue comes
Cool Question
Its very confusing to solve there type of issues even if we get a solution
The following Link show some fix for handling issues like this
Quoting and escaping
So for the issue you have there is fix Add each word in ffmpeg comments to an LinkedList and then convert to command array so that ffmpeg will execute it
As follows (As per you requirement command)
List<String> cmdList = new LinkedList<>();
cmdList.add("-i");
cmdList.add("/storage/emulated/0/ISave Videos/Br0gv9anKKg.mp4");
cmdList.add("-acodec");
cmdList.add("copy");
cmdList.add("-vcodec");
cmdList.add("copy");
cmdList.add("-ss");
cmdList.add("00:00:10");
cmdList.add("-t");
cmdList.add("00:00:20");
cmdList.add("/storage/emulated/0/1547813275685ChunkClip.mp4");
String[] command = cmdList.toArray(new String[cmdList.size()]);
Hope your issue will be get resolved by this solution
I go though many site and search regarding "FFMPEG" implementation for android project.
Most solution founded are using NDK.
but i want to use FFmpeg without using NDK as i found in This Link
I have used this project
https://github.com/guardianproject/android-ffmpeg-java
It has already compiled for android version of FFMPEG library and this file will be in res/raw folder (you can update this file if you need newer version). You need to add this project as a library to your's. And after thst you can write your own function in java for example like this:
public Clip convert (Clip mediaIn, String outPath, ShellCallback sc) throws Exception
{
ArrayList<String> cmd = new ArrayList<String>();
cmd.add(mFfmpegBin);
cmd.add("-y");
cmd.add("-i");
cmd.add(new File(mediaIn.path).getCanonicalPath());
if (mediaIn.startTime != null)
{
cmd.add("-ss");
cmd.add(mediaIn.startTime);
}
if (mediaIn.duration != -1)
{
cmd.add("-t");
cmd.add(String.format(Locale.US,"%f",mediaIn.duration));
}
Clip mediaOut = new Clip();
File fileOut = new File(outPath);
mediaOut.path = fileOut.getCanonicalPath();
cmd.add(mediaOut.path);
execFFMPEG(cmd, sc);
return mediaOut;
}
and execute it using FfmpegController Object.
Please notice me if you have any questions or if this is what you want.
EDIT:
I hope you connect this github code as a library for your project.
There is FfmpegController.java class in src folder. It's a wrapper for using command line ffmpeg exe file. If you want for example execute command like this one
ffmpeg -i source.wav -b:a 128k output.mp3
you need to add function to FfmpegController.java class. Something like this:
public Clip convert(Clip mediaIn, String outPath, ShellCallback sc) throws Exception
{
ArrayList<String> cmd = new ArrayList<String>();
Clip mediaOut = new Clip();
String mediaPath = mediaIn.path;
cmd = new ArrayList<String>();
cmd.add(mFfmpegBin);
cmd.add("-i");
cmd.add(mediaPath);
cmd.add("-b:a");
cmd.add("128k");
mediaOut.path = outPath;
cmd.add(mediaOut.path);
execFFMPEG(cmd, sc);
return mediaOut; // this is not importatnt because file will be put in outPath
}
Now in your project initialize FfmpegController object and run your function.
I have used this FFmpeg sample which is library that used without NDK
First of download sample example FFmpeg Sample
Download FFmpeg library FFmpeg Library
Extract both in one folder and import project from Android Studio
Now, Calling FFmpeg command
This command is for rotate (/sdcard/videokit/in.mp4) video in 90 Angle and generate out.mp4 in specific location in SD card
ffmpeg -y -i /sdcard/videokit/in.mp4 -strict experimental -vf transpose=1 -s 160x120 -r 30 -aspect 4:3 -ab 48000 -ac 2 -ar 22050 -b 2097k /sdcard/videokit/out.mp4
Now run this command with predefined method in library and add listeners of GeneralUtils
GeneralUtils.copyLicenseFromAssetsToSDIfNeeded(this, workFolder);
GeneralUtils.copyDemoVideoFromAssetsToSDIfNeeded(this, demoVideoFolder);
//demoVideoFolder where your Input file path
//workFolder Absolute path
// workFolder = getApplicationContext().getFilesDir().getAbsolutePath() + "/";
LoadJNI vk = new LoadJNI();
try {
vk.run(GeneralUtils.utilConvertToComplex(commandStr), workFolder, getApplicationContext());
// copying vk.log (internal native log) to the videokit folder
GeneralUtils.copyFileToFolder(vkLogPath, demoVideoFolder);
} catch (Throwable e) {
Log.e(Prefs.TAG, "vk run exeption.", e);
}
Run this and check in File Manager for Output . I hope it works Good :) Enjoy
First, im a beginner in FFMPEG so please bear with me.
Im using this library and successfully combined an audio and a video :D
However, i keep failing when i tried to insert an image/watermark over a video.
This is the code im using :
public MediaDesc combineVideoAndImage (MediaDesc videoIn, MediaDesc image, MediaDesc out, ShellCallback sc) throws Exception
{
ArrayList<String> cmd = new ArrayList<String>();
cmd.add(ffmpegBin);
cmd.add("-i");
cmd.add(new File(videoIn.path).getCanonicalPath());
cmd.add("-vf");
cmd.add("movie=" + new File(image.path).getAbsolutePath() + " [logo];[in][logo] overlay=10:10 [out]");
cmd.add("-strict");
cmd.add("-2");
File fileOut = new File(out.path);
cmd.add(fileOut.getCanonicalPath());
execFFMPEG(cmd, sc);
return out;
}
Those code will generate this cmd :
ffmpeg -i VIDEONAME.mp4 -vf "movie=LOGONAME.png [logo];[in][logo] overlay=10:10 [out]"
-strict -2 OUTPUTNAME.MP4
I have tested this CMD on ubuntu 13.10 64bit, with latest FFMPEG installed and t succeed.
But it does not in my android project. It does not catch/throw any error/exception, the program running normally and the file is created but has nothing in it (0 byte)
Any help is appreciated. Thanks for your help :D
Try with following command
ffmpeg -i input.mp4 -i watermark.png -filter_complex "overlay=10:10" -codec:a copy output.mp4
i have tested it on android and it is working perfect.