Android 简单视频录制

1 视频播放

1.1 支持的视频格式

3GP(.3gp)和MPEG-4(.mp4),其中3GP是源自MPEG-4的视频标准,专门用于移动设备。Android支持H.263编解码器,这时一种旨在用于低延迟和低比特率视频会议应用程序的编解码器,MPEG-4和3GP文件都支持H.263视频,MPEG-4还支持H.264编解码器。

1.2 视频播放的基本使用

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical">

    <!-- MediaController设置播放使用 -->
    <LinearLayout
        android:id="@+id/media_root_view"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:orientation="vertical">

        <SurfaceView
            android:id="@+id/surface_view"
            android:layout_width="match_parent"
            android:layout_height="300dp" />

    </LinearLayout>

    <Button
        android:id="@+id/btn_record_video"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="录制视频" />

    <Button
        android:id="@+id/btn_stop_record_video"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="停止录制视频" />

    <Button
        android:id="@+id/btn_play_video"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="播放视频" />

</LinearLayout>


package com.example.media.video;

import android.content.pm.PackageManager;
import android.hardware.Camera;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.MediaRecorder;
import android.os.Bundle;
import android.os.Environment;
import android.support.annotation.Nullable;
import android.support.v7.app.AppCompatActivity;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.widget.Button;
import android.widget.MediaController;
import android.widget.Toast;

import com.example.media.R;

import java.io.File;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 *  简单录像功能
 */

public class SimpleRecordActivity extends AppCompatActivity implements SurfaceHolder.Callback,
        MediaPlayer.OnCompletionListener, MediaPlayer.OnErrorListener, MediaPlayer.OnPreparedListener,
        MediaPlayer.OnSeekCompleteListener, MediaPlayer.OnVideoSizeChangedListener, MediaPlayer.OnInfoListener,
        MediaController.MediaPlayerControl {
    private static final String TAG = SimpleRecordActivity.class.getSimpleName();

    private Button mBtnRecordVideo;
    private Button mBtnStopRecordVideo;
    private Button mBtnPlayVideo;

    private SurfaceHolder mSurfaceHolder;
    private MediaRecorder mMediaRecorder;
    private Camera mCamera;
    private MediaPlayer mMediaPlayer;
    private MediaController mMediaController;

    private String mRecordFilePath;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_simple_record);

        SurfaceView surfaceView = findViewById(R.id.surface_view);
        mSurfaceHolder = surfaceView.getHolder();
        mSurfaceHolder.addCallback(this);
        mSurfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); // 必须设置
        surfaceView.setFocusable(true);
        surfaceView.setClickable(true);
        surfaceView.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (mMediaController != null) {
                    if (mMediaController.isShowing()) {
                        mMediaController.hide();
                    } else {
                        mMediaController.show();
                    }
                }
            }
        });
        mMediaController = new MediaController(this);

        mBtnRecordVideo = findViewById(R.id.btn_record_video);
        mBtnStopRecordVideo = findViewById(R.id.btn_stop_record_video);
        mBtnPlayVideo = findViewById(R.id.btn_play_video);

        // 开始录像
        mBtnRecordVideo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                if (!isSupportCamera()) {
                    Toast.makeText(SimpleRecordActivity.this, "不支持录像功能", Toast.LENGTH_SHORT).show();
                    return;
                }

                if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                    Toast.makeText(SimpleRecordActivity.this, "请插入sd卡", Toast.LENGTH_SHORT).show();
                    return;
                }

                mBtnRecordVideo.setEnabled(false);
                mBtnStopRecordVideo.setEnabled(true);

                try {
                    mMediaRecorder = new MediaRecorder();
                    // 设置录像源(在setOutputFormat()之前设置)
                    mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER); // 音频源
                    mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 视频源
                    // 设置录制视频格式
                    mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
                    // 设置录像编码(在setOutputFormat()之后设置)
                    mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
                    mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.MPEG_4_SP);
                    // 设置录像参数(视频质量相关)
                    mMediaRecorder.setVideoSize(640, 480); // 设置视频分辨率
                    mMediaRecorder.setVideoFrameRate(30); // 设置视频帧率,1秒30帧
                    mMediaRecorder.setVideoEncodingBitRate(3 * 1024 * 1024); // 设置视频编码流,值越大,视频越清晰,当然视频越大
                    mMediaRecorder.setOrientationHint(90);
                    mMediaRecorder.setMaxDuration(30 * 1000); // 设置录制最大时长为30秒
                    mMediaRecorder.setPreviewDisplay(mSurfaceHolder.getSurface());

                    mRecordFilePath = getRecordFilePath();
                    if (mRecordFilePath != null) {
                        mMediaRecorder.setOutputFile(mRecordFilePath);
                        mMediaRecorder.prepare();
                        mMediaRecorder.start();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        // 停止录像
        mBtnStopRecordVideo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                mBtnRecordVideo.setEnabled(true);
                mBtnStopRecordVideo.setEnabled(false);
                mBtnPlayVideo.setEnabled(true);
                releaseMediaRecorder();
            }
        });

        // 播放
        mBtnPlayVideo.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                try {
                    if (mRecordFilePath == null) {
                        return;
                    }

                    mMediaPlayer = new MediaPlayer();
                    mMediaPlayer.setDataSource(mRecordFilePath);
                    mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);
                    mMediaPlayer.setDisplay(mSurfaceHolder); // 在SurfaceView播放录制的视频
                    mMediaPlayer.setOnCompletionListener(SimpleRecordActivity.this);
                    mMediaPlayer.setOnErrorListener(SimpleRecordActivity.this);
                    mMediaPlayer.setOnVideoSizeChangedListener(SimpleRecordActivity.this);
                    mMediaPlayer.setOnInfoListener(SimpleRecordActivity.this);
                    mMediaPlayer.setOnSeekCompleteListener(SimpleRecordActivity.this);
                    mMediaPlayer.setOnVideoSizeChangedListener(SimpleRecordActivity.this);
                    mMediaPlayer.prepare();

                    // 在MediaPlayer准备完毕后设置MediaController控制
                    mMediaController.setMediaPlayer(SimpleRecordActivity.this);
                    mMediaController.setAnchorView(findViewById(R.id.media_root_view));
                    mMediaController.setEnabled(true);
                    mMediaController.show();

                    mMediaPlayer.start();

                    mBtnRecordVideo.setEnabled(false);
                    mBtnStopRecordVideo.setEnabled(false);
                    mBtnPlayVideo.setEnabled(false);
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });

        mBtnRecordVideo.setEnabled(true);
        mBtnStopRecordVideo.setEnabled(false);
        mBtnPlayVideo.setEnabled(false);
    }

    private boolean isSupportCamera() {
        return getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA);
    }

    @Override
    protected void onDestroy() {
        releaseMediaRecorder();
        releaseMediaPlayer();
        releaseCamera();
        removeRecordFile();
        super.onDestroy();
    }

    private String getRecordFilePath() {
        // Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)
        // 保存应用程序相关联的图片和视频的标准位置,如果应用程序卸载,保存在此位置的媒体文件会被删除

        // 保存图片和视频标准、共享和推荐位置,可以让其他程序轻松发现、读取、更改、删除保存在此的文件
        // 用户卸载了应用程序,不会删除保存到此位置的媒体文件
        if (!Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
            return null;
        }

        File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
                "record");
        if (!mediaStorageDir.exists()) {
            if (!mediaStorageDir.mkdirs()) {
                Log.i(TAG, "failed to create directory");
                return null;
            }
        }

        String recordPath = mediaStorageDir.getPath() + File.separator + "record"
                + new SimpleDateFormat("yyyyMMddhhmmss", Locale.CHINA).format(new Date()) + ".mp4";
        Log.i(TAG, "record path = " + recordPath);
        return recordPath;
    }

    // SurfaceView创建时回调
    @Override
    public void surfaceCreated(SurfaceHolder surfaceHolder) {
        Log.i(TAG, "surfaceCreated");
        // 目前录制时摄像头会自动变为横屏,播放时是正常的竖屏播放
        try {
            mCamera = Camera.open();
            mCamera.setDisplayOrientation(90); // 竖屏录制 仅支持0 90 180 270四个角度
            mCamera.setPreviewDisplay(surfaceHolder);
            mCamera.startPreview();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    // SurfaceView的底层宽高或参数发生改变时回调
    @Override
    public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
        Log.i(TAG, "surfaceChanged");
        if (mCamera != null) {
            try {
                mCamera.stopPreview();
                mCamera.setPreviewDisplay(surfaceHolder);
                mCamera.startPreview();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

    // SurfaceView销毁时回调
    @Override
    public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
        Log.i(TAG, "surfaceDestroyed");
        removeRecordFile();
        finish();
    }

    // MediaPlayer播放完毕时回调
    @Override
    public void onCompletion(MediaPlayer mp) {
        Log.i(TAG, "onCompletion");
        releaseMediaPlayer();
        mBtnRecordVideo.setEnabled(true);
        mBtnPlayVideo.setEnabled(true);
    }

    // MediaPlayer播放错误时回调,如果同时实现了OnCompletionListener也会回调,此时调用reset()进行重置处理
    @Override
    public boolean onError(MediaPlayer mp, int what, int extra) {
        Log.i(TAG, "onError");
        if (what == MediaPlayer.MEDIA_ERROR_SERVER_DIED) {
            Log.v(TAG, "media error server died " + extra);
        } else if (what == MediaPlayer.MEDIA_ERROR_UNKNOWN) {
            Log.v(TAG, "media error unknown = " + extra);
        }
        mBtnPlayVideo.setEnabled(true);
        mBtnPlayVideo.setEnabled(true);
        return false; // 返回false不处理错误
    }

    // MediaPlayer准备完毕时回调
    @Override
    public void onPrepared(MediaPlayer mp) {
        Log.i(TAG, "onPrepared");
    }

    // MediaPlayer播放进度完毕时回调
    @Override
    public void onSeekComplete(MediaPlayer mp) {
        Log.i(TAG, "onSeekComplete");
    }

    // MediaPlayer大小发生改变时回调;同时,当指定数据源和读取视频的元数据后将至少调用它一次
    @Override
    public void onVideoSizeChanged(MediaPlayer mp, int width, int height) {
        Log.i(TAG, "onVideoSizeChanged");
    }

    @Override
    public boolean onInfo(MediaPlayer mp, int what, int extra) {
        Log.i(TAG, "onInfo");
        // 当出现关于播放媒体的特定信息或者需要发出警告时
        if (what == MediaPlayer.MEDIA_INFO_BAD_INTERLEAVING) {
            Log.v(TAG, "media info bad interleaving " + extra);
        }
        // 当媒体不能正确地定位时
        else if (what == MediaPlayer.MEDIA_INFO_NOT_SEEKABLE) {
            Log.v(TAG, "media info not seekable " + extra);
        }
        // 未知错误
        else if (what == MediaPlayer.MEDIA_INFO_UNKNOWN) {
            Log.v(TAG, "media info unknown " + extra);
        }
        // 当设备无法播放视频时将触发如下操作。这可能是将要播放视频,但是该视频太复杂或者码率过高
        else if (what == MediaPlayer.MEDIA_INFO_VIDEO_TRACK_LAGGING) {
            Log.v(TAG, "media info video track lagging " + extra);
        }
        // 当新的元数据可用时
        else if (what == MediaPlayer.MEDIA_INFO_METADATA_UPDATE) {
            Log.v(TAG, "media info metadata update " + extra);
        }

        return false;
    }

    // MediaController点击开始时回调
    @Override
    public void start() {
        if (mMediaPlayer != null) {
            mMediaPlayer.start();
        }
    }

    // MediaController点击暂停时回调
    @Override
    public void pause() {
        if (mMediaPlayer != null && mMediaPlayer.isPlaying()) {
            mMediaPlayer.pause();
        }
    }

    // MediaController获取视频时长
    @Override
    public int getDuration() {
        return mMediaPlayer != null ? mMediaPlayer.getDuration() : 0;
    }

    // MediaController获取当前视频播放位置
    @Override
    public int getCurrentPosition() {
        return mMediaPlayer != null ? mMediaPlayer.getCurrentPosition() : 0;
    }

    // MediaController进度条滑动时回调
    @Override
    public void seekTo(int pos) {
        if (mMediaPlayer != null) {
            mMediaPlayer.seekTo(pos);
        }
    }

    // MediaController判断是否在播放
    @Override
    public boolean isPlaying() {
        return mMediaPlayer != null && mMediaPlayer.isPlaying();
    }

    // MediaController获取缓冲百分比
    @Override
    public int getBufferPercentage() {
        return 0;
    }

    // MediaController是否可暂停
    @Override
    public boolean canPause() {
        return true;
    }

    // MediaController进度条回放
    @Override
    public boolean canSeekBackward() {
        return true;
    }

    // MediaController进度条快进
    @Override
    public boolean canSeekForward() {
        return true;
    }

    // MediaController获取音频SessionId
    @Override
    public int getAudioSessionId() {
        return 0;
    }

    private void releaseMediaRecorder() {
        if (mMediaRecorder != null) {
            mMediaRecorder.stop();
            mMediaRecorder.release();
            mMediaRecorder = null;
        }
    }

    private void releaseCamera() {
        if (mCamera != null) {
            mCamera.lock(); // 锁定摄像头给其他应用使用
            mCamera.stopPreview();
            mCamera.release();
            mCamera = null;
        }
    }

    private void releaseMediaPlayer() {
        if (mMediaPlayer != null) {
            mMediaPlayer.stop();
            mMediaPlayer.release();
            mMediaPlayer = null;
        }
    }

    private void removeRecordFile() {
        if (mRecordFilePath != null) {
            if (new File(mRecordFilePath).delete()) {
                Log.v(TAG, "record file is deleted");
            }
        }
    }
}

2 网络视频

2.1 支持的网络视频类型

  • HTTP

由于HTTP在网络上得到了广泛的支持,通常不会遭遇与其他流式协议一样的防火墙问题,因此大量的媒体以这种方式可用。通过HTTP传输的媒体通常以称为累进式的方式下载。Android支持MPEG-4和3GP文件中的点播媒体,这些文件通过HTTP从标准Web服务器上传输。

当准备通过累进式下载传输视频时,需要铭记几件事情:

必须使用编解码器及Android支持的格式对媒体进行编码。
视频的比特率应在携带视频的网络所能够传输的范围之内。

例如,GPRS的带宽可能会低到20kbps,因此在编码音频和视频时应该考虑到这一点。一般而言,当通过HTTP传输时,媒体将在设备上缓冲,当已经下载了足够的内容时才开始播放,此时应该能够播放到文件结束,而不用停顿下来等待下载更多的媒体。如果媒体的传输只有20kbps,而媒体以400kbps的比特率编码,那么这意味着对于每秒钟的视频,用户必须持续下载20秒。这可能不会很理想。
然而,如果用户在WiFi上传输,那么400kbps可能会比较好,与编码成20kbps的视频相比,它将提供效果更佳的视频。一般而言,待使用的网络速度必须根据视频的质量进行权衡。使用HTTP累进式下载的优势在于:媒体不必与RTSP一样实时传输。

为了在视频正在下载时播放它,必须以允许这么做的方式对它进行编码。具体而言,这意味着结果文件应该在文件的开头包含称为“moov原子”的内容。“moov原子”包含一个关于文件内容及组织方式的索引。为了使视频播放软件能够开始播放该视频,它需要知道这个信息。如果“moov原子”位于文件的末尾,那么播放软件只有在下载整个文件之后才能启动播放,因此此时它才可以得到“moov原子”。

  • RTSP

RTSP是指实时流协议(Real Time Streaming Protocol),从技术上讲,它不是一个媒体传输协议,相反,它是一个用于支持媒体传输的控制协议。在Android中通过RTSP支持的媒体传输形式是RTP(实时传输协议,Real Time Transport Protocol),但是它只有在与RTSP一起使用时才有效。换句话说,Android上的RTP不能独立于RTSP工作。
RTSP和RTP是特定于实时数据流的。这完全不同于HTTP累进式下载,因为它可以在通过网络接收媒体时对其进行播放。
当准备用RTSP传输媒体时,需要铭记几件事情:

  • 需要使用编解码器及Android支持的格式对媒体进行编码,并且其可以通过RTSP服务器流媒体化。虽然支持其他的编解码器(H.264)和容器(MP4),但是一般会将移动设备的流媒体编码为在3GP容器中的MP4视频和AAC音频。

  • 媒体的比特率必须可以实时传输给最终用户,这取决于用户的网络连接。根据网络类型,这些速度会有很大的不同。第二代网络(GPRS)提供的数据速度最高在50~100kbps的范围之内。为了将视频编码成可在这种类型的网络上实时地传输,需要将视频编码在30kbps的范围以内,以考虑额外系统开销和不同的连接质量。向上升级到EDGE网络将允许在50kbps的范围内可靠地传输视频,当前3G网络的保守比特率将在100kbps的范围内,而许多网络能够支持显著较高的比特率。

2.2 在加载网络视频时获取缓冲信息

MediaPlayer.OnBufferingUpdateListener接口在处理网络传输的媒体时特别有用,onBufferingUpdate(MediaPlayer mp, int
bufferedPercent),当缓冲媒体时会重复调用该方法,从而能够跟踪缓冲区的填充程度。

2.3 视频捕获(MediaRecorder,设置音频相关的请查看音频文档)

使用MediaRecorder捕获视频步骤如下(每步调用的执行顺序不同对结果影响非常大):

  • 创建MediaRecorder实例

  • 设置音频源和视频源

MediaRecorder.setVideoSource(MediaRecorder.VideoSource.DEFAULT)
  • 设置输出格式
MediaRecorder.setOutputFormat(MediaRecorder.OutputFormat. DEFAULT)
  • 设置音频和视频编码器
MediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT)
  • 设置输出文件
MediaRecorder.setOutputFile(filePath)
  • 准备录制
MediaRecorder.prepare()
  • 开始录制
MediaRecorder.start()
  • 重置/停止
MediaRecorder.reset()/MediaRecorder.stop()
  • 释放资源
MediaRecorder.release()

视频源

  • CAMERA:使用摄像头录制视频

  • DEFAULT:使用摄像头录制视频

输出格式

  • DEFAULT:指定使用默认的输出格式。默认的输出格式可能会根据设备的不同而有所区别。

  • MPEG-4:指定音频和视频将捕获到一个MPEG-4文件格式的文件中。这个文件是一个.mp4文件。MPEG-4文件通常包含H.264、H.263或MPEG-4 Part 2编码的视频,以及AAC或MP3编码的音频。

  • RAW_AMR:此设置仅用于音频录制,而不用于视频。

  • THREE_GPP:指定音频和视频将被捕获到一个3GP文件格式的文件中。这个文件将是一个.3gp文件。3GP文件通常包含使用H.264、MPEG-4 Part 2或H.263编解码器编码的视频和使用AMR或AAC编解码器编码的音频。

视频编解码器

  • DEFAULT:这时一个设备相关的设置,指定使用设备的默认编解码器。在大多数情况下是H.263,因为它是Android上唯一必须
    支持的编解码器。

  • H263:这个值指定使用的编解码器是H.263。H.263是在1995年发布的编解码器,专门为低比特率视频传输而开发。

  • H264:这个值指定使用的编解码器是H.264(它还被命名为MPEG-4 Part 10或AVC(高级视频编码))。H.264是当前最先进的编解码器,它在2003年发布。大多数Android设备支持使用这种编解码器进行视频播放,而小部分设备使用它进行视频编码。

  • MPEG_4_SP:这个值指定使用的编解码器是MPEG-4 SP(Simple Profile,简单配置)编解码器。从技术上讲,MPEG-4 SP是MPEG-4 Part 2 Simple Profile。它在1999年发布,为需要低比特率视频且不需要大量处理器能力的技术而开发。

音频和视频比特率

MediaRecorder.setVideoEncodingBitRate(150000);
MediaRecorder.setAudioEncodingBitRate(8000);

比特率以位/秒为单位。视频的低比特率设置在256000位/秒(256kbps)范围之内,而高比特率视频在3000000位/秒(3mbps)范围之内。

8000位/秒(8kbps)是一个非常低的比特率,适合于需要在慢速网络上实时传输的音频;196000位/秒(196kbps)和更高的比特率在MP3文件的音乐中很常见。目前大多数Android设备只支持低端的比特率。

音频采样率

MediaRecorder.setAudioSampleRate(8000);

传入的采样率以Hz为单位,其标识每秒采样的数量。采样率越高,则在捕获文件中可以表示的音频频率的范围越大。一个低端
的采样率8000Hz适合于捕获低质量的声音;而高端的采样率48000Hz可用于DVD和许多其他高质量的视频格式。大多数Android
设备只支持低范围的采样率(8000Hz)。

音频通道

MediaRecorder.setAudioChannels(1);

传入通道数量指定捕获的音频通道数量,传入的音频大多数限制为单一通道麦克风,因此使用一个以上的通道不会有益处。对
于选择要使用的通道数量,一般是单声道为一个通道,而立体声为两个通道。

视频帧速率

MediaRecorder.setVideoFrameRate(15);

传入请求的帧速率来控制每秒钟捕获的视频帧数。每秒12~15帧之间的值通常足以表示运动。对于高端而言,电视是每秒30帧。
具体使用的实际帧速率将取决于设备的能力。

视频大小

MediaRecorder.setVideoSize(640, 480);

传入标识宽度和高度像素的整数来控制捕获的视频宽度和高度。标准大小的范围是176 x 144 ~ 640 x 480,许多设备甚至支持更
高的分辨率。

最大文件大小

MediaRecorder.setMaxFileSize(10000000);//10MB

以字节为单位将设置最大文件大小。可以通过实现MediaRecorder.OnInfoListener的OnInfo(MediaRecorder mr, int what, int extra)判断标志what == MediaRecorder.RECORDER_INFO_FILESIZE_REACHED检查,达到最大文件大小时应该显示调用
MediaRecorder.stop()停止录制。

最长持续时间

MediaRecorder.setMaxDuration(10 * 1000); // 10秒

以毫秒为单位设置最长持续时间。可以通过MediaRecorder.OnInfoListener的OnInfo(MediaRecorder mr, int what, int extra)判断标志what == MediaRecorder.MEDIA_RECORDER_INFO_DURATION_REACHED检查,达到最长持续时间应该显示调用
MediaRecoder.stop()停止录制。

概要

MediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));

从Android.2.2开始,MediaRecorder有一个setProfile()方法,其接受一个CamcorderProfile实例作为参数。CamcorderProfile有一个静态方法CamcorderProfile.get(),它接受一个整数参数。使用该方法将允许根据预设值设置整个配置变量集合。

CamcorderProfile.QUALITY_HIGH:高质量视频捕获设置。相关配置如下:

  • 音频比特率:12200位/秒

  • 音频通道:1

  • 音频编解码器:AMR-NB

  • 音频采样率:8000Hz

  • 持续时间:60秒

  • 文件格式:MP4

  • 视频比特率:3 000 000 位/秒

  • 视频帧宽度:720像素

  • 视频帧高度:480像素

  • 视频帧速率:24帧/秒

CamcorderProfile.QUALITY_LOW:低质量视频捕获设置。相关配置如下:

  • 音频比特率:12200位/秒

  • 音频通道:1

  • 音频编解码器:AMR-NB

  • 音频采样率:8000Hz

  • 持续时间:30秒

  • 文件格式:3GPP

  • 视频比特率:256 000 位/秒

  • 视频帧宽度:176像素

  • 视频帧高度:144像素

  • 视频帧速率:15帧/秒

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值