嘿stackoverflow ers,
我需要使用FFmpeg将视频和一些照片组合起来制作视频.
我已经设法在我的系统上编译FFmpeg并静态链接它.
现在我正在寻找利用ffmpeg来完成Android任务的包装/图书馆.
我尝试过的:
> Guardian项目代码,Awesome API,简单而且很好,但是当运行createSlIDeshowFromImagesAndAudio时,我得到了一个很好的返回代码,但是我的设备上永远不会创建该文件(如果您有使用此代码的经验,我得到的返回代码是11).
> JCodec,慢慢地说.
> FMJ,不支持我要求的功能.
所以问题仍然存在,AndroID的FFmpeg包装有什么好处?最佳答案这是FFMPEG的Wrapper完美运行:你必须按照这些步骤为androID制作FFMPEG Wrapper.你需要创建几个classess,如下所示:
ShellUtils.java
package com.example.processvIDeo;public class ShellUtils { //varIoUs console cmds public final static String SHELL_CMD_CHMOD = "chmod"; public final static String SHELL_CMD_KILL = "kill -9"; public final static String SHELL_CMD_RM = "rm"; public final static String SHELL_CMD_PS = "ps"; public final static String SHELL_CMD_PIDOF = "pIDof"; public final static String CHMOD_EXE_VALUE = "700"; public static boolean isRootPossible() { StringBuilder log = new StringBuilder(); try { // Check if Superuser.apk exists file fileSU = new file("/system/app/Superuser.apk"); if (fileSU.exists()) return true; fileSU = new file("/system/bin/su"); if (fileSU.exists()) return true; //Check for 'su' binary String[] cmd = {"which su"}; int exitCode = ShellUtils.doShellCommand(cmd,new ShellCallback () { @OverrIDe public voID shellOut(char[] msg) { //System.out.print(msg); } },false,true); if (exitCode == 0) { logMessage("Can acquire root permissions"); return true; } } catch (IOException e) { //this means that there is no root to be had (normally) so we won't log anything logException("Error checking for root access",e); } catch (Exception e) { logException("Error checking for root access",e); //this means that there is no root to be had (normally) } logMessage("Could not acquire root permissions"); return false; } public static int findProcessID(String command) { int procID = -1; try { procID = findProcessIDWithPIDOf(command); if (procID == -1) procID = findProcessIDWithPS(command); } catch (Exception e) { try { procID = findProcessIDWithPS(command); } catch (Exception e2) { logException("Unable to get proc ID for: " + command,e2); } } return procID; } //use 'pIDof' command public static int findProcessIDWithPIDOf(String command) throws Exception { int procID = -1; Runtime r = Runtime.getRuntime(); Process procps = null; String basename = new file(command).getname(); //fix contributed my mikos on 2010.12.10 procps = r.exec(new String[] {SHELL_CMD_PIDOF,basename}); //procps = r.exec(SHELL_CMD_PIDOF); BufferedReader reader = new BufferedReader(new inputStreamReader(procps.getinputStream())); String line = null; while ((line = reader.readline())!=null) { try { //this line should just be the process ID procID = Integer.parseInt(line.trim()); break; } catch (NumberFormatException e) { logException("unable to parse process pID: " + line,e); } } return procID; } //use 'ps' command public static int findProcessIDWithPS(String command) throws Exception { int procID = -1; Runtime r = Runtime.getRuntime(); Process procps = null; procps = r.exec(SHELL_CMD_PS); BufferedReader reader = new BufferedReader(new inputStreamReader(procps.getinputStream())); String line = null; while ((line = reader.readline())!=null) { if (line.indexOf(' ' + command)!=-1) { StringTokenizer st = new StringTokenizer(line," "); st.nextToken(); //proc owner procID = Integer.parseInt(st.nextToken().trim()); break; } } return procID; } public static int doShellCommand(String[] cmds,ShellCallback sc,boolean runAsRoot,boolean waitFor) throws Exception { Process proc = null; int exitCode = -1; if (runAsRoot) proc = Runtime.getRuntime().exec("su"); else proc = Runtime.getRuntime().exec("sh"); OutputStreamWriter out = new OutputStreamWriter(proc.getoutputStream()); for (int i = 0; i < cmds.length; i++) { logMessage("executing shell cmd: " + cmds[i] + "; runAsRoot=" + runAsRoot + ";waitFor=" + waitFor); out.write(cmds[i]); out.write("\n"); } out.flush(); out.write("exit\n"); out.flush(); if (waitFor) { final char buf[] = new char[20]; // Consume the "stdout" inputStreamReader reader = new inputStreamReader(proc.getinputStream()); int read=0; while ((read=reader.read(buf)) != -1) { if (sc != null) sc.shellOut(buf); } // Consume the "stderr" reader = new inputStreamReader(proc.getErrorStream()); read=0; while ((read=reader.read(buf)) != -1) { if (sc != null) sc.shellOut(buf); } exitCode = proc.waitFor(); } return exitCode; } public static voID logMessage (String msg) { } public static voID logException (String msg,Exception e) { } public interface ShellCallback { public voID shellOut (char[] msg); }}
RegionTrail.java
公共类RegionTrail {
private HashMap
ObscureRegion.java
public class ObscureRegion { /* * Thinking about whether or not a region should contain multiple start/end times * realizing that doing this would make editing a real pita * Of course,it would make displaying be a 1000x better though. class positionTime { int sx = 0; int sy = 0; int ex = 0; int ey = 0; int startTime = 0; int endTime = 0; positionTime(int _sx,int _sy,int _ex,int _ey,int _startTime,int _endTime) { } } */ public static final float DEFAulT_X_SIZE = 150; public static final float DEFAulT_Y_SIZE = 150; public float sx = 0; public float sy = 0; public float ex = 0; public float ey = 0; public int timeStamp = 0; public RegionTrail regionTrail; private RectF rectF; public ObscureRegion(int _timeStamp,float _sx,float _sy,float _ex,float _ey) { timeStamp = _timeStamp; sx = _sx; sy = _sy; ex = _ex; ey = _ey; if (sx < 0) { sx = 0; } else if (sy < 0) { sy = 0; } } public ObscureRegion(int _startTime,float _sy) { this(_startTime,_sx - DEFAulT_X_SIZE/2,_sy - DEFAulT_Y_SIZE/2,_sx + DEFAulT_X_SIZE/2,_sy + DEFAulT_Y_SIZE/2); } public voID moveRegion(float _sx,float _sy) { moveRegion(_sx - DEFAulT_X_SIZE/2,_sy + DEFAulT_Y_SIZE/2); } public voID moveRegion(float _sx,float _ey) { sx = _sx; sy = _sy; ex = _ex; ey = _ey; rectF = null; } public RectF getRectF() { if (rectF == null) rectF = new RectF(sx,ey); return rectF; } public RectF getBounds() { return getRectF(); } public String getStringData(float wIDthMod,float heightmod,int startTime,int duration,String currentMode) { //left,right,top,bottom return "" + (float)startTime/(float)1000 + ',' + (float)(startTime+duration)/(float)1000 + ',' + (int)(sx*wIDthMod) + ',' + (int)(ex*wIDthMod) + ',' + (int)(sy*heightmod) + ',' + (int)(ey*heightmod) + ',' + currentMode; } public RegionTrail getRegionTrail() { return regionTrail; } public voID setRegionTrail(RegionTrail regionTrail) { this.regionTrail = regionTrail; }}
FFMPEGWrapper.java
public class FFMPEGWrapper { String[] libraryAssets = {"ffmpeg"}; public file fileBinDir; Context context; private final static String FFMPEG_BINARY_VERSION = "0.10.4.1"; private final static String FFMPEG_VERSION_KEY = "ffmpegkey"; public FFMPEGWrapper(Context _context) throws fileNotFoundException,IOException { context = _context; fileBinDir = context.getDir("bin",0); checkBinary(); } private voID checkBinary () throws fileNotFoundException,IOException { SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); String currTorBinary = prefs.getString(FFMPEG_VERSION_KEY,null); if ((currTorBinary == null || (!currTorBinary.equals(FFMPEG_BINARY_VERSION))) || !new file(fileBinDir,libraryAssets[0]).exists()) { BinaryInstaller bi = new BinaryInstaller(context,fileBinDir); bi.installFromraw(); } } public voID execProcess( String[] cmds,ShellCallback sc) throws Exception { ProcessBuilder pb = new ProcessBuilder(cmds); pb.redirectErrorStream(true); Process process = pb.start(); BufferedReader reader = new BufferedReader(new inputStreamReader(process.getinputStream())); String line; /*switch(command_call_type) { case Keys.KEY_COMMANDEXE_TYPE_MERGEFRAME: // refincereference.updateLoadingbar(30); break; }*/ while ((line = reader.readline()) != null) { if (sc != null) { sc.shellOut(line.tochararray()); Log.d("FFMPEG",line.tochararray()+""); } } /*switch(command_call_type) { case Keys.KEY_COMMANDEXE_TYPE_MERGEFRAME: //refincereference.updateLoadingbar(40); break; case Keys.KEY_COMMANDEXE_TYPE_CliPMP3: //refincereference.updateLoadingbar(60); break; case Keys.KEY_COMMANDEXE_TYPE_MP3TOM4A: //refincereference.updateLoadingbar(80); break; }*/ /* if (process != null) { process.destroy(); }*/ } public class FFMPEGArg { String key; String value; public static final String ARG_VIDEOCODEC = "vcodec"; public static final String ARG_VERBOSITY = "v"; public static final String ARG_file_input = "i"; public static final String ARG_SIZE = "-s"; public static final String ARG_FRAMERATE = "-r"; public static final String ARG_FORMAT = "-f"; } public voID processVIDeo(file redactSettingsfile,ArrayList
BinaryInstaller.java
public class BinaryInstaller { file installFolder; Context context; private static int isARMv6 = -1; private static String CHMOD_EXEC = "700"; private final static int file_WRITE_BUFFER_SIZE = 32256; public BinaryInstaller (Context context,file installFolder) { this.installFolder = installFolder; this.context = context; } // /* * Extract the Tor binary from the APK file using ZIP */ public boolean installFromraw () throws IOException,fileNotFoundException { inputStream is; file outfile; is = context.getResources().openRawResource(R.raw.ffmpeg); outfile = new file(installFolder,"ffmpeg"); streamTofile(is,outfile,"700"); return true; } private static voID copyAssetfile(Context ctx,String asset,file file) throws IOException,InterruptedException { DataOutputStream out = new DataOutputStream(new fileOutputStream(file)); inputStream is = new GZIPinputStream(ctx.getAssets().open(asset)); byte buf[] = new byte[8172]; int len; while ((len = is.read(buf)) > 0) { out.write(buf,len); } out.close(); is.close(); } /* * Write the inputstream contents to the file */ private static boolean streamTofile(inputStream stm,file outfile,boolean append,boolean zip,String mode) throws IOException { byte[] buffer = new byte[file_WRITE_BUFFER_SIZE]; int bytecount; OutputStream stmOut = new fileOutputStream(outfile,append); if (zip) { ZipinputStream zis = new ZipinputStream(stm); ZipEntry ze = zis.getNextEntry(); stm = zis; } while ((bytecount = stm.read(buffer)) > 0) { stmOut.write(buffer,bytecount); } stmOut.close(); stm.close(); Runtime.getRuntime().exec("chmod "+mode+" "+outfile.getabsolutePath()); return true; } //copy the file from inputstream to file output - alternative impl public voID copyfile (inputStream is,file outputfile) { try { outputfile.createNewfile(); DataOutputStream out = new DataOutputStream(new fileOutputStream(outputfile)); DatainputStream in = new DatainputStream(is); int b = -1; byte[] data = new byte[1024]; while ((b = in.read(data)) != -1) { out.write(data); } if (b == -1); //rejoice // out.flush(); out.close(); in.close(); // chmod? } catch (IOException ex) { Log.e("SLIDEAGRAM","error copying binary",ex); } } /** * Check if this is an ARMv6 device * @return true if this is ARMv6 */ private static boolean isARMv6() { if (isARMv6 == -1) { BufferedReader r = null; try { isARMv6 = 0; r = new BufferedReader(new fileReader("/proc/cpuinfo")); for (String line = r.readline(); line != null; line = r.readline()) { if (line.startsWith("Processor") && line.contains("ARMv6")) { isARMv6 = 1; break; } else if (line.startsWith("cpu architecture") && (line.contains("6TE") || line.contains("5TE"))) { isARMv6 = 1; break; } } } catch (Exception ex) { } finally { if (r != null) try {r.close();} catch (Exception ex) {} } } return (isARMv6 == 1); } private static voID copyRawfile(Context ctx,int resID,file file,String mode,boolean isZipd) throws IOException,InterruptedException { final String abspath = file.getabsolutePath(); // Write the iptables binary final fileOutputStream out = new fileOutputStream(file); inputStream is = ctx.getResources().openRawResource(resID); if (isZipd) { ZipinputStream zis = new ZipinputStream(is); ZipEntry ze = zis.getNextEntry(); is = zis; } byte buf[] = new byte[1024]; int len; while ((len = is.read(buf)) > 0) { out.write(buf,len); } out.close(); is.close(); // Change the permissions Runtime.getRuntime().exec("chmod "+mode+" "+abspath).waitFor(); }}
FFMpegVIDeoProcess.java
public class FFMpegVIDeoProcess{ public static voID mergeFramesIntoVIDeo(Activity context,String duration_per_frame,String input_frame_path,String out_vIDeo_path)throws Exception { //Looper.prepare(); String ffmpegBin; FFMPEGWrapper ffmpeg = null; ShellUtils.ShellCallback sc; if (ffmpeg == null) ffmpeg = new FFMPEGWrapper(context); sc = new ShellUtils.ShellCallback () { int total = 0; int current = 0; @OverrIDe public voID shellOut(char[] shellout) { String line = new String(shellout); int IDx1; String newStatus = null; int progress = 0; if ((IDx1 = line.indexOf("Duration:"))!=-1) { int IDx2 = line.indexOf(",",IDx1); String time = line.substring(IDx1+10,IDx2); int hour = Integer.parseInt(time.substring(0,2)); int min = Integer.parseInt(time.substring(3,5)); int sec = Integer.parseInt(time.substring(6,8)); total = (hour * 60 * 60) + (min * 60) + sec; newStatus = line; progress = 0; } else if ((IDx1 = line.indexOf("time="))!=-1) { int IDx2 = line.indexOf(" ",IDx1); String time = line.substring(IDx1+5,IDx2); newStatus = line; int hour = Integer.parseInt(time.substring(0,8)); current = (hour * 60 * 60) + (min * 60) + sec; progress = (int)( ((float)current) / ((float)total) *100f ); } if (newStatus != null) { // Message msg = mHandler.obtainMessage(1); // msg.getData().putInt("progress",progress); // msg.getData().putString("status",newStatus); // mHandler.sendMessage(msg); } } }; ffmpegBin = new file(ffmpeg.fileBinDir,"ffmpeg").getabsolutePath(); Runtime.getRuntime().exec("chmod 700 " +ffmpegBin); // refincereference.updateLoadingbar(20); ffmpeg.execProcess(new String[]{ ffmpegBin,"image2",duration_per_frame,input_frame_path,"640x640",//"640x388",out_vIDeo_path },sc); //Looper.loop(); }}
将所有文件放在一起后,如果要将帧合并到视频中,请调用此函数,如下所示
FFMpegVIDeoProcess.createFramesinFolder(this,DIR_IN_WHICH_YOU_WANT_TO_KEEP_FRAMES,"frame_%03d.jpg"); FFMpegVIDeoProcess.mergeFramesIntoVIDeo(args1,DIR_IN_WHICH_YOU_WANT_TO_KEEP_FRAMES/frame_%3d.jpg",argN...);
如果您有任何查询,请随时提出问题.谢谢 总结
以上是内存溢出为你收集整理的寻找Android的FFmpeg Wrappers全部内容,希望文章能够帮你解决寻找Android的FFmpeg Wrappers所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)