|
|
@@ -0,0 +1,106 @@
|
|
|
+package com.sheep.gamegroup.util;
|
|
|
+
|
|
|
+import android.content.Context;
|
|
|
+import android.graphics.Bitmap;
|
|
|
+import android.media.MediaMetadataRetriever;
|
|
|
+
|
|
|
+import com.sheep.gamegroup.absBase.AbsObserver;
|
|
|
+import com.sheep.jiuyan.samllsheep.SheepApp;
|
|
|
+
|
|
|
+import java.io.File;
|
|
|
+import java.io.FileOutputStream;
|
|
|
+import java.io.IOException;
|
|
|
+import java.util.ArrayList;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Locale;
|
|
|
+
|
|
|
+import io.reactivex.Observable;
|
|
|
+import io.reactivex.ObservableEmitter;
|
|
|
+import io.reactivex.ObservableOnSubscribe;
|
|
|
+import io.reactivex.ObservableSource;
|
|
|
+import io.reactivex.android.schedulers.AndroidSchedulers;
|
|
|
+import io.reactivex.functions.Function;
|
|
|
+import io.reactivex.schedulers.Schedulers;
|
|
|
+
|
|
|
+/**
|
|
|
+ * Created by realicing on 2018/11/29.
|
|
|
+ * realicing@sina.com
|
|
|
+ * 可以获取视频帧
|
|
|
+ */
|
|
|
+public class MediaMetadataRetrieverUtil {
|
|
|
+ private static final String TAG = "MediaMetadataRetrieverUtil";
|
|
|
+
|
|
|
+ public static String getFilePath(String fromFile, String outDir, int index) {
|
|
|
+ return String.format(Locale.CHINA, "%s%s%s_frame_%d.png", outDir, File.separator, FileUtil.getFileNameNoExFromPath(fromFile), index);
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 取出视频文件中的图片帧列表
|
|
|
+ *
|
|
|
+ * @param fromFile 要操作的本地视频文件
|
|
|
+ * @param duration 单位毫秒
|
|
|
+ * @param size 需要的图片个数
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static void tryGetFrameFileList(final String fromFile, final long duration, final int size, AbsObserver<List<String>> absObserver) {
|
|
|
+ Observable.create(new ObservableOnSubscribe<List<String>>() {
|
|
|
+ @Override
|
|
|
+ public void subscribe(ObservableEmitter<List<String>> emitter) throws Exception {
|
|
|
+ emitter.onNext(getFrameFileList(fromFile, SheepApp.getInstance().getDir("frame", Context.MODE_PRIVATE).getAbsolutePath(), duration, size));
|
|
|
+ }
|
|
|
+ })
|
|
|
+ .subscribeOn(Schedulers.io())
|
|
|
+ .observeOn(AndroidSchedulers.mainThread())
|
|
|
+ .subscribe(absObserver);
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 取出视频文件中的图片帧列表
|
|
|
+ *
|
|
|
+ * @param fromFile 要操作的本地视频文件
|
|
|
+ * @param outDir 输出路径
|
|
|
+ * @param duration 单位毫秒
|
|
|
+ * @param size 需要的图片个数
|
|
|
+ * @return
|
|
|
+ */
|
|
|
+ public static List<String> getFrameFileList(String fromFile, String outDir, long duration, int size) {
|
|
|
+ if (duration < size || size < 1) {
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ long per = duration * 1000L / (size - 1);
|
|
|
+ List<String> resultList = new ArrayList<>();
|
|
|
+ long time = System.currentTimeMillis();
|
|
|
+ MediaMetadataRetriever metadataRetriever = new MediaMetadataRetriever();
|
|
|
+ metadataRetriever.setDataSource(fromFile);
|
|
|
+
|
|
|
+ for (int i = 0; i < size; i++) {
|
|
|
+ //这里单位为微秒
|
|
|
+ long atTime = i + 1 == size ? (duration * 1000L) : i * per;
|
|
|
+ Bitmap bitmap = metadataRetriever.getFrameAtTime(atTime, MediaMetadataRetriever.OPTION_CLOSEST);
|
|
|
+
|
|
|
+ String path = getFilePath(outDir, fromFile, i);
|
|
|
+ FileOutputStream fileOutputStream = null;
|
|
|
+ try {
|
|
|
+ fileOutputStream = new FileOutputStream(path);
|
|
|
+ bitmap.compress(Bitmap.CompressFormat.PNG, 90, fileOutputStream);
|
|
|
+ resultList.add(path);
|
|
|
+ } catch (Exception e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ } finally {
|
|
|
+ if (fileOutputStream != null) {
|
|
|
+ try {
|
|
|
+ fileOutputStream.close();
|
|
|
+ } catch (IOException e) {
|
|
|
+ e.printStackTrace();
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ bitmap.recycle();
|
|
|
+ }
|
|
|
+ long curTime = System.currentTimeMillis();
|
|
|
+ LogUtil.println(TAG, time, curTime, curTime - time, (curTime - time) / 1000, (curTime - time) / 10000);
|
|
|
+ return resultList;
|
|
|
+ }
|
|
|
+}
|