我已经设法使用NDK版本r5c为Android NDK编译halfninja ffmpeg scripts。 (不幸的是,任何使用早期NDK编译的尝试都会产生一些错误),而且我对整个NDK过程都不是很了解,所以对我来说这有点让人失望。
他的脚本正在编译ffmpeg版本N-30996-gf925b24(他为脚本执行的具体提交)
继续我的实际应用。
我设法修剪视频没有问题,现在我需要加入/连接它们,但任何尝试使用在这3个链接上找到的命令的任意和几种组合(link1,link2,{{3} })生成错误,例如cat is not valid
,> is undefinined
,unknown option filter_complex
或尝试覆盖某些输入文件。
有没有人知道是否有可能和(怎么做),加入/连接mp4视频(所有相同的编解码器,大小,质量等)使用Android上的半连队编译ffmpeg,或者如何编译/获取使用最新源代码的Android版ffmpeg?
我也快速尝试link3但没有取得多大成功。
最终我试图让这个伪方法起作用:
public static File concatenate(String[] inputPaths, String outputPath){
// ... do stuff do generate ffmpeg commands....
VideoKit v = new VideoKit();
v.run(cmds);
File f = new File(outputPath);
return f;
}
答案 0 :(得分:4)
LordNeckbeard提供的答案真的是要走的路。
How to concatenate flv file into one?
使用您的限制
-f concat
-c
-bsf
ffmpeg -i q.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb q.ts
ffmpeg -i r.mp4 -vcodec copy -acodec copy -vbsf h264_mp4toannexb r.ts
ffmpeg -i 'concat:q.ts|r.ts' -vcodec copy -acodec copy -absf aac_adtstoasc qr.mp4
答案 1 :(得分:2)
这个序列将在CLI上播放mp4。它来自串联的ffmpeg faq页面......
$FFMPEG_HOME/ffmpeg -i gpsclip_seg1.mp4 -vn -f u16le -acodec pcm_s16le -ac 1 -ar 44100 - > temp1.a < /dev/null
$FFMPEG_HOME/ffmpeg -i gpsclip_seg2.mp4 -vn -f u16le -acodec pcm_s16le -ac 1 -ar 44100 - > temp2.a < /dev/null
$FFMPEG_HOME/ffmpeg -i gpsclip_seg3.mp4 -vn -f u16le -acodec pcm_s16le -ac 1 -ar 44100 - > temp3.a < /dev/null
cat temp1.a temp2.a temp3.a > all.a
$FFMPEG_HOME/ffmpeg -i gpsclip_seg1.mp4 -an -f yuv4mpegpipe - > temp1.v < /dev/null &
$FFMPEG_HOME/ffmpeg -i gpsclip_seg2.mp4 -an -f yuv4mpegpipe - < /dev/null | tail -n +2 > temp2.v
$FFMPEG_HOME/ffmpeg -i gpsclip_seg3.mp4 -an -f yuv4mpegpipe - < /dev/null | tail -n +2 > temp3.v
cat temp1.v temp2.v temp3.v > all.v
$FFMPEG_HOME/ffmpeg -f u16le -acodec pcm_s16le -ac 1 -ar 44100 -i all.a -f yuv4mpegpipe -i all.v -same_quant -y output.mp4
我查看了halfninja的'Android.mk'...并且为了测试,您应该能够使用adb将'ffmpeg'可执行文件从halfninja build推送到/ data / local / ...在手机上。在构建项目时,我认为可执行文件将位于../output文件夹中,位于项目中的JNI文件夹上方。
假设您可以在设备上获得root权限,然后可以通过获取shell在手机上的CLI界面上进行测试,然后使用“su”获取root权限,然后从ffmpeg / MP4 / concat线程复制cli表达式,例如这个one并在手机上运行它们,输出到您有权访问的文件夹。
在测试模式下,如果您可以在链接接受的答案中显示的CLI调用时使用步骤获得所需的结果,则可以返回到JNI接口,调用halfninja的'videokit'包,实现相同的您在测试中使用的命令序列。
添加了多个电话的注释......
由于您将多次调用JNI中的ffmpeg lib,因此您应该知道这可能会影响通过JNI多次调用ffmpeg的issue。如果halfninja尚未完成调解此问题,您可能必须更改Android.mk结构以实现在线程中讨论的包装器库,以便您可以通过JNI在每次调用ffmpeg之间加载/卸载所需的共享库。
android和'cat'
你应该在手机的/ system / bin中有一个符号链接
lrwxr-xr-x root shell 2012-07-09 13:02 cat -> toolbox
如果没有,请尝试在手机上安装'busybox',这样您就可以在手机上模拟cli脚本。
答案 2 :(得分:1)
ffmpeg concat demuxer已被添加到FFMPEG Fire Flower(1.1版)中。使用FFmpeg fire flower或Magic来获得此功能。构建ffmpeg后,请使用分路器。这在http://ffmpeg.org/trac/ffmpeg/wiki/How%20to%20concatenate%20(join,%20merge)%20media%20files中有解释 网站作为concat demuxer。
答案 3 :(得分:1)
由于FFneja的halfninja版本无法使用连接功能,我建议您将FFmpeg库更新到至少1.1版。
在我看来,你有两个选择:
尝试使用这两个Compiling FFmpeg on Android指南之一编译较新版本的FFmpeg。那么您可能还需要更新的Android NDK版本。这是最简单的解决方案。
或者尝试在halfninja库中实现更新版本的FFmpeg,这样更难,但是你可以保持几乎相同的界面。
答案 4 :(得分:0)
你好,我有这种灵魂。我使用Mp4parser库
public class Mp4ParserWrapper {
public static final String TAG = Mp4ParserWrapper.class.getSimpleName();
public static final int FILE_BUFFER_SIZE = 1024;
/**
* Appends mp4 audio/video from {@code anotherFileName} to {@code mainFileName}.
*/
public static boolean append(String mainFileName, String anotherFileName) {
boolean rvalue = false;
try {
File targetFile = new File(mainFileName);
File anotherFile = new File(anotherFileName);
if (targetFile.exists() && targetFile.length()>0) {
String tmpFileName = mainFileName + ".tmp";
//mainfile=vishal0
//another file=vishal1
//tmpfile=vishal0.tmp
append(mainFileName, anotherFileName, tmpFileName);
copyFile(tmpFileName, mainFileName);
anotherFile.delete();
new File(tmpFileName).delete();
rvalue = true;
} else if ( targetFile.createNewFile() ) {
copyFile(anotherFileName, mainFileName);
anotherFile.delete();
rvalue = true;
}
} catch (IOException e) {
Log.e(TAG, "Append two mp4 files exception", e);
}
return rvalue;
}
public static void copyFile(final String from, final String destination)
throws IOException {
FileInputStream in = new FileInputStream(from);
FileOutputStream out = new FileOutputStream(destination);
copy(in, out);
in.close();
out.close();
}
public static void copy(FileInputStream in, FileOutputStream out) throws IOException {
byte[] buf = new byte[FILE_BUFFER_SIZE];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
}
public static void append(
final String firstFile,
final String secondFile,
final String newFile) throws IOException {
final FileInputStream fisOne = new FileInputStream(new File(secondFile));
final FileInputStream fisTwo = new FileInputStream(new File(firstFile));
final FileOutputStream fos = new FileOutputStream(new File(String.format(newFile)));
append(fisOne, fisTwo, fos);
fisOne.close();
fisTwo.close();
fos.close();
}
// FIXME remove deprecated code
public static void append(
final FileInputStream fisOne,
final FileInputStream fisTwo,
final FileOutputStream out) throws IOException {
final Movie movieOne = MovieCreator.build(Channels.newChannel(fisOne));
final Movie movieTwo = MovieCreator.build(Channels.newChannel(fisTwo));
final Movie finalMovie = new Movie();
final List<Track> movieOneTracks = movieOne.getTracks();
final List<Track> movieTwoTracks = movieTwo.getTracks();
for (int i = 0; i <movieOneTracks.size() || i < movieTwoTracks.size(); ++i) {
finalMovie.addTrack(new AppendTrack(movieTwoTracks.get(i), movieOneTracks.get(i)));
}
final IsoFile isoFile = new DefaultMp4Builder().build(finalMovie);
isoFile.getBox(out.getChannel());
}
}
并调用:
Mp4ParserWrapper.append(firstfilename,secondfilename);