ffmpeg-android-java
ffmpeg-android-java copied to clipboard
Compress the video in background
Hi, Thanks for the lib. It is very useful to my project. But if I take 2 min video mean it will take more than 5 min to compress. I am trying to run the compress process in background. But I can not do that. It requires UI injection. Is there any way to run the compress in background. So that user no need to wait for the compression. Please let me any idea to run the video compression in background.
You can use an IntentService for that: http://developer.android.com/training/run-background-service/create-service.html
It require UI injection. I can not inject the UI from service. Please let me how to do this.
You can use LocalBroadcastManager for that.
For example in your IntentService you can sendBroadcast() with an intent containing the data you need to update the UI:
Intent localProgressIntent = new Intent("BROADCAST_CREATEVIDEO_PROCESSING");
// Puts the status into the Intent
localProgressIntent.putExtra("CREATION_CURRENT_PROGRESS", progress);
// Broadcasts the Intent to receivers in this app.
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(localProgressIntent);
In the Activity where you want UI changes, you first have to listen to those broadcasts:
// The filter's action key is "BROADCAST_CREATEVIDEO_PROCESSING"
IntentFilter mStatusIntentFilter = new IntentFilter("BROADCAST_CREATEVIDEO_PROCESSING");
LocalBroadcastManager.getInstance(this).registerReceiver(mCreateVideoProcessReceiver, mStatusIntentFilter);
Where mCreateVideoProcessReceiver is the function that will be called when this activity receives data, so when you called sendBroadcast() in your IntentService.
private BroadcastReceiver mCreateVideoProcessReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
//Get the intent extras
Bundle extras = intent.getExtras();
if (extras != null){
//Get the progress that was passed
int currentProgress = extras.getInt("CREATION_CURRENT_PROGRESS");
mProgressBar.setProgress(currentProgress);
}
}
};
More information can be found in the Android docs: http://developer.android.com/training/run-background-service/report-status.html
Hi @SebSob @hiteshsondhi88 .. I am trying like this. I attached the code for your review.
public class VideoCompressionService extends Service {
private static final String TAG = VideoCompressActivity.class.getSimpleName();
@Inject
FFmpeg ffmpeg;
private static final int MY_NOTIFICATION_ID = 1;
NotificationManager notificationManager;
Notification myNotification;
@Override
public void onCreate() {
// TODO Auto-generated method stub
super.onCreate();
notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// Let it continue running until it is stopped.
Toast.makeText(this, "BGService Service Started", Toast.LENGTH_LONG).show();
Log.e("My Service==> ", "Started..");
notifyMessage("onStartCommand Start");
loadFFMpegBinary();
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Log.e("My Service==> ", "onDestroy..");
}
public void loadFFMpegBinary() {
try {
notifyMessage("loadFFMpegBinary Start");
ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
@Override
public void onFailure() {
Alerts.getInstance().showUnsupportedExceptionDialog();
}
});
notifyMessage("loadFFMpegBinary Second");
compressVideo(CustomCameraHandler.getInstance().getVideoPathDetails(), CustomCameraHandler.getInstance().getCCVideoOutPutPath().getAbsolutePath(), ffmpeg);
} catch (FFmpegNotSupportedException e) {
Alerts.getInstance().showUnsupportedExceptionDialog();
}
}
public void compressVideo(String source,String desc, FFmpeg ffmpeg){
notifyMessage("compressVideo Start");
MediaMetadataRetriever metaRetriever = new MediaMetadataRetriever();
metaRetriever.setDataSource(source);
String strtime = metaRetriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
int duration = Integer.parseInt(strtime);
int bitrate = calBitrate(duration / 1000, Integer.parseInt("10"));
int bufferSize=bitrate*2;
String cmd=String.format(Constants.FFMPEG_COMPRESS_COMMAND, bitrate, bufferSize);
cmd = Constants.FFMPEG_COMPRESS_RULES + source + cmd + desc;
String[] command = cmd.split(" ");
if (command.length != 0) {
notifyMessage("==> compressVideo If Start");
execFFmpegBinary(command,ffmpeg );
} else {
Toast.makeText(Application.getInstance().getApplicationContext(), "empty_command_toast", Toast.LENGTH_LONG).show();
}
}
private void execFFmpegBinary(final String[] command,FFmpeg ffmpeg ) {
try {
notifyMessage("==> execFFmpegBinary Start");
ffmpeg.execute(command, new ExecuteBinaryResponseHandler() {
@Override
public void onFailure(String s) {
notifyMessage("==> onFailure Start");
onDestroy();
Log.d(TAG, "FAILED with output : " + s);
}
@Override
public void onSuccess(String s) {
notifyMessage("==> onSuccess Start");
onDestroy();
Log.d(TAG, "SUCCESS with output : " + s);
}
});
} catch (FFmpegCommandAlreadyRunningException e) {
// do nothing for now
}
}
private int calBitrate(int duration, int targetSize){
targetSize = targetSize*1024*1024;
int audiosize = (120*1000/8)*duration;
return (targetSize-audiosize)*8/duration;
}
private void notifyMessage(String message){
String notificationText = message;
myNotification = new NotificationCompat.Builder(getApplicationContext())
.setContentTitle("Progress")
.setContentText(notificationText)
.setTicker("Notification!")
.setWhen(System.currentTimeMillis())
//.setDefaults(Notification.DEFAULT_SOUND)
.setAutoCancel(true)
.setSmallIcon(R.drawable.ic_launcher)
.build();
notificationManager.notify(MY_NOTIFICATION_ID, myNotification);
}
}
But I am getting Nullpointer exception in ffmpeg.loadBinary(new LoadBinaryResponseHandler().
I tried many way. I can not move the compression to background service. Please let me know any other idea to resolve this. Thanks in advance.
That's would be ideal to handle this is background, since it takes time. How did you handle it finally @Vijayadhas ? Thanks in advance.
Hi @Vijayadhas I am using this command for compressing video file , String[] mcpress={"-i","/storage/emulated/0/ffmpegTest/vtv_status.mp4","-c:v h264 -acodec mp3","/storage/emulated/0/ffmpegTest/mout.mp4"};
but i am getting following error in Onfailure. could you please tell how did you compress the video?
ffmpeg version n3.0.1 Copyright (c) 2000-2016 the FFmpeg developers built with gcc 4.8 (GCC) configuration: --target-os=linux --cross-prefix=/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/bin/arm-linux-androideabi- --arch=arm --cpu=cortex-a8 --enable-runtime-cpudetect --sysroot=/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/sysroot --enable-pic --enable-libx264 --enable-libass --enable-libfreetype --enable-libfribidi --enable-libmp3lame --enable-fontconfig --enable-pthreads --disable-debug --disable-ffserver --enable-version3 --enable-hardcoded-tables --disable-ffplay --disable-ffprobe --enable-gpl --enable-yasm --disable-doc --disable-shared --enable-static --pkg-config=/home/vagrant/SourceCode/ffmpeg-android/ffmpeg-pkg-config --prefix=/home/vagrant/SourceCode/ffmpeg-android/build/armeabi-v7a --extra-cflags='-I/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/include -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=2 -fno-strict-overflow -fstack-protector-all' --extra-ldflags='-L/home/vagrant/SourceCode/ffmpeg-android/toolchain-android/lib -Wl,-z,relro -Wl,-z,now -pie' --extra-libs='-lpng -lexpat -lm' --extra-cxxflags= libavutil 55. 17.103 / 55. 17.103 libavcodec 57. 24.102 / 57. 24.102 libavformat 57. 25.100 / 57. 25.100 libavdevice 57. 0.101 / 57. 0.101 libavfilter 6. 31.100 / 6. 31.100 libswscale 4. 0.100 / 4. 0.100 libswresample 2. 0.101 / 2. 0.101 libpostproc 54. 0.100 / 54. 0.100 Trailing options were found on the commandline. Input #0, mov,mp4,m4a,3gp,3g2,mj2, from '/storage/emulated/0/ffmpegTest/vtv_status.mp4': Metadata: major_brand : isom minor_version : 512 compatible_brands: isomiso2avc1mp41 encoder : Lavf57.71.100 Duration: 00:00:15.25, start: 0.046440, bitrate: 890 kb/s Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 640x272 [SAR 1:1 DAR 40:17], 757 kb/s, 25 fps, 25 tbr, 12800 tbn, 50 tbc (default) Metadata: handler_name : VideoHandler Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default) Metadata: handler_name : SoundHandler At least one output file must be specified
String[] mcpress={"-i","/storage/emulated/0/ffmpegTest/vtv_status.mp4","-c:v","h264","-acodec","mp3","/storage/emulated/0/ffmpegTest/mout.mp4"};
make this array list like this