2015-12-17 79 views
2

我開發了一個應用程序,可以從庫中播放視頻。我想在所選的視頻中使用FFmpeg命令添加水印。但我不知道如何將路徑傳遞給FFmpeg命令。我找不到適當的教程或參考資料。我的編碼如下:Android:將視頻路徑傳遞給FFmpeg

MainActivity.java:

import android.app.Activity; 
import android.app.ProgressDialog; 
import android.content.DialogInterface; 
import android.content.Intent; 
import android.net.Uri; 
import android.os.Bundle; 
import android.os.Handler; 
import android.os.Message; 
import android.os.PowerManager; 
import android.util.Log; 
import android.view.View; 
import android.widget.Button; 
import android.widget.Toast; 
import android.widget.VideoView; 

import com.netcompss.ffmpeg4android.CommandValidationException; 
import com.netcompss.ffmpeg4android.GeneralUtils; 
import com.netcompss.ffmpeg4android.Prefs; 
import com.netcompss.ffmpeg4android.ProgressCalculator; 
import com.netcompss.loader.LoadJNI; 

public class MainActivity extends Activity { 
public ProgressDialog progressBar; 

String workFolder = null; 
String demoVideoFolder = null; 
String demoVideoPath = null; 
String vkLogPath = null; 
LoadJNI vk; 
private final int STOP_TRANSCODING_MSG = -1; 
private final int FINISHED_TRANSCODING_MSG = 0; 
private boolean commandValidationFailedFlag = false; 

Button button; 
VideoView videoView; 
private static final int PICK_FROM_GALLERY = 1; 


private void runTranscodingUsingLoader() { 
    Log.i(Prefs.TAG, "runTranscodingUsingLoader started..."); 

    PowerManager powerManager = (PowerManager)MainActivity.this.getSystemService(Activity.POWER_SERVICE); 
    PowerManager.WakeLock wakeLock = powerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "VK_LOCK"); 
    Log.d(Prefs.TAG, "Acquire wake lock"); 
    wakeLock.acquire(); 



    String[] complexCommand = {"ffmpeg","-y" ,"-i", "/sdcard/videokit/in.mp4","-strict","experimental", 
      "-vf", "movie=/sdcard/videokit/watermark.png [watermark];" + 
      " [in][watermark] overlay=main_w-overlay_w-10:10 [out]","-s", 
      "320x240","-r", "30", "-b", "15496k", "-vcodec", "mpeg4","-ab", 
      "48000", "-ac", "2", "-ar", "22050", "/sdcard/videokit/out1.mp4"}; 
    /////////////////////////////////////////////////////////////////////// 


    vk = new LoadJNI(); 
    try { 
     // running complex command with validation 
     vk.run(complexCommand, workFolder, getApplicationContext()); 

     // running without command validation 
     //vk.run(complexCommand, workFolder, getApplicationContext(), false); 

     // running regular command with validation 
     //vk.run(GeneralUtils.utilConvertToComplex(commandStr), workFolder, getApplicationContext()); 

     Log.i(Prefs.TAG, "vk.run finished."); 
     // copying vk.log (internal native log) to the videokit folder 
     GeneralUtils.copyFileToFolder(vkLogPath, demoVideoFolder); 

    } catch (CommandValidationException e) { 
     Log.e(Prefs.TAG, "vk run exeption.", e); 
     commandValidationFailedFlag = true; 

    } catch (Throwable e) { 
     Log.e(Prefs.TAG, "vk run exeption.", e); 
    } 
    finally { 
     if (wakeLock.isHeld()) { 
      wakeLock.release(); 
      Log.i(Prefs.TAG, "Wake lock released"); 
     } 
     else{ 
      Log.i(Prefs.TAG, "Wake lock is already released, doing nothing"); 
     } 
    } 

    // finished Toast 
    String rc = null; 
    if (commandValidationFailedFlag) { 
     rc = "Command Vaidation Failed"; 
    } 
    else { 
     rc = GeneralUtils.getReturnCodeFromLog(vkLogPath); 
    } 
    final String status = rc; 
    MainActivity.this.runOnUiThread(new Runnable() { 
     public void run() { 
      Toast.makeText(MainActivity.this, status, Toast.LENGTH_LONG).show(); 
      if (status.equals("Transcoding Status: Failed")) { 
       Toast.makeText(MainActivity.this, "Check: " + vkLogPath + " for more information.", Toast.LENGTH_LONG).show(); 
      } 
     } 
    }); 
} 


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

    button = (Button) findViewById(R.id.button); 

    videoView = (VideoView) findViewById(R.id.videoview); 

    button.setOnClickListener(new View.OnClickListener() { 

     public void onClick(View v) { 
      // TODO Auto-generated method stub 
      Intent intent = new Intent(); 

      intent.setType("video/*"); 
      intent.setAction(Intent.ACTION_GET_CONTENT); 

      startActivityForResult(Intent.createChooser(intent, "Complete action using"), PICK_FROM_GALLERY); 
     } 
    }); 

} 

@Override 
public void onActivityResult(int requestCode, int resultCode, Intent data) { 
    if (resultCode != RESULT_OK) return; 

    if (requestCode == PICK_FROM_GALLERY) { 
     Uri mVideoURI = data.getData(); 
     videoView.setVideoURI(mVideoURI); 
     videoView.start(); 
     demoVideoFolder = mVideoURI.getPath(); 
     demoVideoPath = demoVideoFolder; 
     savevideo(mVideoURI); 

    } 


} 
private Handler handler = new Handler() { 
    @Override 
    public void handleMessage(Message msg) { 
     Log.i(Prefs.TAG, "Handler got message"); 
     if (progressBar != null) { 
      progressBar.dismiss(); 

      // stopping the transcoding native 
      if (msg.what == STOP_TRANSCODING_MSG) { 
       Log.i(Prefs.TAG, "Got cancel message, calling fexit"); 
       vk.fExit(getApplicationContext()); 


      } 
     } 
    } 
}; 

public void runTranscoding() { 
    progressBar = new ProgressDialog(MainActivity.this); 
    progressBar.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); 
    progressBar.setTitle("FFmpeg4Android Direct JNI"); 
    progressBar.setMessage("Press the cancel button to end the operation"); 
    progressBar.setMax(100); 
    progressBar.setProgress(0); 

    progressBar.setCancelable(false); 
    progressBar.setButton(DialogInterface.BUTTON_NEGATIVE, "Cancel", new DialogInterface.OnClickListener() { 
     @Override 
     public void onClick(DialogInterface dialog, int which) { 
      handler.sendEmptyMessage(STOP_TRANSCODING_MSG); 
     } 
    }); 

    progressBar.show(); 

    new Thread() { 
     public void run() { 
      Log.d(Prefs.TAG,"Worker started"); 
      try { 
       //sleep(5000); 
       runTranscodingUsingLoader(); 
       handler.sendEmptyMessage(FINISHED_TRANSCODING_MSG); 

      } catch(Exception e) { 
       Log.e("threadmessage",e.getMessage()); 
      } 
     } 
    }.start(); 

    // Progress update thread 
    new Thread() { 
     ProgressCalculator pc = new ProgressCalculator(vkLogPath); 
     public void run() { 
      Log.d(Prefs.TAG,"Progress update started"); 
      int progress = -1; 
      try { 
       while (true) { 
        sleep(300); 
        progress = pc.calcProgress(); 
        if (progress != 0 && progress < 100) { 
         progressBar.setProgress(progress); 
        } 
        else if (progress == 100) { 
         Log.i(Prefs.TAG, "==== progress is 100, exiting Progress update thread"); 
         pc.initCalcParamsForNextInter(); 
         break; 
        } 
       } 

      } catch(Exception e) { 
       Log.e("threadmessage",e.getMessage()); 
      } 
     } 
    }.start(); 
} 

public void savevideo (Uri mVideoURI){ 
    demoVideoFolder = mVideoURI.getPath(); 
    demoVideoPath = demoVideoFolder; 
    Log.i(Prefs.TAG, getString(R.string.app_name) + " version: " + GeneralUtils.getVersionName(getApplicationContext())); 

    Button invoke = (Button) findViewById(R.id.button); 
    invoke.setOnClickListener(new View.OnClickListener() { 
     public void onClick(View v) { 
      Log.i(Prefs.TAG, "run clicked."); 
      runTranscoding(); 
     } 
    }); 

    workFolder = getApplicationContext().getFilesDir() + "/"; 
    Log.i(Prefs.TAG, "workFolder (license and logs location) path: " + workFolder); 
    vkLogPath = workFolder + "vk.log"; 
    Log.i(Prefs.TAG, "vk log (native log) path: " + vkLogPath); 
    GeneralUtils.copyLicenseFromAssetsToSDIfNeeded(this, workFolder); 
    GeneralUtils.copyDemoVideoFromAssetsToSDIfNeeded(this, demoVideoFolder); 
    int rc = GeneralUtils.isLicenseValid(getApplicationContext(), workFolder); 
    Log.i(Prefs.TAG, "License check RC: " + rc); 

} 
} 

ffmpeg的命令:

String[] complexCommand = {"ffmpeg","-y" ,"-i", "/sdcard/videokit/in.mp4","-strict","experimental", 
      "-vf", "movie=/sdcard/videokit/watermark.png [watermark];" + 
      " [in][watermark] overlay=main_w-overlay_w-10:10 [out]","-s", 
      "320x240","-r", "30", "-b", "15496k", "-vcodec", "mpeg4","-ab", 
      "48000", "-ac", "2", "-ar", "22050", "/sdcard/videokit/out1.mp4"}; 

提斯命令是從一個樣本項目。我如何將視頻路徑傳遞給此命令?我不知道如何編輯命令來支持我的需求。有人可以通過這個指導我。任何幫助將非常有幫助。謝謝。

回答

2
complexCommand = {"ffmpeg","-y" ,"-i", "inputVideoPath","-strict","experimental", 
     "-vf", "movie=/sdcard/videokit/watermark.png [watermark];" + 
     " [in][watermark] overlay=main_w-overlay_w-10:10 [out]","-s", 
     "320x240","-r", "30", "-b", "15496k", "-vcodec", "mpeg4","-ab", 
     "48000", "-ac", "2", "-ar", "22050", "outputVideoPath"}; 

「inputVideoPath」是您需要指定要修改的視頻位置的地方。 「outputVideoPath」是您需要指定視頻輸出位置的地方。

[watermark]之後還有另一條路徑。如果有的話,這應該是水印圖像的路徑。

0

我能做到這一點使用

ffmpeg -y -i /sdcard/videokit/in.mp4 -i /sdcard/videokit/watermark.png -filter_complex [0:v][1:v]overlay=main_w-overlay_w-10:main_h-overlay_h-10[out] -map [out] -map 0:a -codec:a copy /sdcard/videokit/out_ben.mp4 

here服用。