RecorderManager安卓仿微信自定义音视频录制

因为在项目中经常需要使用音视频录制,所以写了一个公共库RecorderManager,欢迎大家使用。

一.效果展示

仿微信界面视频录制

图片描述
图片描述

2.音频录制界面比较简单,就不放图了

二.引用

1.Add it in your root build.gradle at the end of repositories

allprojects {
        repositories {
            ...
            maven { url 'https://jitpack.io' }
        }
    }

2.Add the dependency

dependencies {
            implementation 'com.github.MingYueChunQiu:RecorderManager:0.2.3'
    }

三.使用

1.音频录制

采用默认配置录制

mRecorderManager.recordAudio(mFilePath);

自定义配置参数录制

mRecorderManager.recordAudio(new RecorderOption.Builder()
                    .setAudioSource(MediaRecorder.AudioSource.MIC)
                    .setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
                    .setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
                    .setAudioSamplingRate(44100)
                    .setBitRate(96000)
                    .setFilePath(path)
                    .build();

2.视频录制

(1).可以直接使用RecordVideoActivity,实现了仿微信风格的录制界面

                startActivity(new Intent(MainActivity.this, RecordVideoActivity.class));

通过在Intent中传入下列参数来设置路径和最长时间

                //设置视频录制的最长时间
                intent.putExtra(MediaStore.EXTRA_DURATION_LIMIT, 20);
                //设置视频录制的画质
                intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);

RecordVideoActivity里已经配置好了默认参数,可以直接使用,然后在onActivityResult里拿到视频路径的返回值

@Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == Activity.RESULT_OK && requestCode == 0) {
            Log.e("onActivityResult", "onActivityResult: " + " " + data.getStringExtra(EXTRA_RECORD_VIDEO_FILE_PATH) + " " +
                    data.getIntExtra(EXTRA_RECORD_VIDEO_DURATION, -1));
        }
    }

(2).如果想要界面一些控件的样式,可以继承RecordVideoActivity,里面提供了几个protected方法,可以拿到界面的一些控件

/**
     * 获取计时控件
     *
     * @return 返回计时AppCompatTextView
     */
    protected AppCompatTextView getTimingView() {
        return mRecordVideoFg == null ? null : mRecordVideoFg.getTimingView();
    }

    /**
     * 获取圆形进度按钮
     *
     * @return 返回进度CircleProgressButton
     */
    protected CircleProgressButton getCircleProgressButton() {
        return mRecordVideoFg == null ? null : mRecordVideoFg.getCircleProgressButton();
    }

    /**
     * 获取播放控件
     *
     * @return 返回播放AppCompatImageView
     */
    protected AppCompatImageView getPlayView() {
        return mRecordVideoFg == null ? null : mRecordVideoFg.getPlayView();
    }

    /**
     * 获取取消控件
     *
     * @return 返回取消AppCompatImageView
     */
    protected AppCompatImageView getCancelView() {
        return mRecordVideoFg == null ? null : mRecordVideoFg.getCancelView();
    }

    /**
     * 获取确认控件
     *
     * @return 返回确认AppCompatImageView
     */
    protected AppCompatImageView getConfirmView() {
        return mRecordVideoFg == null ? null : mRecordVideoFg.getConfirmView();
    }

    /**
     * 获取返回控件
     *
     * @return 返回返回AppCompatImageView
     */
    protected AppCompatImageView getBackView() {
        return mRecordVideoFg == null ? null : mRecordVideoFg.getBackView();
    }

想要替换图标资源的话,提供下列名称图片

record_video_cancel.png
record_video_confirm.png
record_video_play.png
record_video_pull_down.png

(3).同时提供了对应的RecordVideoFragment,实现与RecordVideoActivity同样的功能,实际RecordVideoActivity就是包裹了一个RecordVideoFragment

1.创建RecordVideoFragment

/**
     * 获取录制视频Fragment实例(使用默认配置项)
     *
     * @param filePath 存储文件路径
     * @return 返回RecordVideoFragment
     */
    public static RecordVideoFragment newInstance(String filePath) {
        return newInstance(filePath, 30);
    }

    /**
     * 获取录制视频Fragment实例(使用默认配置项)
     *
     * @param filePath    存储文件路径
     * @param maxDuration 最大时长(秒数)
     * @return 返回RecordVideoFragment
     */
    public static RecordVideoFragment newInstance(String filePath, int maxDuration) {
        return newInstance(new RecordVideoOption.Builder()
                .setRecorderOption(new RecorderOption.Builder().buildDefaultVideoBean(filePath))
                .setMaxDuration(maxDuration)
                .build());
    }

    /**
     * 获取录制视频Fragment实例
     *
     * @param option 录制配置信息对象
     * @return 返回RecordVideoFragment
     */
    public static RecordVideoFragment newInstance(RecordVideoOption option) {
        RecordVideoFragment fragment = new RecordVideoFragment();
        fragment.mOption = option;
        if (fragment.mOption == null) {
            fragment.mOption = new RecordVideoOption();
        }
        if (fragment.mOption.getRecorderOption() == null && fragment.getContext() != null) {
            File file = fragment.getContext().getExternalFilesDir(Environment.DIRECTORY_MOVIES);
            if (file != null) {
                fragment.mOption.setRecorderOption(new RecorderOption.Builder().buildDefaultVideoBean(
                        file.getAbsolutePath() +
                                File.separator + System.currentTimeMillis() + ".mp4"));
            }
        }
        return fragment;
    }

2.然后添加RecordVideoFragment到自己想要的地方就可以了
3.可以设置OnRecordVideoListener,拿到各个事件的回调

public class RecordVideoOption:
     private RecorderOption option;//录制配置信息
    private int maxDuration;//最大录制时间
    private OnRecordVideoListener listener;//录制视频监听器

    /**
     * 录制视频监听器
     */
    public interface OnRecordVideoListener {
 /**
         * 当完成视频录制时回调
         *
         * @param filePath      视频文件路径
         * @param videoDuration 视频时长(毫秒)
         */
        void onCompleteRecordVideo(String filePath, int videoDuration);

        /**
         * 当点击返回按钮时回调
         */
        void onClickBack();
    }

(4).如果想自定义自己的界面,可以直接使用RecorderManager类

1.创建RecorderManager实例

public class RecorderManager implements RecorderManagerable

/**
     * 创建录制管理类实例(使用默认录制类)
     *
     * @return 返回录制管理类实例
     */
    public static RecorderManagerable newInstance() {
        return new RecorderManager(new RecorderHelper());
    }

    /**
     * 创建录制管理类实例
     *
     * @param recorderable 实际录制类
     * @return 返回录制管理类实例
     */
    public static RecorderManagerable newInstance(Recorderable recorderable) {
        return new RecorderManager(recorderable);
    }

它们返回的都是RecorderManagerable 接口类型,RecorderManager 是默认的实现类,RecorderManager 内持有一个真正进行操作的Recorderable。

Recorderable是一个接口类型,由实现Recorderable的子类来进行录制操作,默认提供的是RecorderHelper,RecorderHelper实现了Recorderable。

public interface Recorderable {

    boolean recordAudio(String path);

    boolean recordAudio(RecorderOption bean);

    boolean recordVideo(Camera camera, Surface surface, String path);

    boolean recordVideo(Camera camera, Surface surface, RecorderOption bean);

    void release();

    MediaRecorder getMediaRecorder();
}

2.拿到后创建相机对象

if (mCamera == null) {
            mCamera = mManager.initCamera();
        }
        try {
            mCamera.setPreviewDisplay(svVideoRef.get().getHolder());
            mCamera.startPreview();
            mCamera.unlock();
        } catch (IOException e) {
            e.printStackTrace();
        }

3.录制

isRecording = mManager.recordVideo(mCamera, svVideoRef.get().getHolder().getSurface(), mOption.getRecorderOption());

4.释放

            mManager.release();
            mManager.releaseCamera(mCamera);
            mCamera = null;

四.总结

目前来说,大体流程就是这样,更详细的信息请到Github上查看, 后期将添加摄像头切换、闪光灯等更多功能,敬请关注,github地址为 https://github.com/MingYueChunQiu/RecorderManager,码云地址为 https://gitee.com/MingYueChunQiu/RecorderManager ,如果它能对你有所帮助,请帮忙点个star,有什么建议或意见欢迎反馈。

大纲与资料.png

高清视频资料.jpg

+qq群:853967238。获取以上高清技术思维图,以及相关技术的免费视频学习资料

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,980评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,178评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,868评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,498评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,492评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,521评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,910评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,569评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,793评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,559评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,639评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,342评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,931评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,904评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,144评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,833评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,350评论 2 342

推荐阅读更多精彩内容

  • 清晨睡意朦胧的我 没有等待阳光关顾 你,便是我睁眼最后的防线 踩着不愿意的脚步 迷糊的坐在车上 没有什么的特殊理由...
    蝉翼呵呵阅读 254评论 0 2
  • 你在那里, 我在这里。 你和我之间, 可不可以没有距离……… 你说可以, 我说可以。 就这样, 你和我在一起, 永...
    小剧在成长阅读 244评论 2 8
  • 买这本书时,并不知道讲的都是些我们认为的精神病患者的案例,但当自己拿起这本书开始读的时候,却发现,有些想法自己竟...
    小东记事阅读 457评论 0 1
  • 加入组织前,心心念念有这样的组织才能坚持下去。当真的跟老师说了之后发现自己竟开始后悔,总觉得自己根本坚持不了嘛。但...
    漠翊阅读 222评论 5 1