---
tags: Android Studio, FFMPEG
---
# 簡易步驟將浮水印或圖片加到影片上(AndroidStudio+FFmpeg)
### 在自己的Android project中導入ffmpeg (Only use Java)
1. 下載 https://drive.google.com/file/d/0B2aT0QoEmtuaN0VJZ2Z4ODY3T2s/view
並且用AndroidStudio開啟載好的project, 然後將它要你裝的東西裝一裝或者更新一些套件
2. 回到你自己的project, 點選File => New => import module => 選擇步驟1.載好的資料夾:
```
ffmpeg4android_demo_studio\ffmpeg4android_lib
```
3. 在AndroidManifest.xml中加上permission
```xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
```
若是Android 6以上, 請在MainActivity的onCreate()中, 加上
```java
GeneralUtils.checkForPermissionsMAndAbove(MainActivity.this, false);
```
遇到紅字則Alt+Enter 它會幫你改build.gradle(App)檔
4. \(不確定是否必要\)
在build.gradle(App)中
```
Android{
.......
defaultConfig{
....
targetSdkVersion ...
後面加入
ndk{
abiFilter "armeabi-v7a"
}
}
}
.....
dependencies{
...
若沒有下面這行則加入
compile project(':ffmpeg4android_lib')
}
```
5. 在gradle.properties加入
```
android.useDeprecatedNdk=true
```
然後async project
### 使用WaterMarkHelper 將影片加上浮水印/圖片
6. 導入WaterMarkHelper.java之後,
在Activity底下宣告
```java
WaterMarkHelper myHelper;
```
7. 在要使用浮水印功能的地方初始化myHelper並設定參數
參數說明:
```java
String inputVideoPath 輸入影片的檔名路徑(ex:"/sdcard/input.mp4")
String inputWaterMarkPath 輸入浮水印圖片的檔名路徑(ex:"/sdcard/waterMark.png")
String outputVideoPath 輸出影片的檔名路徑(ex:"/sdcard/output.mp4")
String waterMarkX 浮水印在影片裡的橫向位置(左側為0), 可利用影片以及浮水印寬度及高度的參數
影片寬度: main_w, 影片高度: main_h, 圖片寬度: overlay_w, 圖片高度: overlay_h
String waterMarkY 浮水印在影片裡的直向位置(上方為0), 同樣可利用寬高參數
```
範例code:
```java
myHelper = new WaterMarkHelper("/sdcard/in.mp4", //請確保in.mp4存在/sdcard/
"/sdcard/watermark.png", //請確保watermark.png存在/sdcard/
"/sdcard/testOut.mp4", //
"main_w/2 - overlay_w/2", // x軸的正中間
"main_h/2 - overlay_h/2"); // y軸的正中間
```
8. 執行浮水印功能
```java
myHelper.addVideoWaterMark(MainActivity.this); //MainActivity改成你自己的Activity
```
上面那行的外面要包try/catch, 按Alt+Enter它應該會幫你包
範例code:
```java
try {
myHelper.addVideoWaterMark(MainActivity.this);
} catch (CommandValidationException e) {
e.printStackTrace();
}
```
### 參考資料:
[Android Warzone - FFmpeg4Android](http://androidwarzone.blogspot.tw/2011/12/ffmpeg4android.html)
# Easy steps to watermark a video(AS+FFmpeg)
### How to import FFmpeg in Android project (Only use Java)
1. Download this https://drive.google.com/file/d/0B2aT0QoEmtuaN0VJZ2Z4ODY3T2s/view
2. File => New => import module => go find the folder downloaded at step1:
```
ffmpeg4android_demo_studio\ffmpeg4android_lib
```
3. Add permission in AndroidManifest.xml
```xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
```
if the version is higher than Android 6, add the following code in onCreate() of your Activity
```java
GeneralUtils.checkForPermissionsMAndAbove(MainActivity.this, false);
```
Alt+Enter if encounter red font, AndroidStudio would help you to modify "build.gradle(Module)"
4. \(Not sure if necessary\)
In build.gradle(Module)
```
Android{
.......
defaultConfig{
....
targetSdkVersion ...
<Add the following code>
ndk{
abiFilter "armeabi-v7a"
}
}
}
.....
dependencies{
...
<Add the following code if doesn't exist>
compile project(':ffmpeg4android_lib')
}
```
5. add following code in "gradle.properties"
```
android.useDeprecatedNdk=true
```
and then async project
### How to use WaterMarkHelper(by Johnny Tu) to add watermark on video
6. After import "WaterMarkHelper.java" in your project, declare the following in your Activity
```java
WaterMarkHelper myHelper;
```
7. initialize myHelper with arguments
Arguments description:
```java
String inputVideoPath (ex:"/sdcard/input.mp4")
String inputWaterMarkPath (ex:"/sdcard/waterMark.png")
String outputVideoPath (ex:"/sdcard/output.mp4")
String waterMarkX the X-coordinate
Video width: main_w, Video height: main_h, Image Width: overlay_w, Image Height: overlay_h
String waterMarkY
```
example code:
```java
myHelper = new WaterMarkHelper("/sdcard/in.mp4", //be sure that in.mp4 exist in /sdcard/
"/sdcard/watermark.png", //be sure that watermark.png exist in /sdcard/
"/sdcard/testOut.mp4", //
"main_w/2 - overlay_w/2", // in the middle of X-axis
"main_h/2 - overlay_h/2"); // in the middle of Y-axis
```
8. adding watermark on video
```java
myHelper.addVideoWaterMark(MainActivity.this); //MainActivity改成你自己的Activity
```
there should be try/catch exception outside the above code, press Alt+Enter should work.
example code:
```java
try {
myHelper.addVideoWaterMark(MainActivity.this);
} catch (CommandValidationException e) {
e.printStackTrace();
}
```
### References:
[Android Warzone - FFmpeg4Android](http://androidwarzone.blogspot.tw/2011/12/ffmpeg4android.html)
# WaterMarkHelper.java
```java
import android.content.Context;
import android.util.Log;
import com.netcompss.ffmpeg4android.CommandValidationException;
import com.netcompss.loader.LoadJNI;
/**
* Created by johnnytu on 2017/5/26.
*/
public class WaterMarkHelper {
private String videoPath; //可任意
private String waterMarkPath; //可任意
private String overlayX;//影片寬=main_w, 浮水印寬=overlay_w
private String overlayY;//影片高=main_h, 浮水印寬=overlay_h
private String videoOutputPath; //可任意
private String videoOutputWidth;
private String videoOutputHeight;
private String videoOutputFps;
private String imgBiteRate;
private String voiceBiteRate;
private String voiceChannelAmount;
private String voiceSampleFrequency;// 聲音的取樣頻率
// 以下參數產生自 以上參數
private String videoOutputSize;
private String waterMarkSettings;
private String[] complexCommand;
WaterMarkHelper(String inputVideoPath,String inputWaterMarkPath,String outputVideoPath,String waterMarkX,String waterMarkY){
videoPath = inputVideoPath;
waterMarkPath = inputWaterMarkPath;
videoOutputPath = outputVideoPath;
overlayX = waterMarkX;
overlayY = waterMarkY;
videoOutputWidth = "";
videoOutputHeight = "";
videoOutputFps = "";
imgBiteRate = "";
voiceBiteRate = "";
voiceChannelAmount = "";
voiceSampleFrequency = "";// 聲音的取樣頻率
videoOutputSize = videoOutputWidth+"x"+videoOutputHeight; //= "320x240";
waterMarkSettings = "movie="+waterMarkPath+" [watermark]; [in][watermark] overlay="
+overlayX+":"+overlayY+" [out]";
// overlay = 寬:高, 影片寬main_w, 浮水印寬overlay_w
//String waterMarkSettings = "movie=/sdcard/videokit/watermark.png [watermark]; [in][watermark] overlay=main_w-overlay_w-10:10 [out]";
complexCommand = new String[]{"ffmpeg", "-y", "-i", videoPath, "-strict", "experimental",
"-vf", waterMarkSettings, "-vcodec", "mpeg4", videoOutputPath};
//vk.run(complexCommand,workFolder,getApplicationContext());
}
public void addVideoWaterMark(Context context) throws CommandValidationException {
Log.d("WaterMarkHelper","starting addVideoWaterMark");
long startTime = System.currentTimeMillis();
LoadJNI vk = new LoadJNI();
String workFolder = context.getApplicationContext().getFilesDir() + "/";
vk.run(complexCommand,workFolder,context.getApplicationContext());
Log.d("WaterMarkHelper","finish addVideoWaterMark, took "+
(System.currentTimeMillis()-startTime)/1000+"seconds.");
}
}
```
# Usage Example 範例程式
### MainActivity.java
```java
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import com.netcompss.ffmpeg4android.CommandValidationException;
import com.netcompss.ffmpeg4android.GeneralUtils;
import com.netcompss.loader.LoadJNI;
public class MainActivity extends AppCompatActivity {
Button btnTest;
WaterMarkHelper myHelper;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// for Android 6 and above, add permission
GeneralUtils.checkForPermissionsMAndAbove(MainActivity.this, false);
btnTest = (Button)findViewById(R.id.btnTest);
btnTest.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
// try {
// waterMarkVideo();
// } catch (CommandValidationException e) {
// e.printStackTrace();
// }
myHelper = new WaterMarkHelper("/sdcard/videokit/in.mp4",
"/sdcard/videokit/watermark.png",
"/sdcard/testOut.mp4",
"main_w/2 - overlay_w/2",
"main_h/2 - overlay_h/2");
try {
myHelper.addVideoWaterMark(MainActivity.this);
} catch (CommandValidationException e) {
e.printStackTrace();
}
}
});
}
/*
private void test(){
GeneralUtils.checkForPermissionsMAndAbove(MainActivity.this, true);
LoadJNI vk = new LoadJNI();
try {
String workFolder = getApplicationContext().getFilesDir().getAbsolutePath();
String[] complexCommand = {"ffmpeg","-i", "/sdcard/videokit/in.mp4"};
vk.run(complexCommand , workFolder , getApplicationContext());
Log.i("test", "ffmpeg4android finished successfully");
} catch (Throwable e) {
Log.e("test", "vk run exception.", e);
}
}
private void waterMarkVideo() throws CommandValidationException {
LoadJNI vk = new LoadJNI();
String workFolder = getApplicationContext().getFilesDir() + "/";
String videoPath = "/sdcard/videokit/in2.mp4"; //可任意
String videoOutputWidth = "320";
String videoOutputHeight = "240";
String waterMarkPath = "/sdcard/videokit/watermark.png"; //可任意
String overlayX = "main_w/2 - overlay_w/2";//影片寬=main_w, 浮水印寬=overlay_w
String overlayY = "main_h/2 - overlay_h/2";//影片高=main_h, 浮水印寬=overlay_h
String videoOutputPath = "/sdcard/videokit/testOut.mp4"; //可任意
String videoOutputFps = "30";
String imgBiteRate = "15496k";
String voiceBiteRate = "48000";
String voiceChannelAmount = "2";
String voiceSampleFrequency = "22050";// 聲音的取樣頻率
String videoOutputSize = videoOutputWidth+"x"+videoOutputHeight; //= "320x240";
String waterMarkSettings = "movie="+waterMarkPath+" [watermark]; [in][watermark] overlay="
+overlayX+":"+overlayY+" [out]";
// overlay = 寬:高, 影片寬main_w, 浮水印寬overlay_w
//String waterMarkSettings = "movie=/sdcard/videokit/watermark.png [watermark]; [in][watermark] overlay=main_w-overlay_w-10:10 [out]";
String[] complexCommand = {"ffmpeg","-y" ,"-i", videoPath,"-strict","experimental",
"-vf", waterMarkSettings,"-s", videoOutputSize,"-r", videoOutputFps, "-b", imgBiteRate,
"-vcodec", "mpeg4","-ab", voiceBiteRate, "-ac", voiceChannelAmount, "-ar", voiceSampleFrequency, videoOutputPath};
//vk.run(complexCommand,workFolder,getApplicationContext());
vk.run(complexCommand,workFolder,getApplicationContext());
}
*/
}
```
### activity_main.xml
```xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical"
tools:context="com.yutouch.watermarkapp.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:orientation="vertical">
<Button
android:id="@+id/btnTest"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Button" />
<TextView
android:id="@+id/textView"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintRight_toRightOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</LinearLayout>
</LinearLayout>
```
### AndroidManifest.xml
```xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.yutouch.watermarkapp">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
```