Android仿微信小视频录制功能

Android仿微信小视频录制功能

作为开博的第一篇文章,正好最近在学习Android视频录制功能,所以决定趁热记录下来。

关于Android视频录制功能的实现流程以及相关API的介绍网上有很多,这里就不再赘述。在学习的过程中主要参考了 Vitamio公司的VCamera SDK 项目,因为该项目在Java层全开源,所以在调用Android系统的相机进行录制方面记录下一些学习体会。

具体关于VCamera项目,请移步VCamera

嗯,还是先看效果:
这里写图片描述

定义

首先是定义视频录制接口,接口很简单只包含两个方法,因为是调用系统的API实现录制,所以在方法上只用考虑到start和stop方法,出于对功能的拓展性上(比如自定义相机功能),接口的方法还可以更丰富。

public interface IMediaRecorder {
   
    /**
     * 开始录制 
     * @return 录制失败返回null
     */
    public MediaObject startRecord();
    /**
     * 停止录制
     */
    public void stopRecord();
}

接着是bean:

    /** 视频最大时长,默认10秒 */
    private int mMaxDuration;
    /** 视频目录 */
    private String mOutputDirectory;
    /** 对象文件 */
    private String mOutputObjectPath;
    /** 视频码率 */
    private int mVideoBitrate;
    /** 最终视频输出路径 */
    private String mOutputVideoPath;
    /** 最终视频截图输出路径 */
    private String mOutputVideoThumbPath;
    /** 文件夹及文件名 */
    private String mKey;
    /** 开始时间 */
    private long mStartTime;
    /** 结束时间 */
    private long mEndTime;
    /** 视频移除标志位 */
    private boolean mRemove;

    /** 两个构造方法 */
    public MediaObject(String key, String path) {
        this(key, path, DEFAULT_VIDEO_BITRATE);
    }
    public MediaObject(String key, String path, int videoBitrate) {
        this.mKey = key;
        this.mOutputDirectory = path;
        this.mVideoBitrate = videoBitrate;
        this.mOutputObjectPath = mOutputDirectory + File.separator + mKey + ".obj";
        this.mOutputVideoPath = mOutputDirectory + File.separator + mKey +".mp4";
        this.mOutputVideoThumbPath = mOutputDirectory + File.separator + mKey + ".jpg";
        this.mMaxDuration = DEFAULT_MAX_DURATION;
    }

实现

在视频录制过程中分为两个部分,第一个就是我们在界面上看到的摄像头传来的预览画面Preview,另一个则是视频录制时使用的”录像机“Recorder,同样为了提高拓展性,在功能实现上我们先将预览画面提出来实现它。因为也许你有许多不同的Recorder,但是预览的方式只有那么一个。

那么抽象出一个录像父类非常重要,它实现了一些都需要用到的方法,其中当然包括我们的Preview

public abstract class MediaRecorderBase implements Callback, PreviewCallback, IMediaRecorder {
   ...}

非常直观哈,Callback接口是SurfaceHolder的回调接口,我们所看到的预览画面就是呈现在SurfaceView上的,PreviewCallback预览画面的回调接口,至于我们先前定义的IMediaRecorder就留给后人去实现吧。

回到主线预览画面上,关于SurfaceView这里不做介绍了,我们要做的是先把它的SurfaceHolder拿过来

    public void setSurfaceHolder(SurfaceHolder sh) {
        if (sh != null) {
            sh.addCallback(this);
            if (!DeviceUtils.hasHoneycomb()) {
                sh.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
            }
        }
    }

然后就可以掌控这一切了。。

    public void prepare() {
        mPrepared = true;
        if (mSurfaceCreated)
            startPreview();
    }
    @Override
    public void surfaceCreated(SurfaceHolder holder) {
        this.mSurfaceHolder = holder;
        this.mSurfaceCreated = true;
        if (mPrepared && !mStartPreview)
            startPreview();
    }
    @Override
    public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
        this.mSurfaceHolder = holder;
    }
    @Override
    public void surfaceDestroyed(SurfaceHolder holder) {
        release();
    }

startPreview()就是我们的预览方法:

/** 开始预览 */
    public void startPreview() {
        if (mStartPreview || mSurfaceHolder == null || !mPrepared)
            return;
        else
            mStartPreview = true;
        try {
            //打开镜头
            if (mCameraId == Camera.CameraInfo.CAMERA_FACING_BACK)
                camera = Camera.open();
            else
                camera = Camera.open(mCameraId);
            try {
                //为preview设置SurfaceHolder
                camera.setPreviewDisplay(mSurfaceHolder);
            } catch (IOException e) {
                if (mOnErrorListener != null) {
                mOnErrorListener.onVideoError(MEDIA_ERROR_CAMERA_SET_PREVIEW_DISPLAY, 0);
                }
                Log.e(" ", "setPreviewDisplay fail " + e.getMessage());
            }
            //获取摄像头参数
            Parameters parameters = camera.getParameters();
            prepareCameraParaments(parameters);
            setPreviewCallback(parameters);
            camera.setParameters(parameters);
            camera.startPreview();
            if (mOnPreparedListener != null)
                mOnPreparedListener.onPrepared();
        } catch (Exception e) {
            e.printStackTrace();
            if (mOnErrorListener != null) {
                mOnErrorListener.onVideoError(MEDIA_ERROR_CAMERA_PREVIEW, 0);
            }
            Log.e(" ", "startPreview fail :" + e.getMessage());
        }
    }

这里有几个方法依次说一下,首先是protected void prepareCameraParaments(Parameters parameters)调用它会对相机进行一些参数上的处理,里面基本包括:

List<int[]> supportedPreviewFpsRange = parameters.getSupportedPreviewFpsRange();

这里返回一个数组列表,里面包含了设备所支持预览画面的FPS值,每个数组含有两个值,第一个值是最小FPS,另一个是最大FPS值,这样就构成了一个区间,可以检测你所期望的FPS值在不在设备支持中。那么:

parameters.setPreviewFrameRate(mFrameRate);

接着,

List<Size> supportedPreviewSizes = parameters.getSupportedPreviewSizes();

这个返回了设备支持的预览画面的尺寸,Size有很多,但是重点在比例,16:9、4:3 、11:9等等,比例非常关键,它直接关系到后来我们的SurfaceView的尺寸,选一个你想要的把它:

parameters.setPreviewSize(customSize.width, customSize.height);

我们知道小视频录制的时候是竖屏的,所以把它竖过来是必须的:

camera.setDisplayOrientation(90);

顺时针旋转90度,之所以这么做,API文档上有介绍,大意就是camera sensor没有转,但是我们可以把画面转过来。
这样就可以了,当然如果想设置更多,当然没问题,这里的Parameters设置的参数实际上都是以Map键值对的形式传入的,具体的源码也有大神解读。那么,比如加一个防抖功能(前提是你的设备支持):

        if ("true".equals(parameters.get("video-stabilization-supported")))
            parameters.set("video-stabilization", "true");

再来看protected void setPreviewCallback(Parameters parameters)方法,作用呢就是给Camera对象设置我们一开始实现的那个PreviewCallback接口:

    protected void setPreviewCallback(Parameters parameters) {
        Camera.Size size = parameters.getPreviewSize();
        if (size != 
  • 32
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 103
    评论
您!要实现仿微信视频通话悬浮窗功能,您可以按照以下步骤进行操作: 1. 创建悬浮窗权限:在 AndroidManifest.xml 文件中添加悬浮窗权限声明,如下所示: ```xml <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> ``` 2. 创建悬浮窗服务:创建一个继承自 Service 的类,用于管理悬浮窗的创建、更新和移除等操作。在该类中,您可以使用 WindowManager 来显示悬浮窗,并监听触摸事件来实现拖拽和缩放等操作。 3. 设计悬浮窗布局:创建一个 XML 布局文件,用于定义悬浮窗的界面。您可以自定义界面元素,如视频画面、控制按钮等。 4. 实现悬浮窗功能:在悬浮窗服务类中,根据需要添加相应的逻辑。例如,您可以使用 MediaProjection API 来捕获屏幕内容,并将其显示在悬浮窗中;您还可以使用 Camera API 来获取摄像头数据,并实现视频通话功能。 5. 添加权限申请逻辑:在需要使用悬浮窗功能的地方,添加权限申请逻辑,以确保用户在安装应用时授予悬浮窗权限。 请注意,实现仿微信视频通话悬浮窗功能需要一定的 Android 开发知识和经验。如果您对 Android 开发不太熟悉,建议您先学习相关的基础知识,然后再尝试实现该功能。同时,还要注意遵守 Android 官方的开发规范和安全要求。希望对您有所帮助!如果您有其他问题,请随时提问。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 103
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值