如何在安卓系统中通过命令行运行ffmpeg

11
我想使用命令行来使用ffmpeg。我已经将ffmpeg.so保存在项目的文件目录中。但是在这样做时,我遇到了异常情况。以下是我的代码:

public class MainActivity extends Activity {

    Process p;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Process p = Runtime.getRuntime().exec("/data/data/com.example.ffmpegnew/files/ffmpeg",null, new File("/data/data/com.example.ffmpegnew/files"));

        }
        catch(Exception e)
        {
            System.out.println("exception"+e);
        }

    }

}

这是异常:

09-16 16:21:24.992: I/System.out(2103): exceptionjava.io.IOException: Error running exec(). Commands: [/data/data/com.example.ffmpegnew/files/ffmpeg] Working Directory: /data/data/com.example.ffmpegnew/files Environment: null

请告诉我我犯了什么错误。谢谢。


1
尝试使用“-r”参数对输入图像和输出视频执行命令,例如,ffmpeg -r 24 -i example.%d.png -vcodec mjpeg -samq -r 24 -y example.mpeg - AndroidEnthusiastic
2个回答

14
首先,您不能直接执行一个共享对象文件。您需要构建一个可以使用/system/bin运行的ffmpeg可执行文件。
请参考Android上的FFmpeg
在您能够编译成功后,您可以将可执行文件放入APK的资产文件夹中,并将其提取到/data/data/<您的包名>/(确保chmod 755也被执行!)。
完成以上步骤后,您可以通过构建命令行字符串并将其传递给ProcessBuilder来运行可执行文件,而不是使用Runtime.exec()。

嗨Royston,FFmpeg库在Windows操作系统32位上无法构建,请帮我解决一下该怎么做? - Ajay
你好,我从未尝试在Windows上构建它 :) - Royston Pinto
@RoystonPinto 我想在安卓上播放视频,我应该在我的xml中创建一个VideoView吗?请指导我如何使用播放命令。 - Abdul Muheet

2
异常提到了“环境”为空……也许可以尝试使用进程生成器(processbuilder)代替“exec”,就像下面这个运行包装在shell脚本(pars_submit)中的ffmpeg的服务器端代码示例一样,请注意builder.environment。
        public String getFfmpeg(@QueryParam("infil1") String infil1, 
                @QueryParam("infil2") String infil2, @QueryParam("otfil") String otfil,
                @QueryParam("t") String time) {         
        String outfil = "dummy.mp4";

          List<String> command = new ArrayList<String>();
            command.add("vendor/bin/pars_submit");

            command.add(infil1);     

            command.add(infil2);
            command.add(otfil);
            command.add(time);

System.out.println("Starting process " +command.toString());
            ProcessBuilder builder = new ProcessBuilder(command);
            Map<String, String> environ = builder.environment();
//          for(Entry<String, String> entry : environ.entrySet()){
    //          System.out.println("ENV " +entry.getKey() + " " +entry.getValue());
      //      }
//          builder.redirectErrorStream(true);
            Process process = null;
            try {
                process = builder.start();

            InputStream is = process.getInputStream();

            InputStreamReader isr = new InputStreamReader(is);
            BufferedReader br = new BufferedReader(isr);
            String line;
            while ((line = br.readLine()) != null) {  
              //System.out.println(line);
                outfil=line;
            }

//          int exitVal = process.waitFor();
 //           System.out.println("Process exitValue: " + exitVal);
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }  
            finally {
                  if (process != null) {
                    process.destroy();
                    process = null;
                  }


                }           


            return outfil;


                }

我认为使用完整的JNI接口和ffmpeg.main()调用的包装器,android-ffmpeg将更加可靠。可以查看所有的git项目,搜索“android-ffmpeg”并查看它们如何调用ffmpeg。不使用CLI。

pars_submit

#!/bin/bash
shopt -s globstar
uri=$1
filnam="${uri##*/}"
uri2=$2
filnam2="${uri2##*/}"
otfil=$3
time=$4
curl -#LO  $uri
curl -#LO  $uri2
ffmpeg -y -loop 1 -i "$filnam" -i "$filnam2" -t "$time" -r 1/2 -pass 1 -vcodec libx264 -b:v 200k -bt 50k  -an -f mp4 -strict -2 -passlogfile mydummy /dev/null
# echo "ffmpegP1 Exit status" $?
ffmpeg -y -loop 1 -i "$filnam" -i "$filnam2" -t "$time" -r 1/2 -pass 2 -vcodec libx264 -b:v 200k -bt 50k  -f mp4 -strict -2 -passlogfile mydummy -ar 44100 "$otfil" 
# echo "ffmpegp2 Exit status" $?
# last test
json=$(curl  -X POST  -H "X-Parse-Application-Id: 3KxPB" -H "X-Parse-REST-API-Key: kVl5Z0CX"  -H "Content-Type: video/mp4"  --data-binary @"$otfil" https://api.parse.com/1/files/"$otfil")
# echo "parse POST Exit status" $?
echo $json

是的,它能工作,但在 br.readLine() 上需要很多时间。有什么建议吗? - Ahmad Arslan
1
手机不适合进行快速转码。为了速度,你需要一个服务器。 - Robert Rowntree

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接