如何在android中从命令行运行ffmpeg

Posted

技术标签:

【中文标题】如何在android中从命令行运行ffmpeg【英文标题】:How to run ffmpeg from command line in android 【发布时间】:2012-09-08 22:37:58 【问题描述】:

我想通过命令行使用 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

请告诉我我做错了什么。谢谢。

【问题讨论】:

对输入图像和输出视频尝试带有“-r”参数的命令,例如,ffmpeg -r 24 -i example.%d.png -vcodec mjpeg -samq -r 24 -y例子.mpeg 【参考方案1】:

首先,您不能直接执行shared object 文件。你需要构建一个可以使用/system/bin运行的ffmpeg可执行文件

请将此作为参考FFmpeg on android

在编译完成后,您可以将 APK 的 assets 文件夹中的可执行文件解压到 /data/data/<your package>/(确保 chmod 755 也一样!)

完成后,您可以使用构建命令行字符串并将其传递给ProcessBuilder 来运行可执行文件,而不是使用 Runtime.exec()

【讨论】:

hai Royston,ffmpeg 库未在 windows os 32 位中构建,请帮助我如何做到这一点? 您好,我从未尝试在 Windows 上构建它 :) @RoystonPinto 我想在 android 中播放视频,我应该在我的 xml 中制作视频视图。请用播放命令指导我【参考方案2】:

异常提到“环境”为空...

也许不是“exec”,而是尝试使用 processbuilder,如下面的运行 ffmpeg 的服务器端代码示例中包装在 shellscript(pars_submit) 中...注意 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;


                

IMO - android-ffmpeg 使用完整的 JNI 接口和包装器来调用 ffmpeg.main() 将更加可靠。查看所有 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() 上需要很多时间.. 有什么建议吗? 手机不适合快速转码。为了速度,你需要一个服务器。

以上是关于如何在android中从命令行运行ffmpeg的主要内容,如果未能解决你的问题,请参考以下文章

如何在命令行中从脚本运行函数?

如何在 WAMPServer 中从 Windows 命令行运行 PHP

怎么让 FFmpeg 运行命令呢?很

如何运行命令行 FFMPEG 并接受多个管道(视频和音频)而不阻塞第一个输入?

Android NDK开发之FFmpeg视频添加水印

在 argparse 中从变量而不是命令行获取值