Android錄製小視訊(仿微信小視訊)
Android錄製小視訊
一、概述
日常生活中,錄製一些視訊已經漸漸成為一種習慣,當然這對於我們技術來說並沒有什麼影響,因為無論大家用不用,你都需要開發,這只是需求制定者–PM應該關心的事情,我們需要關心的是視訊開發的過程以及難點還有會碰上什麼坑,這才是技術應該想的事情。不過,市場上面的視訊以及直播的App確實也是與日俱增,蝌蚪音客、美拍、小影,小咖秀,快手等等。這類App的技術難點基本都是在音視訊處理這一塊,iOS對多媒體處理的支援比較豐富,但是Android就會差很多,不是總有著ios程式設計師的一句話:“我們系統支援呀……”,這時候你除了心裡呵呵,好像也沒有別的辦法了哈,那麼作為Android的屌絲,還是老老實實研究一下自己該怎麼去爬坑吧。
二、型別
大家都知道Android原生錄製比例是1:1,當然這並不是說我們萬能的Android開發者就沒有別的渠道,下面就是比較高大上的用法:
1.這時候大可以放棄原生的介面,使用FFmpeg和OpenCV進行錄製,但是缺點也是明顯的,多機型相容複雜並且要求開發者一定程度的C語言功底,但是最難解決的問題是效能問題,FFmeg和OpenCV都是開源方案,如果要真正達實用級別往往還需要優化定製,這對於熟練於做Android展現的開發者來說完全就是一個新的領域。
2.使用原生API錄製,做一些遮罩等處理,例如微信未更新錢的小視訊,就是這樣的展現形式,當然正常的錄製就沒什麼大問題了,就是各種適配麻煩點,其他的都好說,而且對於開發者來說也能更好的接受。
三、視訊錄製
(一)、第一種方式可以直接呼叫系統錄影
// 啟用系統的照相機進行錄影
Intent intent = new Intent();
intent.setAction("android.media.action.VIDEO_CAPTURE");
intent.addCategory("android.intent.category.DEFAULT");
// 保存錄像到指定的路徑
File file = new File("/sdcard/video.3pg");
Uri uri = Uri.fromFile(file);
intent.putExtra(MediaStore.EXTRA_OUTPUT, uri);
startActivityForResult(intent, 0 );
(二)、當然大部分需求都需要自己定義並且修改某些屬性,下面著重說一下自定義寫法。
1.自定義錄影佈局
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="@android:color/background_dark"
android:orientation="vertical">
<SurfaceView
android:id="@+id/surfaceview"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1" />
<ProgressBar
android:id="@+id/progressBar"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="3dp" />
</LinearLayout>
surfaceView主要使用來顯示錄製視訊的,progressbar顯示進度條。
2.定義自定義RecordVideo
@SuppressLint("NewApi")
public RecordVideo(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// 初始化各項元件
TypedArray typedArray = context.obtainStyledAttributes(attrs, R.styleable.RecordVideo, defStyle, 0);
mWidth = typedArray.getInteger(R.styleable.RecordVideo_witdh, 320);// 預設320
mHeight = typedArray.getInteger(R.styleable.RecordVideo_height, 240);// 預設240
isOpenCamera = typedArray.getBoolean(R.styleable.RecordVideo_open_camera, true);// 預設開啟
mRecordMaxTime=typedArray.getInteger(R.styleable.RecordVideo_timeLenght,60);//預設為10
LayoutInflater.from(context).inflate(R.layout.movie_recorder_view, this);
mSurfaceView = (SurfaceView) findViewById(R.id.surfaceview);
mProgressBar = (ProgressBar) findViewById(R.id.progressBar);
mProgressBar.setMax(mRecordMaxTime);// 設定進度條最大量
mSurfaceHolder = mSurfaceView.getHolder();
mSurfaceHolder.addCallback(new CustomCallBack());
mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
//釋放資源
typedArray.recycle();
}
初始化使用的元件,把第一步surfaceView設定進來
3.定義一個CallBack,並且初始化攝像頭這個必備資源
private class CustomCallBack implements SurfaceHolder.Callback {
@Override
public void surfaceCreated(SurfaceHolder holder) {
if (!isOpenCamera)
return;
initCamera();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if (!isOpenCamera)
return;
releaseCameraResource();
}
}
//初始化攝像
@SuppressLint("NewApi")
public void initCamera() {
if (mCamera != null) {
releaseCameraResource();
}
try {
mCamera = Camera.open();
mCamera.setDisplayOrientation(90);
mCamera.setPreviewDisplay(mSurfaceHolder);
} catch (Exception e) {
//提示使用者許可權並且釋放建立資源
releaseCameraResource();
}
if (mCamera == null)
return;
mCamera.startPreview();
mCamera.unlock();
}
//釋放攝像頭資源
private void releaseCameraResource() {
if (mCamera != null) {
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.lock();
mCamera.release();
mCamera = null;
}
}
4.進入主題,初始化攝像一些基本引數
//初始化攝像頭基本引數
private void initRecord() {
mMediaRecorder = new MediaRecorder();
mMediaRecorder.reset();
if (mCamera != null)
mMediaRecorder.setCamera(mCamera);
mMediaRecorder.setOnErrorListener(this);
mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());
mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);//視訊源
mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//音訊源
mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);//視訊輸出格式
mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);//音訊格式
mMediaRecorder.setVideoSize(mWidth, mHeight);//設定解析度
//設定幀頻率,可以按照需求適當調整,這個直接相關錄製視訊的大小
mMediaRecorder.setVideoEncodingBitRate(1 * 1024 * 1024);
mMediaRecorder.setOrientationHint(90);// 輸出旋轉90度,保持豎屏錄製
mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);// 視訊錄製格式
mMediaRecorder.setOutputFile(mRecordFile.getAbsolutePath());
try {
mMediaRecorder.prepare();
mMediaRecorder.start();
} catch (Exception e) {
//提示錄製許可權存在問題,開啟相關許可權
}
}
上面比較注意的一個是設定幀頻率,這個會影響視訊錄製後的大小;一個是MPEG_4格式,其實就是MP4格式,另一個就是H264格式,這個跟編解碼有關,經過測試,設定H264格式會使Android跟ios通用,其他格式會出現視訊在ios上面無法播放的情況,望大家多多注意。
5.下面就進入激動人心的錄製視訊的時刻,這裡面產生的坑後面會說明一些碰到的
/**
* 開始錄製視訊
* @param onRecordFinishListener 達到指定時間之後回撥介面
*/
public void record(OnRecordFinishListener onRecordFinishListener) {
this.mOnRecordFinishListener = onRecordFinishListener;
createRecordDir();
if (!isOpenCamera)// 如果未開啟攝像頭,則開啟
initCamera();
initRecord();
mTimeCount = 0;// 時間計數器重新賦值
mTimer = new Timer();
mTimer.schedule(new TimerTask() {
@Override
public void run() {
// TODO Auto-generated method stub
mTimeCount++;
mProgressBar.setProgress(mTimeCount);// 設定進度條
if (mTimeCount == mRecordMaxTime) {// 達到指定時間,停止拍攝
stop();
if (mOnRecordFinishListener != null)
mOnRecordFinishListener.onRecordFinish();
}
}
}, 0, 1000);
}
//建立錄製檔案存放的資料夾以及錄製檔名稱
private void createRecordDir() {
File sampleDir = new File(Environment.getExternalStorageDirectory() + File.separator + "demo/video/");
if (!sampleDir.exists()) {
sampleDir.mkdirs();
}
File vecordDir = sampleDir;
// 建立檔案
try {
mRecordFile = File.createTempFile("example", ".mp4", vecordDir); //mp4格式
} catch (IOException e) {
//開啟檔案操作相關許可權
}
}
錄製時候切記要判斷下使用者攝像頭的許可權,假如使用者在錄製前關閉許可權會導致crash的問題,所以判斷下,防止誤操作的產生
7.停止錄製
//停止錄製
public void stop() {
stopRecord();
releaseRecord();
releaseCameraResource();
}
//停止錄製
public void stopRecord() {
mProgressBar.setProgress(0);
if (mTimer != null)
mTimer.cancel();
if (mMediaRecorder != null) {
// 設定後不會崩
mMediaRecorder.setOnErrorListener(null);
try {
mMediaRecorder.stop();
} catch (Exception e) {
return;
}
mMediaRecorder.setPreviewDisplay(null);
}
}
//釋放資源
private void releaseRecord() {
if (mMediaRecorder != null) {
mMediaRecorder.setOnErrorListener(null);
try {
mMediaRecorder.release();
} catch (Exception e) {
return;
}
}
mMediaRecorder = null;
}
停止錄製時候清空一些必要的資源,減輕App的負擔,停止時候記得設定錯誤監聽,做不做操作可以自己進行設定,但是一定要設定,否則系統不會回撥,直接異常。
8.相關的其他方法以及介面
public int getTimeCount() {
return mTimeCount;
}
public File getmRecordFile() {
return mRecordFile;
}
//錄製完成回撥介面
public interface OnRecordFinishListener {
public void onRecordFinish();
}
@Override
public void onError(MediaRecorder mr, int what, int extra) {
try {
if (mr != null)
mr.reset();
} catch (Exception e) {
//如果錄製有錯誤,需要做相關操作來提醒使用者
}
}
9.最後設定Activity就可以進行視訊錄製了
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#64000000">
<RelativeLayout
android:id="@+id/record_video"
android:layout_width="match_parent"
android:layout_height="70dp"
android:background="@color/common_black"
android:layout_alignParentBottom="true">
<Button
android:id="@+id/shoot_button"
android:layout_width="60dp"
android:layout_height="60dp"
android:layout_centerHorizontal="true"
android:layout_centerVertical="true"
android:background="@drawable/bg_movie_add" />
</RelativeLayout>
<com.demo.RecordVideo
android:id="@+id/movieRecorderView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_above="@id/record_video" />
</RelativeLayout>
Activity裡面按鈕處理程式碼,這裡主要需要主要需要onTouch進行監聽,因為可能會出現短暫的按下立馬鬆開,這樣是需要做處理的
mRecorderView = (RecordVideo) findViewById(R.id.movieRecorderView);
mShootBtn = (Button) findViewById(R.id.shoot_button);
mShootBtn.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
if (event.getAction() == MotionEvent.ACTION_DOWN) {
mRecorderView.record(new RecordVideo.OnRecordFinishListener() {
@Override
public void onRecordFinish() {
handler.sendEmptyMessage(1);
}
});
} else if (event.getAction() == MotionEvent.ACTION_UP) {
if (mRecorderView.getTimeCount() > 1)
handler.sendEmptyMessage(1);
else {
if (mRecorderView.getmRecordFile() != null) {
mRecorderView.getmRecordFile().delete();
}
mRecorderView.stop();
mRecorderView.initCamera();
Toast.makeText(RecordVideoActivity.this,"視訊錄製時間太短", Toast.LENGTH_SHORT).show();
}
}
}
}
private Handler handler = new Handler() {
@Override
public void handleMessage(Message msg) {
finishActivity();
}
};
private void finishActivity() {
if (isFinish) {
mRecorderView.stop();
// 返回到播放頁面
Intent intent = new Intent();
intent.putExtra("path", mRecorderView.getmRecordFile().getAbsolutePath());
setResult(RESULT_OK, intent);
}
finish();
}
這裡面可能會碰到的問題,在過程中已經描述了幾個需要注意的點,後面還有比較難搞的點就是許可權,這個可以參考下許可權檢查。
專案地址github
最後,歡迎討論的小夥伴。
個人郵箱: [email protected]
相關推薦
Android錄製小視訊(仿微信小視訊)
Android錄製小視訊 一、概述 日常生活中,錄製一些視訊已經漸漸成為一種習慣,當然這對於我們技術來說並沒有什麼影響,因為無論大家用不用,你都需要開發,這只是需求制定者–PM應該關心的事情,我們需要關心的是視訊開發的過程以及難點還有會碰上什麼坑,這才是技術
微信小程式--仿微信小程式朋友圈Pro(內容釋出、點贊、評論、回覆評論)
#### 微信小程式--仿微信小程式朋友圈Pro(內容釋出、點贊、評論、回覆評論) 專案開源地址[M朋友圈Pro 求個Star](https://gitee.com/Kindear/CloudUI) > 專案背景 基於原來的開源專案 [微信小程式仿朋友圈功能開發(釋出、點贊、評論等功能)](htt
Android 仿微信小視訊的錄製
這篇博文是借鑑下面這篇博文的,這篇播放對於整個專案的架構寫的比較清晰。這篇博文寫的很詳細,博主也是非常用心的分享自己的心得以及遇到的問題,希望對於想了解視訊錄製的博友們有所幫助。以上兩種方式都是使用原生的視訊錄製,所以檔案特別大,使用性不強,但是可以瞭解這樣一個技術,下面這個
21小時精通微信小程序開發(仿貓眼電影App、微信小程序問答)|微信小程序開發視頻教程
小程序開發 結構化 pan 即使 準備 ofo 入門 sha 小時 21小時精通微信小程序開發(仿貓眼電影App、微信小程序問答)網盤地址:https://pan.baidu.com/s/1GTpPX4A1U-w_3i6k7lLztQ 密碼: 5pcz備用地址(騰訊微雲):
-齊梟飛前端架構師 微信小程式--仿微信 QQ左劃事件--
廢話不多說,直接上程式碼: js: var app = getApp() Page({ data: { items: [], startX: 0, //開始座標 startY: 0 }, onLoad: func
「騰訊視訊」微信小程式外掛介紹
上期,我們在《從原理到應用,一文帶你瞭解小程式外掛能力》一文中介紹了小程式外掛的意義、作用以及應用。今天開始,我們會每期與大家分享一款優秀的小程式外掛,從使用場景到使用方法,都將作出詳細的介紹。 第一期與大家分享的小程式外掛,是「騰訊視訊」外掛。 「騰訊視訊」外
微信小程式仿微信語音
搞了這麼長時間,第一次寫文章。給大家分享個技術難度不高的,主要展示錄音功能。 先看一下效果 就是這樣,點選底部按鈕會產生變化,根據bind:touchstart在觸控時觸發開始錄音事件,根據bind:touchend會在你結束觸控的時候呼叫錄音結束事件,產生一個臨時url。並且根
同一個app不同activity顯示多工(仿微信小程式切換效果)
簡書地址:https://www.jianshu.com/p/a8f695841008 轉載請註明出處 如題,這種效果類似微信小程式顯示的效果,就是開啟微信跳一跳後,切換安卓多工視窗(就是清理記憶體視窗),會看到如下頁面 微信小程式會在其中顯示兩個單獨
店鋪無縫對接一號旺鋪小程序 盤點微信小程序新增功能
如何快速 被人 程序兼容 推送 模糊搜索 絕地反擊 作用 電商 通過 前段時間,筆者寫過一篇《不開發,商家店鋪如何快速接入微信一號旺鋪小程序》的文章。結果反響平平,無人問津。所以,筆者就在想,也許小程序真的大勢已去。 盤點迄今為止微信小程序增加的功能:價值提升,商家福音到
Android-通過SlidingMenu高仿微信6.2最新版手勢滑動返回(二)
word 代碼下載 extend ride 方法 最新版 roi library fin 轉載請標明出處: http://blog.csdn.net/hanhailong726188/article/details/46453627 本
android之使用GridView+仿微信圖片上傳功能(附源代碼)
相冊 ada nbu [] for round pen fromfile idt 由於工作要求最近在使用GridView完成圖片的批量上傳功能,我的例子當中包含仿微信圖片上傳、拍照、本地選擇、相片裁剪等功能,如果有需要的朋友可以看一下,希望我的實際經驗能對您有所幫助。
【小程序】微信小程序實現各種特效實例
負責 tab php 微信 點擊 space pic 效果圖 前後端 寫在前面 最近在負責一個微信小程序的前端以及前後端接口的對接的項目,整體上所有頁面的布局我都已經搭建完成,裏面有一些常用的特效,總結一下,希望對大家和我都能有所幫助 實例1:滾動tab選項卡 先看一下效果
【小程序】微信小程序之地圖功能
城市 comment olt delphi 天氣 posit truct 變量 綁定 轉載請註明出處:http://blog.csdn.net/crazy1235/article/details/55004841 基本使用 地圖組件使用起來也很簡單。 .wxml <m
[小程序開發] 微信小程序內嵌網頁web-view開發教程
工具 內容 不支持 clas .html bind har 開發 style 為了便於開發者靈活配置小程序,微信小程序開放了內嵌網頁能力。這意味著小程序的內容不再局限於pages和large,我們可以借助內嵌網頁豐富小程序的內容。下面附上詳細的開發教程(含視頻操作以及註意事
如何讓精準用戶知道我們的小程序?微信小程序帶給門店商家什麽?
IT 頁面 自身 無需 動態 電商 使用 互聯 源碼 在4月的騰訊“互聯網+”數字峰會上,微信透露了一個數據:能夠切實解決用戶痛點的小程序七日留存接近30%。而這類微信小程序基本都已經讓用戶完成了品牌認知,用戶會從微信任務欄或者歷史列表中主動找到它們,然後重復使用。 小程
【小程序】微信小程序綁定企業微信後怎樣獲取到用戶信息
臨時 ces code secret 企業微信 AC inf 小程序 ram 一、獲取access_token 1、https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=ID&corpsecret=SECRECT C
Okam(奧卡姆):小程式開發框架,支援百度小程式、微信小程式、支付寶小程式
Okam(奧卡姆):小程式開發框架,支援百度小程式、微信小程式、支付寶小程式 Okam 是什麼 `Okam` 一個面向小程式開發的開發框架,開發體驗類 `Vue`。詳情 Okam 對各小程式的支援情況 支援 百度小程式 支援 微信小程式 支援 支付寶小程式 Okam 提供
微信小程式-day02-微信小程式-框架-配置-pages、windows、tabBars、debug(json檔案)
1.pages(頁面路徑列表) "pages":[ "pages/index/index", "pages/do/do", "pages/eat/eat", "pages/logs/logs" ] 2.windows(全域性的預設視窗表現) "window":{
技術小白之微信小程式的圖片加文字連結
在多彩的圖片呈現下的程式必不可缺的便是文字的搭配,圖片勾起興趣,文字輔助表達,多數情況下我們上傳的圖片都需要在它周圍添上合適的標題,以便美觀和表述清晰。下面是簡單的圖片文字連結的截圖: 說到圖片和文字的連結就不得不理下思路:首先我想要在小程式內顯示圖片文字資訊,且在點選目標圖片或文字時,可
淺談支付寶小程式與微信小程式開發的區別
淺談支付寶小程式與微信小程式開發的區別 一、app.json (1)設定小程式通用的的狀態列、導航條、標題、視窗背景色 支付寶小程式 "window": { "defaultTitle": "病案到家", //頁面標題 "titleBarColor": "#1