/** * Copyright 2014 Djia * All right reserved. * * Created on 2014-8-13 */ package com.wind.gifassistant.data; import android.graphics.Bitmap; import android.graphics.Bitmap.CompressFormat; import android.media.MediaMetadataRetriever; import android.text.TextUtils; import android.util.Log; import com.wind.gifassistant.utils.AppConfigs; import com.wind.gifassistant.utils.AppUtils; import java.io.FileOutputStream; /** * * @author Djia * @time 2014-8-13下午4:50:43 * @instuction */ public class ExtractPicturesWorker { private static final String TAG = AppConfigs.APP_TAG + "ExtractPicturesWorker"; private static final boolean DEBUG = true; private static final int DEFAULT_FRAME_RATE = 10; private static final int MAX_FRAME_RATE = 25; private static final int MAX_FRAME_COUNT = 200; /** * */ public ExtractPicturesWorker() { // TODO Auto-generated constructor stub } // default public static boolean extractPictureToFile(String videoPath, int second) { return extractPictureToFile(videoPath, second, AppUtils.APP_GIF_TEMP_FILES_FOLDER_PATH, second + ""); } /* * 从指定的video中提取指定时间点的图片文件 目前只能生成为jep格式 */ public static boolean extractPictureToFile(String videoPath, int second, String outPath, String fileName) { boolean success = true; if (TextUtils.isEmpty(videoPath)) { logd("empty video path"); return false; } MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.setDataSource(videoPath); // 取得视频的长度(单位为毫秒) String time = retriever .extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); // 取得视频的长度(单位为秒) int total = Integer.valueOf(time) / 1000; if (second < 0 || second > total) { loge("unavalible second(" + second + "), total(" + total + ")"); return false; } Bitmap bitmap = retriever.getFrameAtTime(second * 1000 * 1000, MediaMetadataRetriever.OPTION_CLOSEST); String path = outPath + "/" + fileName + ".jpg"; FileOutputStream fos = null; try { fos = new FileOutputStream(path); bitmap.compress(CompressFormat.JPEG, 80, fos); fos.close(); } catch (Exception e) { success = false; e.printStackTrace(); } finally { if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); bitmap = null; } } return success; } /* * videoPath: 视频路径 * beginPos: 起始点,单位秒 * endPos: 结束点,单位秒 * frameRate:截取率,大小为 x帧/秒,人眼能容忍的一般为25帧/秒,这样的gif看起来比较连贯 */ public static int extractPicturesToFile(String videoPath, String outPath, int beginPos, int endPos, int frameRate) { if (TextUtils.isEmpty(videoPath)) { loge("empty video path"); return 0; } if (frameRate <= 0) { loge("unavalible frameRate( " + frameRate + ")"); return 0; } MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.setDataSource(videoPath); // 取得视频的长度(单位为毫秒) String time = retriever .extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); // 取得视频的长度(单位为秒) int total = Integer.valueOf(time) / 1000; if (endPos <= beginPos || endPos < 0 || endPos > total) { loge("unavalible beginPos(" + beginPos + "), and unavalible endPos(" + endPos +"), total(" + total + ")"); return 0; } int count = 0; // 计算时间点并导出图片 long beginPosUs = beginPos*1000*1000; int usSpace = (1*1000*1000) / frameRate; int totalS = endPos - beginPos; int totalFrames = frameRate*totalS + 1; logd("need total frames = " + totalFrames); for (int i = 0; i < totalFrames; i++) { long usP = (beginPosUs + (i * usSpace)); Bitmap bitmap = retriever.getFrameAtTime(usP, MediaMetadataRetriever.OPTION_CLOSEST_SYNC); if (bitmap == null) { logd("cant get frame in us(" + usP + ")"); continue; } logd("got frame in us(" + usP + ")"); String path = outPath + "/" + i + ".jpg"; FileOutputStream fos = null; try { fos = new FileOutputStream(path); bitmap.compress(CompressFormat.JPEG, 80, fos); fos.close(); count++; } catch (Exception e) { e.printStackTrace(); } finally { if (bitmap != null && !bitmap.isRecycled()) { bitmap.recycle(); bitmap = null; } } } return count; } /* * videoPath: 视频路径 * outPath: 解析出的图片保存位置 * beginPos: 起始点,单位秒 * endPos: 结束点,单位秒 * 该方法估计一个合理的frameRate,然后再截取 */ public static int extractPicturesToFile(String videoPath, String outPath, int beginPos, int endPos) { int frameRate = 0; int totalSecs = endPos - beginPos; if (totalSecs <= 0) { loge("unavalible secs"); return 0; } frameRate = MAX_FRAME_COUNT / totalSecs; if (frameRate < DEFAULT_FRAME_RATE) { frameRate = DEFAULT_FRAME_RATE; } if (frameRate > MAX_FRAME_RATE) { frameRate = MAX_FRAME_RATE; } logd("resonable framerate = " + frameRate); return extractPicturesToFile(videoPath, outPath, beginPos, endPos, frameRate); } /* * videoPath: 视频路径 * outPath: 解析出的图片保存位置 * beginPos: 起始点,单位秒 * endPos: 结束点,单位秒 * 该方法每秒只取3张图 */ public static int extractPicturesToFileHalf(String videoPath, String outPath, int beginPos, int endPos) { int totalSecs = endPos - beginPos; if (totalSecs <= 0) { loge("unavalible secs"); return 0; } return extractPicturesToFile(videoPath, outPath, beginPos, endPos, 2); } /* * 从指定的video中提取指定时间点的图片, 返回bitmap格式对象 */ public static Bitmap extractBitmap(String videoPath, int second) { if (TextUtils.isEmpty(videoPath)) { logd("extractBitmap empty video path"); return null; } MediaMetadataRetriever retriever = new MediaMetadataRetriever(); retriever.setDataSource(videoPath); // 取得视频的长度(单位为毫秒) String time = retriever .extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION); // 取得视频的长度(单位为秒) int total = Integer.valueOf(time) / 1000; if (second < 0 || second > total) { loge("unavalible second(" + second + "), total(" + total + ")"); return null; } Bitmap bitmap = retriever.getFrameAtTime(second * 1000 * 1000, MediaMetadataRetriever.OPTION_CLOSEST_SYNC); return bitmap; } private static void logd(String message) { if (DEBUG) { Log.d(TAG, message); } } private static void loge(String message) { if (DEBUG) { Log.e(TAG, message); } } }