FFmpegMediaMetadataRetriever-native.aar

 

FFmpegMediaMetadataRetriever-native.aar

 

下载地址:

https://github.com/wseemann/FFmpegMediaMetadataRetriever

releases中

1. 把下载的好多aar放在libs中,

  repositories {
        flatDir {
            dirs 'libs'
        }
    }
implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-core:1.0.15'
implementation 'com.github.wseemann:FFmpegMediaMetadataRetriever-native:1.0.15'

2.java引用:

import wseemann.media.FFmpegMediaMetadataRetriever;

上面的方法好像ok,还需要细细测试。

 

这是编译好的:

https://github.com/liangzs/ffmpeg/blob/master/armv7-fmmr.aar

 

在android系统中,有获取视频文件缩略图和时长api方法,系统的aip的方法最终是会调jni方法,这样使得我们在取一些不主流的视频格式文件的时候,获取不到缩略图和时长,然后即使是常见的编码,有时候也取不出来,对于某些机型来说。
一般系统自带的方法有两个如下:
一个是用MediaMetadataRetriever

MediaMetadataRetriever media = new MediaMetadataRetriever();
media.setDataSource(videoPath);
Bitmap bitmap = media.getFrameAtTime();

另外一个是contentprovider遍历cursor

 

Cursor thumbCursor = context.getApplicationContext().getContentResolver().query(
                    MediaStore.Video.Thumbnails.EXTERNAL_CONTENT_URI,
                    null, MediaStore.Video.Thumbnails.VIDEO_ID
                            + "=" + id, null, null);
            if (thumbCursor.moveToFirst()) {
                albumPath = thumbCursor.getString(thumbCursor
                        .getColumnIndex(MediaStore.Video.Thumbnails.DATA));
                Bitmap bitmap = BitmapFactory.decodeFile(albumPath);
            }
//时长
cursor.getInt(cursor.getColumnIndexOrThrow(MediaStore.Video.Media.DURATION));

对于因为项目碰到一些一些非主流的视频编码格式的,上面两个方法都不能取到缩略图和时长,那么只能用地方三的编码库了。最常见莫过于ffmpeg,刚好github上面有这么一个项目。
https://github.com/wseemann/FFmpegMediaMetadataRetriever
只取了其中呢一个arm-v7 的arr包,效果很杠杠的,但是单arm-v7的包就已经4M大小了,对于关心安装包体积的来说,只取一个缩略图和时长,又不用ffmpeg进行音视频解码的视频编解码功能,是有点大材小用了。所以重新对该开源项目进行裁剪编译。

首先,本人是在linux环境下进行编译的,如果window 编译也可以的,之前我在window编译ffmpeg的,索性这次我就在linux下编译了。

然后项目工程中,配置好ndk路径,因为要读取local.properties的值的,然后需要关心的有两个文件,build-ffmpeg.sh,build_ffmpeg.sh。
在build-ffmpeg.sh中我把不需要的cpu类型给去掉

 

TARGET_ARMEABI_DIR=$WORKING_DIR/../jni/ffmpeg/ffmpeg/armeabi
TARGET_ARMEABIV7A_DIR=$WORKING_DIR/../jni/ffmpeg/ffmpeg/armeabi-v7a
TARGET_X86_DIR=$WORKING_DIR/../jni/ffmpeg/ffmpeg/x86
TARGET_MIPS_DIR=$WORKING_DIR/../jni/ffmpeg/ffmpeg/mips
TARGET_X86_64_DIR=$WORKING_DIR/../jni/ffmpeg/ffmpeg/x86_64
TARGET_ARMEABI_64_DIR=$WORKING_DIR/../jni/ffmpeg/ffmpeg/arm64-v8a
注释成
#TARGET_ARMEABI_DIR=$WORKING_DIR/../jni/ffmpeg/ffmpeg/armeabi
TARGET_ARMEABIV7A_DIR=$WORKING_DIR/../jni/ffmpeg/ffmpeg/armeabi-v7a
#TARGET_X86_DIR=$WORKING_DIR/../jni/ffmpeg/ffmpeg/x86
#TARGET_MIPS_DIR=$WORKING_DIR/../jni/ffmpeg/ffmpeg/mips
#TARGET_X86_64_DIR=$WORKING_DIR/../jni/ffmpeg/ffmpeg/x86_64
#TARGET_ARMEABI_64_DIR=$WORKING_DIR/../jni/ffmpeg/ffmpeg/arm64-v8a

然后把build_ffmpeg.sh中的路径配置好,比如说原项目是mac环境,
PREBUILT=NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64

最后是修改裁剪编译脚本了,其查看configure有哪些指令可以用,一搜一大堆。
原脚本内容:

 

pushd ffmpeg-$FFMPEG_VERSION
./configure --target-os=linux \
    --incdir=$BUILD_DIR/$TARGET/include \
    --libdir=$BUILD_DIR/$TARGET/lib \
    --enable-cross-compile \
    --extra-libs="-lgcc" \
    --arch=$ARCH \
    --cc=$PREBUILT/bin/$HOST-gcc \
    --cross-prefix=$PREBUILT/bin/$HOST- \
    --nm=$PREBUILT/bin/$HOST-nm \
    --sysroot=$PLATFORM \
    --extra-cflags="$OPTIMIZE_CFLAGS " \
    --enable-shared \
    --enable-small \
    --extra-ldflags="-Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib -lc -lm -ldl -llog" \
    --disable-ffplay \
    --disable-ffmpeg \
    --disable-ffprobe \
    --disable-avfilter \
    --disable-avdevice \
    --disable-ffserver \
    --disable-doc \
    --disable-avdevice \
    --disable-swresample \
    --disable-postproc \
    --disable-avfilter \
    --disable-gpl \
    --disable-encoders \
    --disable-hwaccels \
    --disable-muxers \
    --disable-bsfs \
    --disable-protocols \
    --disable-indevs \
    --disable-outdevs \
    --disable-devices \
    --disable-filters \
    --enable-encoder=png \  编码格式开了png,因为要什么图片,其他编码都是禁用了--disable-encoders \
    --enable-protocol=file,http,https,mmsh,mmst,pipe,rtmp,rtmps,rtmpt,rtmpts,rtp \
    --disable-debug \
    --disable-asm \
    $ADDITIONAL_CONFIGURE_FLAG

然后我们的做法是把编码(encoder)禁用,封装(muxers)禁用,然后开放常用普遍的解码(decoders),解封装(demuxers)。如果后续项目发现有些编码格式取不出来,再把此编码格式放进去重新编译包。

最后多加了一下两句:

 

    --disable-decoders --enable-decoder=vp9 --enable-decoder=h264 --enable-decoder=mpeg4 --enable-decoder=aac \
    --disable-demuxers --enable-demuxer=rtsp --enable-demuxer=rtp --enable-demuxer=flv --enable-demuxer=h264 \

然后我编译出来封装成arr,就只有1.2M了,大体过程就是这样了

附上编译包地址:
https://github.com/liangzs/ffmpeg/blob/master/armv7-fmmr.aar

好吧,送佛送到西,以集成all-fmmr.aar为例

参考:https://blog.csdn.net/fxjzzyo/article/details/84989285

  • 首先,把all-fmmr.aar拷贝的工程的app/libs/目录下,如下图:
    在这里插入图片描述
  • 然后,在app的build.gradle文件的dependencies里添加下面一句:
compile(name:'all-fmmr',ext:'aar')
  •  
  • 再然后,在app的build.gradle文件的android里添加下面代码:
 repositories {
        flatDir {
            dirs 'libs'   // aar目录
        }
    }
  • 加好之后你的app的build.gradle文件应该是介样:
apply plugin: 'com.android.application'

android {
    compileSdkVersion 26
    defaultConfig {
        applicationId "com.example.fxjzzyo.helloworld"
        minSdkVersion 15
        targetSdkVersion 26
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    sourceSets{
        main{
            jniLibs.srcDirs=['libs']
        }
    }
    repositories {
        flatDir {
            dirs 'libs'   // aar目录
        }
    }
}

dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    implementation 'com.android.support:appcompat-v7:26.1.0'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
    androidTestCompile('com.android.support:support-annotations:26.1.0') {
        force = true;
    }
    compile(name:'all-fmmr',ext:'aar')
//    compile 'com.github.wseemann:FFmpegMediaMetadataRetriever:1.0.14'
}

这样,你就可以愉快地在代码里使用FFmpegMediaMetadataRetriever 啦!

2.2 代码里使用FFmpegMediaMetadataRetriever

正如github上介绍的代码就是

//new出对象
FFmpegMediaMetadataRetriever mmr = new FFmpegMediaMetadataRetriever();

//设置数据源
mmr.setDataSource(mUri);

//获取媒体文件的专辑标题
mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_ALBUM);

//获取媒体文件的专辑艺术家
mmr.extractMetadata(FFmpegMediaMetadataRetriever.METADATA_KEY_ARTIST);

//获取2秒处的一帧图片(这里的2000000是微秒!!!)
Bitmap b = mmr.getFrameAtTime(2000000, FFmpegMediaMetadataRetriever.OPTION_CLOSEST); 

//释放资源
mmr.release();

其实这个和Android自带的MediaMetadataRetriever用法一样一样的,就是多了个l类名变成了FFmpegMediaMetadataRetriever,其余都一样。

3. 完整代码

听说不贴完整代码的不厚道,我那么厚道当然贴一贴啦。惊喜吧~

3.1 布局文件activity_video_info.xml

<RelativeLayout 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">

    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentBottom="true"
        android:onClick="getVideoInfo"
        android:text="获取信息" />

    <ImageView
        android:id="@+id/iv_thumbnail"
        android:layout_width="200dp"
        android:layout_height="200dp"
        android:layout_below="@id/iv_thumbnail"
        android:layout_centerHorizontal="true" />

</RelativeLayout>

3.2 java代码VideoInfoActivity.java


public class VideoInfoActivity extends AppCompatActivity {

    private ImageView imageView;

    //这个网络视频url可能失效,很可能!所以你要自己找一个可以浏览器种打开播放的url
    String url = "http://219.238.7.67/mp4files/418000000CE88BD1/202.108.250.226/youku/657259485123b717b789144ef/03000801005C009A1DA6539003E880F6C38754-67FB-4855-9645-7E00B1822316.mp4";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_info);
        //android 6.0权限申请
        checkPermission();

    }
    public void checkPermission(){
        //检查权限(NEED_PERMISSION)是否被授权 PackageManager.PERMISSION_GRANTED表示同意授权
        if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
                != PackageManager.PERMISSION_GRANTED) {
            //用户已经拒绝过一次,再次弹出权限申请对话框需要给用户一个解释
            if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission
                    .WRITE_EXTERNAL_STORAGE)) {
                Toast.makeText(this, "请开通相关权限,否则无法正常使用本应用!", Toast.LENGTH_SHORT).show();
            }
            //申请权限
            ActivityCompat.requestPermissions(this, new String[]{android.Manifest.permission.WRITE_EXTERNAL_STORAGE}, 0);

        } else {
            Toast.makeText(this, "授权成功!", Toast.LENGTH_SHORT).show();
            //初始化
            init();
        }
    }
    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        if(requestCode==0){
            if(grantResults.length>0&&grantResults[0]==PackageManager.PERMISSION_GRANTED){
                //申请成功
                init();
            }else {
                Toast.makeText(this,"相机权限申请被拒绝!",Toast.LENGTH_SHORT).show();
            }
            return;
        }
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    private void init() {
        imageView = findViewById(R.id.iv_thumbnail);
    }

  /**
     * 点击按钮,获取视频缩略图
     * @param view
     */
    public void getVideoInfo(View view) {
        Bitmap videoThumbnail = null;
       
        //获取本地视频缩略图,在sdk根目录下准备一个test.mp4的文件
//        String videoPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/test.mp4";
//         videoThumbnail = getVideoThumbnail(videoPath);
        
        //获取网络视频缩略图
        videoThumbnail = getNetVideoThumbnail(url);
        
        imageView.setImageBitmap(videoThumbnail);

    }

    /**
     * 获取本地视频缩略图
     * @param filePath
     * @return
     */
    public Bitmap getVideoThumbnail(String filePath) {
        Bitmap b=null;
        //使用MediaMetadataRetriever
//        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        
        //FFmpegMediaMetadataRetriever
        FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever();
        File file = new File(filePath);
        try {

            retriever.setDataSource(file.getPath());
            b=retriever.getFrameAtTime();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (RuntimeException e) {
            e.printStackTrace();

        } finally {
            try {
                retriever.release();
            } catch (RuntimeException e) {
                e.printStackTrace();
            }
        }
        return b;
    }


    /**
     * 获取网络视频缩略图
     * @param url
     * @return
     */
    public Bitmap getNetVideoThumbnail(String url) {
        Bitmap b=null;
        //使用MediaMetadataRetriever
//        MediaMetadataRetriever retriever = new MediaMetadataRetriever();

        //FFmpegMediaMetadataRetriever
        FFmpegMediaMetadataRetriever retriever = new FFmpegMediaMetadataRetriever();

        try {
            retriever.setDataSource(url,new HashMap<String, String>());
            b=retriever.getFrameAtTime(400*1000,FFmpegMediaMetadataRetriever.OPTION_CLOSEST);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (RuntimeException e) {
            e.printStackTrace();

        } finally {
            try {
                retriever.release();
            } catch (RuntimeException e) {
                e.printStackTrace();
            }
        }
        return b;
    }

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

AI算法网奇

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值