2017년 7월 10일 월요일

Android video encoding with fr and resolution manipulation


I want to be able to take a video recorded with an Android device and encode it to a new Resolution and Frame Rate using my app. The purpose is to upload a much smaller version of the original video (in size), since this will be videos 30 min long or more.
So far, I've read of people saying FFmpeg is they way to go. However, the documentation seems to be lacking.
I have also considered using http opencv http://opencv.org/platforms/android.html
Considering I need to manipulate the video resolution and frame rate, which tool do you think can do such things better? Are there any other technologies to consider?
An important question is, since this will be long videos, is it reasonable to do the encoding in an android device (Consider power resources, time, etc.)
Thanks in advance!

--
I decided to use ffmpeg to tackle this project. After much researching and trials, I was not able to build ffmpeg for library (using Ubuntu 14.04 LTS.)
However, I used this excellent library https://github.com/guardianproject/android-ffmpeg-java I just created a project and added that library and it works like a charm. No need to build your own files or mess with the Android NDK. Of course you would still need to build the library yourself if you want to customize it. But it has everything I need.
Here is an example of how I used to lower a video resolution and change the frame rate:
 @Override
 protected void onCreate(Bundle savedInstanceState) {
     super.onCreate(savedInstanceState);
     // input source
     final Clip clip_in = new Clip("/storage/emulated/0/Developer/test.mp4"); 

     Activity activity = (Activity) MainActivity.this;
     File fileTmp = activity.getCacheDir(); 
     File fileAppRoot = new File(activity.getApplicationInfo().dataDir);

     final Clip clip_out = new Clip("/storage/emulated/0/Developer/result2.mp4");
     //put flags in clip
     clip_out.videoFps = "30";
     clip_out.width = 480;
     clip_out.height = 320;
     clip_out.videoCodec = "libx264";
     clip_out.audioCodec = "copy";

     try {
         FfmpegController fc = new FfmpegController(fileTmp, fileAppRoot);
         fc.processVideo(clip_in, clip_out, false, new ShellUtils.ShellCallback() {

             @Override
             public void shellOut(String shellLine) {
                 System.out.println("MIX> " + shellLine);
             }

             @Override
             public void processComplete(int exitValue) {

                 if (exitValue != 0) {
                     System.err.println("concat non-zero exit: " + exitValue);
                     Log.d("ffmpeg","Compilation error. FFmpeg failed");
                     Toast.makeText(MainActivity.this, "result: ffmpeg failed", Toast.LENGTH_LONG).show();
                 } else {
                     if(new File( "/storage/emulated/0/Developer/result2.mp4").exists()) {
                         Log.d("ffmpeg","Success file:"+ "/storage/emulated/0/Developer/result2.mp4");
                     }
                 }
             }
         });
     } catch (FileNotFoundException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
     } catch (IOException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
     } catch (InterruptedException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
     } catch (Exception e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
     }
     // automated try and catch
      setContentView(R.layout.activity_main);
    }
 }
The function processVideo produces a command similar to ffmpeg -i input -s 480X320 -r 30 -vcodec libx264 -acodec copy output
This a very simple example, but it outputted the same kind of conversion done by ffmpeg desktop. This codes needs lots of work! I hope it helps anyone.

--

댓글 없음:

댓글 쓰기