Android MediaRecorder录像

基于Camera2和MediaRecorder实现视频录制 视频录制,在一般开发中很少遇到,大部分开发工作都是写写页面,请求接口,展示数据等等。真要遇到,可能采用第三方库实现,一来实现快速,二来可能觉得别人实现的比较好。特别是在开发周期很紧的情况下,一般都不会自己花时间实现。其实最好是使用手机系统的录制视频,功能完善,稳定。然后在onActiityResult方法中接收录制好的视频路径处理即可。但是,有时出于某些原因,比如不符合ui设计等等,不能使用系统自带录制功能,需要自己实现。下面将我自己实现的,记录下来。 阅读详情

近期小编正在做类似于朋友圈的功能,调用系统录像,华为机10s中就录出来41M,上传就要30-40s,测试提出BUG,产品提出需优化,小编在风中凌乱,没做过啊,,,近期终于完成需求,梳理一下,方便以后看。

一. 软编码和硬编码如何区分

软编码:使用CPU进行编码

硬编码:使用非CPU进行编码,如显卡GPU、专用的DSP、FPGA、ASIC芯片等

二. 软编码和硬编码比较

软编码:实现直接、简单,参数调整方便,升级容易,但CPU负载重,性能较硬编码低,低码率下质量通常比硬编码要好一点

硬编码:性能高,低码率下通常质量低于硬编码器,但部分产品在GPU硬件平台移植了优秀的软编码算(如X264)等,质量基于等同于软编码

三. 目前主流GPU加速平台

Intel、AMD、NVIDIA

四. 目前主流GPU平台开发框架

CUDA: NVIDIA的封闭编程框架,通过框架可以调用GPU计算资源

AMD APP: AMD为自己的GPU提出的一套通用并行编程框架,标准放开,通过在CPU、GPU同事支持OpenCL框架,进行计算力融合

OpenCL:开放计算语言,为异构平台编写程序的该框架,异构平台可包含CPU、GPU以及其他计算处理器,木匾是使用相同的计算能支持不同平台硬件加速。

Intel QuickSync: 集成Intel显卡中的专用视频编解码模块。

五. Android实现视频编码——H.264硬编码 硬编码 软编码

硬编码:通过调用Android系统自带的Camera录制视频,实际上是调用了底层的高清编码硬件模块,也即显卡,不适用CPU,速度快

软编码:使用CPU进行编码,如常见C/C++代码,一般编译生成的二进制都是的,速度相对较慢。例如使用AndroidNDK编译H264生成so库,编写jni接口,再使用java调用so库。

软编流程:camera采集YUV数据==>滤镜==>x264编码器机型编码==>MP4打包合成

硬编流程:采用手机提供的硬板接口,利用硬件芯片直接进行编码合成。

优点:速度快、效率高、CPU占用极少,及时长时间高清录制也不会发烫,同事由于使用系统API,库相对较少。

缺点:某些奇葩记性需要处理兼容性问题,同事Android上的硬编跟Surface以及OpenGL关系比较密切,网上相关知识较少,需要自己摸索采坑。

硬编的主要流程如下图所示,可以看到所有的数据,聪采集、编码、显示以及合成都在GPU里面进行流转。

​

软编:FFmpeg

硬编:MediaCodec、MediaMuxer

六. 录制方案:

1. 使用系统自带的MediaRecorder

坑:

1) Android不同机型,屏幕尺寸不同,支持显示视频的分辨率也不同,在设置MediaRecorder的VideoSize和Profile时,如果手机不支持,就会崩溃,在SurfaceView显示,Camera设置PreviewSize设置不正确时,会出现变形。

2)前置摄像头,录像VideoSize和系统的屏幕比例基本不一致,会导致我们录出来的视频会有变形,另外就是左右镜像问题,其实也能理解,前置摄像头就和后置摄像头一样是对着录制的,而朋友圈录像估计是做了镜像处理,类似直播的API,貌似现在小视频都有做翻转的

2. Google grafika

3. FFmpeg

七. 代码

https://github.com/CarGuo/VideoRecord

录像不太清楚,因为分辨率写死了是640*480的,手机VideoSize都支持,但是由于现在屏幕分辨率较高,导致拍完之后都不太清楚,另外就是一些变形的状况

https://github.com/chenzhihui28/VideoRecorderAndCompressor

1. 切换摄像头的时候,CameraPreview类会执行refreshCamera方法,期间会调用optimizeCameraDimens方法,这个时候获取到的mCamera.getParameters().getSupportedPreviewSizes()明显发生了变化,

2. 另外就是横屏的处理,每次拿着手机横屏录像,录像完了之后旋转了90度,需要改动代码:设置屏幕方向为portrait,变换屏幕方向不进行重绘,在CameraActivity中preprareMediaRecorder方法,之前的判断屏幕方向就不需要了,判断rotationRecord,竖着放,mediaRecorder设置OrientationHint,前置摄像头270,后置90,横着放,前后设置为0,横倒着放设置180

if (rotationRecord == 90) {
            mediaRecorder.setOrientationHint(cameraFront ? 270 : 90);
} else if (rotationRecord == 0) {
            mediaRecorder.setOrientationHint(cameraFront ? 0 : 0);
} else if (rotationRecord == 180) {
            mediaRecorder.setOrientationHint(cameraFront ? 180 : 180);
 }

   /**
     * 旋转前置摄像头为正
     */
    private void frontCameraRotate() {
        Camera.CameraInfo info = new Camera.CameraInfo();
        Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_FRONT, info);
        int degrees = getDisplayRotation(this);
        int result;
        if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
            result = (info.orientation + degrees) % 360;
            result = (360 - result) % 360; // compensate the mirror
        } else { // back-facing
            result = (info.orientation - degrees + 360) % 360;
        }
        frontOri = info.orientation;
        frontRotate = result;
    }

    /**
     * 获取旋转角度
     *
     * @param activity
     * @return
     */
    private int getDisplayRotation(Activity activity) {
        int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
        switch (rotation) {
            case Surface.ROTATION_0:
                return 0;
            case Surface.ROTATION_90:
                return 90;
            case Surface.ROTATION_180:
                return 180;
            case Surface.ROTATION_270:
                return 270;
        }
        return 0;
    }

    /**
     * 旋转界面UI
     */
    private void rotationUIListener() {
        orientationEventListener = new OrientationEventListener(this) {
            @Override
            public void onOrientationChanged(int rotation) {
                if (!recording) {
                    if (((rotation >= 0) && (rotation <= 30)) || (rotation >= 330)) {
                        // 竖屏拍摄
                        if (rotationFlag != 0) {
                            //旋转logo
                            rotationAnimation(rotationFlag, 0);
                            //这是竖屏视频需要的角度
                            rotationRecord = 90;
                            //这是记录当前角度的flag
                            rotationFlag = 0;
                        }
                    } else if (((rotation >= 230) && (rotation <= 310))) {
                        // 横屏拍摄
                        if (rotationFlag != 90) {
                            //旋转logo
                            rotationAnimation(rotationFlag, 90);
                            //这是正横屏视频需要的角度
                            rotationRecord = 0;
                            //这是记录当前角度的flag
                            rotationFlag = 90;
                        }
                    } else if (rotation > 30 && rotation < 95) {
                        // 反横屏拍摄
                        if (rotationFlag != 270) {
                            //旋转logo
                            rotationAnimation(rotationFlag, 270);
                            //这是反横屏视频需要的角度
                            rotationRecord = 180;
                            //这是记录当前角度的flag
                            rotationFlag = 270;
                        }
                    }
                }
            }
        };
        orientationEventListener.enable();
    }


    private void rotationAnimation(int from, int to) {
        ValueAnimator progressAnimator = ValueAnimator.ofInt(from, to);
        progressAnimator.setDuration(300);
        progressAnimator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
            @Override
            public void onAnimationUpdate(ValueAnimator animation) {
                int currentAngle = (int) animation.getAnimatedValue();
                buttonFlash.setRotation(currentAngle);
                textChrono.setRotation(currentAngle);
                buttonChangeCamera.setRotation(currentAngle);
            }
        });
        progressAnimator.start();
    }

3. 后置摄像头,我们可以采用最接近手机屏幕比例的,这样拍出来不会产生变形,CameraPreivew获取到ratio之后,获取摄像头参数的getSupportedVideoSizes(),选择最接近比例的,保存起来,在CameraActivity中获取,MediaRecorder参数设置:

Camera.Size videoSize = mPreview.getVideoSize();

mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);

mediaRecorder.setVideoFrameRate(15);

mediaRecorder.setVideoSize(videoSize.width, videoSize.height);

mediaRecorder.setVideoEncodingBitRate(3 * videoSize.width / 2 * videoSize.height / 2);

mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);

mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);

mediaRecorder.setMaxDuration(10 * 1000);

注意:设置编码setAudioEncorder和setVideoEncoder方法需放置在其他设置之后,比如放在设置帧率之前,会报错

4. 前置摄像头暂时没有找到好的解决方案,因为屏幕比例获取到之后,在获取摄像头getSupportedVideoList()时,能得到的一些尺寸设置会出问题,只能选择demo中720P和480P,但是依旧有变形和镜像问题,还需好好研究。

Android 多媒体 通过MediaRecorder+SurfaceView实现拍照,录像 1.拍照实现步骤: <1>界面使用SurfaceView控件,显示照相机的画面 <2>SurfaceView接受摄像头界面变化的信息 <3>重写三个方法 surfaceDestroyed—>当预览界面关闭时,触发 一般在这里执行销毁照相机的操作,释放内存 camera.stopPreview(); 阅读详情

相关推荐

硬编码和软编码区别 ?

硬编码:   硬编码就是直接将数据写入到代码中进行编译开发。在java开发中,如果我们没有使用MyBatis框架或者其它ORM框架前,我们使用原始的JDBC操作数据库时候,我们直接将sql语句嵌入到JDBC代码中;再比如jsp开发过程中,我们将前端html代码与java代码进行耦合。以上两种情况都是硬编码。 硬编码耦合度高,不利于模块拆分然后进行协同开发。同时由于硬编码是直接将操作数据的代码片段,或者读取配置文件片段嵌入到代码中,如果我们是C/S开发,我们每次更新数据操作方式和更新配置文件位置时候,都需要重

我写写哈的博客 4821

简单谈谈硬编码和软编码

工作中,经常被问硬编码、软编码怎么区分的问题,还是对这个问题整理一下吧。 一、软编码和硬编码如何区分        软编码:使用CPU进行编码        硬编码:使用非CPU进行编码,如显卡GPU、专用的DSP、FPGA、ASIC芯片等 二、软编码和硬编码比较        软编码:实现直接、简单,参数调整方便,升级易,但CPU负载重,性能较硬编码低,质量通常比硬编码要好。

charleslei的专栏 4万+

【49】Camunda8-Self-Managed部署之Docker方式

围绕camunda8 self-managed,介绍了基于Docker部署相关服务的过程。

AlieNeny的博客 1682

MediaRecorder setOrientationHint

为什么80%的码农都做不了架构师?>>> ...

weixin_33716941的博客 1916

CANOE DIVA 工程怎样在具体服务前增加前置条件

然后会在CANoe的Test Module视窗中发现一个跟系统条件相关的Test Module模块,在该模块中有生成跟系统条件相关的CAPL 脚本。这里需要根据你的实际项目进行更改,diva工程加载到canoe的工程的时候,会同步加入你创建的cdd文件,这里示例的ABS_ESP 就是你的cdd的ECU命名,后面就是具体的前置条件服务。4、配置完成后,测试用例就会如下图Trace窗口所示,在每一次10 02请求之前都会调用CAPL Function的PreconditionCheck函数中定义的脚本。

weixin_45940007的博客 1964

基于YOLOX与LPRNet的车牌检测与识别系统(Python+UI界面)实战指南

本文详细介绍了如何利用YOLOX目标检测模型与LPRNet车牌识别模型,从零构建一个完整的车牌检测与识别系统。通过解析CCPD数据集、训练深度学习模型,并最终集成到PyQt5开发的图形化UI界面中,提供了一个从数据处理到应用部署的完整实战指南,帮助开发者快速掌握智能交通系统中的关键技术。

weixin_29230901的博客 338

Android 开发 MediaRecorder视频录制入门

MediaRecorder是Android SDK提供用于录制音视频,关于音频的录制在我另一篇博客里已经介绍.传送门:,而这篇博客将介绍MediaRecorder视频录制的入门和一些MediaRecorder视频录制的深坑.为什么只介绍简单的录制视频的入门操作,因为MediaRecorder在实际开发的时候肯定还需要配合Camera来使用.而Camera这个大坑又有Camera1和Camera2,所以我们需要分篇幅来介绍Camera1和Camera2与MediaRecorder的使用方式.

zsy_2020的博客 2286

使用 Cynthion 与 Packetry 进行 USB 抓包与协议分析

Cynthion 是 Great Scott Gadgets 推出的USB 流量分析与注入设备。它具备以下特点:通过 FPGA 实现高速 USB 流量捕获;能够同时作为 USB Host 和 Device,进行调试和测试;支持输出 pcap 文件,可直接用 Wireshark 分析;提供 Python API,方便与上层软件联动。简单来说,Cynthion 是一个USB 协议分析仪 + 注入工具。硬件层捕获:实时拦截 USB 总线上的数据包;软件层解析。

YIMUleizi的博客 1263

mediarecoder 安卓_Android--MediaRecorder录音录像

前言Android除了支持播放多媒体文件之外,还可以从对应的硬件中捕获多媒体,比如从麦克风录音、从摄像头录像等。本篇博客讲解一下Android下如何通过MediaRecorder进行录音以及录像的步骤,最后将以简单的Demo演示。本篇博客的主要内容:MediaRecorderMediaRecorder主要用于记录音频与视频,它位于"android.media.MediaRecorder"下。它为开...

weixin_30421223的博客 281

WRF和WPS安装和编译时遇到的问题

检查是否自己netcdf和Fortran编译器一致。解决办法:修改configure.wps里的路径。如果没问题且wrf已成功编译,考虑重新。path修改为jasper在的路径。

m0_54898744的博客 1837

飞书+扣子+DeepSeek三件套:5分钟搞定公众号文章批量改写(附完整配置截图)

本文详细介绍了如何利用飞书、扣子和DeepSeek三款工具,无需编程即可搭建一个高效的公众号文章批量改写自动化工作流。通过飞书多维表格管理链接与成果,扣子平台串联整个流程,并调用DeepSeek智能体进行内容润色与改写,实现从内容抓取到智能处理的完整自动化,大幅提升新媒体运营效率。

python9snake的博客 208

android MediaRecorder的简单应用-录像

之前用MediaRecorder类实现了简单的录音demo,它还有录像功能,如下是一个简单的录像实现过程, 实现步骤跟录音录音大致一样,在此温习一遍: 第一步:实例化对象:mRecord = new MediaRecorder(); 第二步:设置输入源: 1、音频输入源:mRecord.setAudioSource(MediaRecorder.AudioSource.MIC);

Sunnyfans的专栏 8380

【Unity3D插件】XCharts插件完全教程《全网最全》-专栏文章目录

最近在做图表类需求功能的时候,发现了一款强大的Unity3D插件,也就是XCharts图表插件,功能强大,支持多种图表。官方介绍:一款基于UGUI的功能强大、简单易用的数据可视化图表插件。支持折线图、饼状图、饼图、雷达图、散点图、热力图、环形图、K线图、极坐标、平行坐标等十多种内置图表,以及3D饼图、3D金字塔、漏斗图、仪表盘、水位图、象形柱图、甘特图、矩形树图等拓展图表。内置丰富示例和模板,参数可视化配置,效果实时预览,纯代码绘制。支持折线图、柱状图、饼图、雷达图、散点图、热力图等常见图表。

优快云博客专家,Unity3D高级软件工程师,《Unity 3D从入门到实战》作者。 3196

安卓双摄像头录像_Android使用MediaRecorder和Camera实现视频录制及播放功能整理

package com.example.mediarecorder;import android.app.Activity;import android.hardware.Camera;import android.media.AudioManager;import android.media.MediaPlayer;import android.media.MediaRecorder;impor...

weixin_39520204的博客 840

YOLOv改进 | YOLOv11添加WTConv小波卷积,能够更有效地捕捉局部和全局特征

在计算机视觉目标检测领域,YOLO(You Only Look Once)系列算法凭借“单阶段检测”的高效性(一次前向传播同时完成目标定位与分类),已成为工业界与学术界的主流选择。从YOLOv1到YOLOv11,算法持续迭代优化,在速度与精度之间寻求平衡,广泛应用于自动驾驶、智能安防、工业质检等场景。为解决上述问题,本文提出一种基于,将输入特征图分解为不同频率的子带(低频全局信息与高频局部细节),并分别通过卷积操作提取局部与全局特征,最后融合多尺度特征,从而更有效地捕捉目标的局部细节与全局结构。

走向CTO的路上... 1248

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Android Cameara2 + MediaRecorder 完成录像功能

打开相机预览流程是Camera2的默认流程可参考:https://blog.csdn.net/kk3087961/article/details/135616576。

kk3087961的博客 1068

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

安卓双摄像头录像_android开发之调用手机的摄像头使用MediaRecorder录像并播放_Android_脚本之家...

我们玩玩手机的录像功能吧。做个DEMO。看看录制过程:复制代码 代码如下:mediarecorder = new MediaRecorder();// 创建mediarecorder对象// 设置录制视频源为Camera(相机)mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);// 设置录制完成后视频的封装格式THREE_...

weixin_39940788的博客 710

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

Android MediaRecorder录像功能

本文介绍了使用Android MediaRecorder进行音视频录制的基本流程:首先创建MediaRecorder实例并解锁相机;然后绑定相机设备,设置音频源为CAMCORDER,视频源为CAMERA;接着配置录制参数,包括MP4格式输出、H264视频编码(640*480比特率、25帧率、1280x720分辨率)和AAC音频编码;最后指定输出文件路径并启动录制。该流程涵盖了从初始化到开始录制的关键步骤,为Android音视频录制开发提供了基础实现方案。

shuiquan88的专栏 281

Android--MediaRecorder录音录像

前言   Android除了支持播放多媒体文件之外,还可以从对应的硬件中捕获多媒体,比如从麦克风录音、从摄像头录像等。本篇博客讲解一下Android下如何通过MediaRecorder进行录音以及录像的步骤,最后将以简单的Demo演示。    本篇博客的主要内容: MediaRecorderMediaRecorder录制音频MediaRecorder录制视频MediaRecord

萌萌的It人 www.itmmd.com 5422

android camera录像,android Camera拍照 及 MediaRecorder录像 预览图像差90度

Camera拍照:今天做照相机程序,结果写好了发现出问题了,预览的图像差90度。相关源代码如下:Camera.Parameters params = camera.getParameters();params.setPreviewSize(width,height);params.setPreviewFrameRate(4);params.setPictureFormat(PixelFormat....

weixin_31202821的博客 280

Android MediaRecorder录音录像 暂停 继续录音 播放 ARM格式(音频一)

Android MediaRecorder录音录像 暂停 继续录音 播放 ARM格式(音频一) https://blog.csdn.net/WHB20081815/article/details/88778605 Android 录音机小米商业项目开源代码 AudioRecord录音暂停 播放 Wav格式(音频二) https://blog.csdn.net/WHB20081815/arti...

深南大盗的博客 2291

Android--MediaRecorder实现手机录像

MediaRecorder实现手机录像 1.界面设计 2.实现代码 3.录像权限 1.界面设计(xxx.xml) 如图: <SurfaceView android:layout_width="match_parent" android:layout_height="400dp" android:id="@+id/sv_medi

qq_37465836的博客 681

安卓双摄像头录像_android开发之调用手机的摄像头使用MediaRecorder录像并播放

我们玩玩手机的录像功能吧。做个DEMO。看看录制过程:mediarecorder = new MediaRecorder();// 创建mediarecorder对象// 设置录制视频源为Camera(相机)mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);// 设置录制完成后视频的封装格式THREE_GPP为3gp.MP...

weixin_39621427的博客 356

Android多媒体-视频-MediaRecorder录像

早在在录制视频的过程中,如果设置的是不支持的分辨率或者Surface未创建成功,将会产生start failed异常,即在调用mMediaRecorder.start()时。MediaRecorder录像状态图。初始化MediaRecorder。以上可用于设置前后摄像头。

weixin_47145826的博客 438

Android-mediaRecorder(媒体录像器)实例

效果图如下: package com.example.android27_vedio;import android.media.MediaRecorder; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.view.SurfaceView; import androi

up的博客 588

【Android 10 源码】MediaRecorder 录像流程:MediaRecorder 配置

MediaRecorder 录像配置主要涉及输出文件路径、音频来源、视频来源、输出格式、音频编码格式、视频编码格式、比特率、帧率和视频尺寸等。 我们假设视频输入源来自 Camera,Camera2 API 将相机图像渲染到 MediaRecorder 提供的 Surface 上,而 MediaRecorder 将这个渲染数据编码为 H264。 /** * 配置录制视频相关数据 */ private void configMediaRecorder(){ F

洪伟的专栏 2494
上一篇: 分辨率、帧率和码率三者之间的关系
下一篇: Android 学习笔记
leverge2009
博客等级 码龄14年 34粉丝 18原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值