Android中利用ffmpeg进行视频压缩

在项目中接到仿照微信小视频录制以及上传本地视频的需求,此时就要考虑到视频的压缩问题,第一时间想到了ffmpeg第三方视频压缩库,秉着不重复造轮子的原则,开始在博客上寻找开源代码。在鸿阳大神的公众号中找到了一篇由马北剑西投稿的文章。

该文章的博客地址:https://blog.csdn.net/mabeijianxi/article/details/63335722

开源代码github地址:https://github.com/mabeijianxi/small-video-record.

在实际运用操作中,发现该代码有一定的缺陷,有些机型无法获取到本地视频地址,于是在此基础上做了修改,供遇到相同问题的童鞋参考。

  /**
     * 下面是原博客中MainActivity中选择本地视频后处理压缩的代码,在一些机型上无法获取到视频地址
     */

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == CHOOSE_CODE) {
            //
            if (resultCode == RESULT_OK && data != null && data.getData() != null) {
                Uri uri = data.getData();
                String[] proj = { MediaStore.Images.Media.DATA ,MediaStore.Images.Media.MIME_TYPE};

                Cursor cursor = getContentResolver().query(uri, proj, null,
                        null, null);
                if (cursor != null && cursor.moveToFirst()) {
                    int _data_num = cursor.getColumnIndex(MediaStore.Images.Media.DATA);
                    int mime_type_num = cursor.getColumnIndex(MediaStore.Images.Media.MIME_TYPE);

                    String _data = cursor.getString(_data_num);
                    String mime_type = cursor.getString(mime_type_num);
                    if (!TextUtils.isEmpty(mime_type) && mime_type.contains("video") && !TextUtils.isEmpty(_data)) {
                        BaseMediaBitrateConfig compressMode = null;

                        int compressModeCheckedId = rg_only_compress_mode.getCheckedRadioButtonId();

                        if (compressModeCheckedId == R.id.rb_cbr) {
                            String bitrate = et_only_compress_bitrate.getText().toString();
                            if (checkStrEmpty(bitrate, "请输入压缩额定码率")) {
                                return;
                            }
                            compressMode = new CBRMode(166, Integer.valueOf(bitrate));
                        } else if (compressModeCheckedId == R.id.rb_auto) {
                            String crfSize = et_only_compress_crfSize.getText().toString();
                            if (TextUtils.isEmpty(crfSize)) {
                                compressMode = new AutoVBRMode();
                            } else {
                                compressMode = new AutoVBRMode(Integer.valueOf(crfSize));
                            }
                        } else if (compressModeCheckedId == R.id.rb_vbr) {
                            String maxBitrate = et_only_compress_maxbitrate.getText().toString();
                            String bitrate = et_only_compress_bitrate.getText().toString();

                            if (checkStrEmpty(maxBitrate, "请输入压缩最大码率") || checkStrEmpty(bitrate, "请输入压缩额定码率")) {
                                return;
                            }
                            compressMode = new VBRMode(Integer.valueOf(maxBitrate), Integer.valueOf(bitrate));
                        } else {
                            compressMode = new AutoVBRMode();
                        }

                        if (!spinner_only_compress.getSelectedItem().toString().equals("none")) {
                            compressMode.setVelocity(spinner_only_compress.getSelectedItem().toString());
                        }

                        String sRate = et_only_framerate.getText().toString();
                        int iRate=0;
                        if(!TextUtils.isEmpty(sRate)){
                            iRate=Integer.valueOf(sRate);
                        }
                        LocalMediaConfig.Buidler buidler = new LocalMediaConfig.Buidler();
                        final LocalMediaConfig config = buidler
                                .setVideoPath(_data)
                                .captureThumbnailsTime(1)
                                .doH264Compress(compressMode)
                                .setFramerate(iRate)
                                .build();
                        new Thread(new Runnable() {
                            @Override
                            public void run() {
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        showProgress("","压缩中...",-1);
                                    }
                                });
                                OnlyCompressOverBean onlyCompressOverBean = new LocalMediaCompress(config).startCompress();
                                runOnUiThread(new Runnable() {
                                    @Override
                                    public void run() {
                                        hideProgress();
                                    }
                                });
                                Intent intent = new Intent(MainActivity.this, SendSmallVideoActivity.class);
                                intent.putExtra(MediaRecorderActivity.VIDEO_URI, onlyCompressOverBean.getVideoPath());
                                intent.putExtra(MediaRecorderActivity.VIDEO_SCREENSHOT, onlyCompressOverBean.getPicPath());
                                startActivity(intent);
                            }
                        }).start();
                    } else {
                        Toast.makeText(this, "选择的不是视频或者地址错误,也可能是这种方式定制神机取不到!", Toast.LENGTH_SHORT);
                    }
                }
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

 修改后的代码:

 @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == CHOOSE_CODE) {
            //
            if (resultCode == RESULT_OK && data != null && data.getData() != null) {
                Uri uri = data.getData();
                String[] proj = { MediaStore.Images.Media.DATA ,MediaStore.Images.Media.MIME_TYPE};

                String path = getPath(this, uri);       //  修改后获取本地视频地址
                BaseMediaBitrateConfig compressMode = null;

                int compressModeCheckedId = rg_only_compress_mode.getCheckedRadioButtonId();

                if (compressModeCheckedId == R.id.rb_cbr) {
                    String bitrate = et_only_compress_bitrate.getText().toString();
                    if (checkStrEmpty(bitrate, "请输入压缩额定码率")) {
                        return;
                    }
                    compressMode = new CBRMode(166, Integer.valueOf(bitrate));
                } else if (compressModeCheckedId == R.id.rb_auto) {
                    String crfSize = et_only_compress_crfSize.getText().toString();
                    if (TextUtils.isEmpty(crfSize)) {
                        compressMode = new AutoVBRMode();
                    } else {
                        compressMode = new AutoVBRMode(Integer.valueOf(crfSize));
                    }
                } else if (compressModeCheckedId == R.id.rb_vbr) {
                    String maxBitrate = et_only_compress_maxbitrate.getText().toString();
                    String bitrate = et_only_compress_bitrate.getText().toString();

                    if (checkStrEmpty(maxBitrate, "请输入压缩最大码率") || checkStrEmpty(bitrate, "请输入压缩额定码率")) {
                        return;
                    }
                    compressMode = new VBRMode(Integer.valueOf(maxBitrate), Integer.valueOf(bitrate));
                } else {
                    compressMode = new AutoVBRMode();
                }

                if (!spinner_only_compress.getSelectedItem().toString().equals("none")) {
                    compressMode.setVelocity(spinner_only_compress.getSelectedItem().toString());
                }

                String sRate = et_only_framerate.getText().toString();
                int iRate=0;
                if(!TextUtils.isEmpty(sRate)){
                    iRate=Integer.valueOf(sRate);
                }
                LocalMediaConfig.Buidler buidler = new LocalMediaConfig.Buidler();
                final LocalMediaConfig config = buidler
                        .setVideoPath(path)
                        .captureThumbnailsTime(1)
                        .doH264Compress(compressMode)
                        .setFramerate(iRate)
                        .build();
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                showProgress("","压缩中...",-1);
                            }
                        });
                        OnlyCompressOverBean onlyCompressOverBean = new LocalMediaCompress(config).startCompress();
                        runOnUiThread(new Runnable() {
                            @Override
                            public void run() {
                                hideProgress();
                            }
                        });
                        Intent intent = new Intent(MainActivity.this, SendSmallVideoActivity.class);
                        intent.putExtra(MediaRecorderActivity.VIDEO_URI, onlyCompressOverBean.getVideoPath());
                        intent.putExtra(MediaRecorderActivity.VIDEO_SCREENSHOT, onlyCompressOverBean.getPicPath());
                        startActivity(intent);
                    }
                }).start();
            }
        }
        super.onActivityResult(requestCode, resultCode, data);
    }

 增加以下几个方法:

@SuppressLint("NewApi")
    public static String getPath(final Context context, final Uri uri) {

        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) {
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory() + "/" + split[1];
                }

                // TODO handle non-primary volumes
            }
            // DownloadsProvider
            else if (isDownloadsDocument(uri)) {

                final String id = DocumentsContract.getDocumentId(uri);
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));

                return getDataColumn(context, contentUri, null, null);
            }
            // MediaProvider
            else if (isMediaDocument(uri)) {
                final String docId = DocumentsContract.getDocumentId(uri);
                final String[] split = docId.split(":");
                final String type = split[0];

                Uri contentUri = null;
                if ("image".equals(type)) {
                    contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
                } else if ("video".equals(type)) {
                    contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
                } else if ("audio".equals(type)) {
                    contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
                }

                final String selection = "_id=?";
                final String[] selectionArgs = new String[] {
                        split[1]
                };

                return getDataColumn(context, contentUri, selection, selectionArgs);
            }
        }
        // MediaStore (and general)
        else if ("content".equalsIgnoreCase(uri.getScheme())) {

            // Return the remote address
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();

            return getDataColumn(context, uri, null, null);
        }
        // File
        else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }

        return null;
    }

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context The context.
     * @param uri The Uri to query.
     * @param selection (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    public static String getDataColumn(Context context, Uri uri, String selection,
                                       String[] selectionArgs) {

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {
                column
        };

        try {
            cursor = context.getContentResolver().query(uri, projection, selection, selectionArgs,
                    null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                return cursor.getString(index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }


    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    public static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is DownloadsProvider.
     */
    public static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    public static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is Google Photos.
     */
    public static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

猜你喜欢

转载自blog.csdn.net/Lulu_hsu/article/details/82379411