Skip to content

Commit cf18df8

Browse files
committed
add README
1 parent 9f7ab80 commit cf18df8

File tree

9 files changed

+143
-36
lines changed

9 files changed

+143
-36
lines changed

.idea/misc.xml

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
# MediaUtils
2+
3+
A demo of record audio and video about Android
4+
5+
一个在 Android 上实现录像和录音功能的小例子。
6+
7+
GitHub 地址:[https://github.com/Werb/MediaUtils](https://github.com/Werb/MediaUtils)
8+
9+
[![download](/app/src/main/res/mipmap-xhdpi/video.png)](https://fir.im/cbas) 也可直接点击下载体验
10+
11+
* Android 的 MediaRecorder 相信用过的同学一定踩过很多坑
12+
* 之前写的代码很乱,现在重构了一下,可以直接放到自己的项目中用
13+
* 本例子将 MediaRecorder 进行了重构,通过 MediaUtils 对外暴露几个必需的方法来实现录像和录音功能
14+
* 录制视频界面参考新版微信小视频,还原了微信的动画效果
15+
* 支持 Android 7.0
16+
* 通过线程及 Exception 等手段避免了常见的 start failed , stop failed 等问题
17+
* 重绘了录制视频和录音时的两个自定义view,可在原本基础上进行二次开发
18+
* 提供了视频截图方法,支持双击放大,支持自动对焦
19+
* 视频录制暂时使用 SurfaceView + Camera , 后续会升级为 TextureView + Camera2
20+
21+
### 效果图
22+
23+
<!-- <img src="/screenshots/video.gif" alt="screenshot" title="home" width="360" height="640" />
24+
<img src="/screenshots/audio.gif" alt="screenshot" title="home" width="360" height="640" /> -->
25+
26+
### 核心类
27+
#### MediaUtils
28+
29+
* 重构后对外暴露只有8行代码,可结合实际情况使用
30+
```
31+
// 初始化
32+
MediaUtils mediaUtils = new MediaUtils(this);
33+
mediaUtils.setRecorderType(MediaUtils.MEDIA_VIDEO);
34+
mediaUtils.setTargetDir(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES));
35+
mediaUtils.setTargetName(UUID.randomUUID() + ".mp4");
36+
mediaUtils.setSurfaceView(surfaceView);
37+
// 开始录制
38+
mediaUtils.record()
39+
// 结束录制 save or unSave
40+
mediaUtils.stopRecordUnSave();
41+
mediaUtils.stopRecordSave();
42+
```
43+
44+
#### CameraHelper
45+
* 在 Android 中录制视频时显示的 Size 和实际拍照的 Size 是由 Camera 所决定的,最好的方法是计算出可支持的 PreviewSize 和 VideoSize 计算出一个合适的size,同时根据自己视频的用途,选择合理的 Size
46+
* CameraHelper 参考自 GoogleCameraSample 帮助你计算出合适的 Size
47+
```
48+
public static Camera.Size getOptimalVideoSize(List<Camera.Size> supportedVideoSizes,
49+
List<Camera.Size> previewSizes, int w, int h) {
50+
final double ASPECT_TOLERANCE = 0.1;
51+
double targetRatio = (double) w / h;
52+
// sizes
53+
List<Camera.Size> videoSizes;
54+
if (supportedVideoSizes != null) {
55+
videoSizes = supportedVideoSizes;
56+
} else {
57+
videoSizes = previewSizes;
58+
}
59+
Camera.Size optimalSize = null;
60+
// Start with max value and refine as we iterate over available video sizes. This is the
61+
// minimum difference between view and camera height.
62+
double minDiff = Double.MAX_VALUE;
63+
// Target view height
64+
int targetHeight = h;
65+
// Try to find a video size that matches aspect ratio and the target view size.
66+
// Iterate over all available sizes and pick the largest size that can fit in the view and
67+
// still maintain the aspect ratio.
68+
for (Camera.Size size : videoSizes) {
69+
double ratio = (double) size.width / size.height;
70+
if (Math.abs(ratio - targetRatio) > ASPECT_TOLERANCE)
71+
continue;
72+
if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
73+
optimalSize = size;
74+
minDiff = Math.abs(size.height - targetHeight);
75+
}
76+
}
77+
// Cannot find video size that matches the aspect ratio, ignore the requirement
78+
if (optimalSize == null) {
79+
minDiff = Double.MAX_VALUE;
80+
for (Camera.Size size : videoSizes) {
81+
if (Math.abs(size.height - targetHeight) < minDiff && previewSizes.contains(size)) {
82+
optimalSize = size;
83+
minDiff = Math.abs(size.height - targetHeight);
84+
}
85+
}
86+
}
87+
return optimalSize;
88+
}
89+
```
90+
91+
#### 自定义View
92+
* 仿造新版微信拍摄视频的界面,通过 Paint,RectF,Canvas 绘制
93+
* 突然喜欢上了在 Android 画动效,开启 dribbble 抄动效模式
94+
95+
好了,知识虽小但五脏俱全
96+
97+
欢迎使用我自己开源的一个 Android 图片选择器
98+
* 【PickPhotoView】 Github 地址:[https://github.com/Werb/PickPhotoSample](https://github.com/Werb/PickPhotoSample)
99+
100+
项目中关于 Android M的权限检查用到了,我的另外一个库
101+
* 【PermissionsChecker】Github 地址 :[https://github.com/Werb/PermissionsCheckerSample](https://github.com/Werb/PermissionsCheckerSample)
102+
103+
104+
105+
### 很高兴你看到这里
106+
107+
> 有时候啊 你总是在追赶前面的人
108+
109+
> 总是抱怨自己为什么不能再努力一点
110+
111+
>累了你可以停下来 看看原来的自己
112+
113+
>其实你已经很了不起了。
114+
115+
我是 wanbo 。

app/src/main/AndroidManifest.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010

1111
<application
1212
android:allowBackup="true"
13-
android:icon="@mipmap/ic_launcher"
13+
android:icon="@mipmap/video"
1414
android:label="@string/app_name"
1515
android:supportsRtl="true"
1616
android:theme="@style/AppTheme">

app/src/main/java/com/werb/mediautilsdemo/MediaUtils.java

Lines changed: 25 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
package com.werb.mediautilsdemo;
22

33
import android.app.Activity;
4+
import android.graphics.Bitmap;
45
import android.hardware.Camera;
56
import android.media.CamcorderProfile;
7+
import android.media.MediaMetadataRetriever;
68
import android.media.MediaRecorder;
79
import android.util.Log;
810
import android.view.GestureDetector;
@@ -14,6 +16,7 @@
1416
import com.werb.mediautilsdemo.widget.AutoFitTextureView;
1517

1618
import java.io.File;
19+
import java.io.FileOutputStream;
1720
import java.io.IOException;
1821
import java.util.List;
1922

@@ -50,20 +53,10 @@ public void setRecorderType(int type) {
5053
this.recorderType = type;
5154
}
5255

53-
/**
54-
* Dir
55-
*
56-
* @param file targetDir
57-
*/
5856
public void setTargetDir(File file) {
5957
this.targetDir = file;
6058
}
6159

62-
/**
63-
* name with suffix
64-
*
65-
* @param name
66-
*/
6760
public void setTargetName(String name) {
6861
this.targetName = name;
6962
}
@@ -341,4 +334,26 @@ private void setZoom(int zoomValue) {
341334
}
342335
}
343336

337+
private String getVideoThumb(String path) {
338+
MediaMetadataRetriever media = new MediaMetadataRetriever();
339+
media.setDataSource(path);
340+
return bitmap2File(media.getFrameAtTime());
341+
}
342+
343+
private String bitmap2File(Bitmap bitmap) {
344+
File thumbFile = new File(targetDir,
345+
targetName);
346+
if (thumbFile.exists()) thumbFile.delete();
347+
FileOutputStream fOut;
348+
try {
349+
fOut = new FileOutputStream(thumbFile);
350+
bitmap.compress(Bitmap.CompressFormat.JPEG, 100, fOut);
351+
fOut.flush();
352+
fOut.close();
353+
} catch (IOException e) {
354+
return null;
355+
}
356+
return thumbFile.getAbsolutePath();
357+
}
358+
344359
}

app/src/main/java/com/werb/mediautilsdemo/widget/AudioWaveView.java

Lines changed: 0 additions & 24 deletions
This file was deleted.

app/src/main/java/com/werb/mediautilsdemo/widget/AutoFitTextureView.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
/**
2424
* A {@link TextureView} that can be adjusted to a specified aspect ratio.
25+
* 暂时没用到
2526
*/
2627
public class AutoFitTextureView extends TextureView {
2728

1.23 KB
Loading

screenshots/audio.gif

137 KB
Loading

screenshots/video.gif

8.41 MB
Loading

0 commit comments

Comments
 (0)