我是Android应用开发的新手,我被要求制作视频分割器应用。我正在尝试使用FFMPEG,但库大小很大,使得.APK文件为140MB。我怎么解决这个问题?类似的应用程序大小约为15MB。
此外,当尝试将30秒长的视频分成两部分时,帧速率从~30FPS开始并随着时间的推移下降到2.2FPS左右。我怎么解决这个问题?这是我目前的代码:
package splicer.com.splicer;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.media.MediaMetadataRetriever;
import android.media.MediaScannerConnection;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.method.ScrollingMovementMethod;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import com.github.hiteshsondhi88.libffmpeg.ExecuteBinaryResponseHandler;
import com.github.hiteshsondhi88.libffmpeg.FFmpeg;
import com.github.hiteshsondhi88.libffmpeg.LoadBinaryResponseHandler;
import com.github.hiteshsondhi88.libffmpeg.exceptions.FFmpegNotSupportedException;
public class MainActivity extends AppCompatActivity {
private Button button;
private TextView textView;
private FFmpeg ffmpeg;
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
ffmpeg = FFmpeg.getInstance(getApplicationContext());
try {
ffmpeg.loadBinary(new LoadBinaryResponseHandler() {
@Override
public void onStart() {}
@Override
public void onFailure() {}
@Override
public void onSuccess() {}
@Override
public void onFinish() {}
});
} catch(FFmpegNotSupportedException e) {
e.printStackTrace();
}
textView = (TextView) findViewById(R.id.textView);
textView.setY(200);
textView.setHeight(700);
textView.setMovementMethod(new ScrollingMovementMethod());
button = (Button) findViewById(R.id.button);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
openGallery();
}
});
}
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String stringFromJNI();
public void openGallery() {
if(ContextCompat.checkSelfPermission(this, Manifest.permission.READ_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String [] {Manifest.permission.READ_EXTERNAL_STORAGE}, 0);
}
if(ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String [] {Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);
}
Intent gallery = new Intent(Intent.ACTION_PICK, MediaStore.Video.Media.EXTERNAL_CONTENT_URI);
startActivityForResult(gallery, 100);
}
public String getRealPathFromURI(Context context, Uri contentUri) {
Cursor cursor = null;
try {
String[] proj = { MediaStore.Images.Media.DATA };
cursor = context.getContentResolver().query(contentUri, proj, null, null, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
cursor.moveToFirst();
return cursor.getString(column_index);
} finally {
if (cursor != null) {
cursor.close();
}
}
}
@Override
protected void onActivityResult(int requestCode, int resultCode, final Intent intent) {
super.onActivityResult(requestCode, resultCode, intent);
if(resultCode == RESULT_OK && requestCode == 100) {
MediaMetadataRetriever retriever = new MediaMetadataRetriever();
try {
retriever.setDataSource(getBaseContext(), intent.getData());
String time = retriever.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION);
long splitCount = Long.valueOf(time) / 1000 / 15;
if(splitCount > 1) {
final String path = getRealPathFromURI(getBaseContext(), Uri.parse(intent.getData().toString()));
for(int a = 0, start = 0; a < splitCount; ++a, start += 15) {
// I am only testing with .mp4s atm, this will change before production
final String targetPath = path.replace(".mp4", "_" + (a + 1) + ".mp4");
ffmpeg.execute(new String [] {
"-r",
"1",
"-i",
path,
"-ss",
String.valueOf(start),
"-t",
String.valueOf(start + 15),
"-r",
"24",
targetPath
}, new ExecuteBinaryResponseHandler() {
@Override
public void onStart() {}
@Override
public void onProgress(String message) {
textView.setText("onProcess: " + message);
}
@Override
public void onFailure(String message) {
textView.setText("onFailure: " + message + " --- " + path);
}
@Override
public void onSuccess(String message) {
textView.setText("onSuccess:" + message);
MediaScannerConnection.scanFile(getBaseContext(),
new String [] { targetPath }, null,
new MediaScannerConnection.OnScanCompletedListener() {
public void onScanCompleted(String path, Uri uri) {}
});
}
@Override
public void onFinish() {}
});
}
}
} catch(Exception e) {
e.printStackTrace();
} finally {
retriever.release();
}
}
}
}
我不相信这里的一切都尽可能最优,但我只是想在此刻证明这个概念。在正确的方向上任何帮助都会很棒,谢谢!