Android音视频系列(一):基本概念扫盲

版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/u011315960/article/details/96862786

前言

已经快两个月没写博客了,最近换了工作,之前一直想研究研究音视频方面的东西,终于有机会实现了,所以最近会一直写这个系列。我也是刚刚摸索了一段时间,有什么问题大家一起讨论指正。

第一篇是概念扫盲篇,如果不知道一些常用的API之后必然很难下手。

正文

由于FFmpeg特别的火,所以我一直认为音视频和Android原生的API关系不大,其实这种理解是错误的,FFmpeg的优势是解决了Android不同版本的API性能差距和问题,尽量在不同机型上达到性能相近的效果,第三方库的更新肯定要比系统版本更新方便多了。

所以如果对原生的API有了熟练的掌握,过度到FFmpeg就都是小问题了。今天我们了解一些常用的API的概念。

MediaPlayer

音视频播放的上层API,可以用来播放音频和视频文件,特别常用的API。

// 创建MediaPlayer
 val mediaPlayer = MediaPlayer()
 // 设置要播放的文件路径
 mediaPlayer.setDataSource(path)
 // 准备
 mediaPlayer.prepare()
 // 播放
 mediaPlayer.start()

还有一些暂停,停止的方法,这里就不介绍了,相信大家都用过。

MediaRecoder

音视频录制的上层API,通过一些简单的配置,就可以直接录制音视频保存到指定的文件路径。

// 创建MediaRecorder
val mediaRecorder = MediaRecorder()
// 录制声音的来源,具体参考AudioSource
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
// 录制视频的来源
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE)
// 输出的文件编码格式
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
// 保存的文件路径 
mediaRecorder.setOutputFile(videoRecorderFile)

// 设置录音编码器
// 注意设置的录制音频编码格式与视频的编码格式是否匹配
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB)
// 音频录制的其他设置
mediaRecorder.setAudioEncodingBitRate(60)
mediaRecorder.setAudioSamplingRate(14400)
// 视频录制的其他设置
mediaRecorder.setVideoSize(getScreenWidth(), getScreenHeight())
mediaRecorder.setVideoEncodingBitRate(2 * getScreenWidth().times(getScreenHeight()))
mediaRecorder.setVideoFrameRate(60)
mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264)
mediaRecorder.prepare()
mediaRecorder.start()

// 停止录制
mediaRecorder!!.stop()
mediaRecorder!!.release()

都是基本的配置,不过如果是录制视频一般要和Surface一起使用,从摄像头中得到录制的内容,MediaRecorder也有对应的方法设置:

// 设置摄像头
mediaRecorder.setCamera(camera!!)
// 设置录制的角度,如果与摄像头不符,会出现视频角度不对的问题
mediaRecorder.setOrientationHint(90);
// 设置录音和录制视频的来源
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER)
mediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA)
 // 设置录制的质量
mediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH))
....

网上有很多Demo,大家可以去搜索一下,之后我们也会自己写一写Demo。

AudioRecord

音频录制的API,通过流的形式输出的音频数据是未经过编码的,也就是PCM原数据,所以直接保存录制出的内容是无法直接使用播放器进行播放。

// 创建AudioRecord
AudioRecord(
			// 录制音频的来源,参数与MediaRecoder相同
            AudioSource,
            // 采样率,
            sampleRateInH,
            // 声音的频道
            CHANNEL,
            // 编码位数
            ENCODING,
            // 录制一帧的最小Buffer大小
            AudioRecord.getMinBufferSize(
                sampleRateInH,
                CHANNEL,
                ENCODING
            )
 )

可以看出,AudioRecorder相比MediaRecoder要更加细致,如果你有对音频有一些特殊的处理,例如变声,就需要使用到AudioRecorder,然后再自己编码保存。

然后我们再了解一下构造方法中的参数:

AudioSource:录制的声音来源,跟MediaRecoder是一样的。
·
sampleRateInH:采样率,通俗的讲采样频率是指计算机每秒钟采集多少个信号样本,单位是Hz。越高声音肯定是越清晰,常用的大小有:
8000Hz 电话所用采样率,对于人的说话已经足够
11025Hz 获得的声音称为电话音质,基本上能让你分辨出通话人的声音
22050Hz 无线电广播所用采样率,广播音质
32000Hz miniDV数码视频camcorder、DAT(LPmode)所用采样率
44100Hz 音频CD,也常用于MPEG-1音频(VCD,SVCD,MP3)所用采样率
47250Hz NipponColumbia(Denon)开发的世界上第一个商用PCM录音机所用采样率
48000Hz miniDV、数字电视、DVD、DAT、电影和专业音频所用的数字声音所用采样率
.
CHANNEL:就是视频的立体声,左声道,右声道
.
ENCODING:这个编码指的是保存的位数,一般使用16位。
.
AudioRecord.getMinBufferSize:每一帧的最小大小,如果是读操作,就要用到它。

MediaCodec

音视频的编码和解码器,应该是这个系列最重要的API了,为了配合他的使用,还得用到MediaFormat等其他的API。

// 这里仅仅是一个简单的例子,MediaCodec的使用要更复杂一些
// 创建一个avc格式的视频编码器
mediaCodec = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC)
// 详细配置MediaFormat
val mediaFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, width, height)
mediaFormat.setInteger(MediaFormat.KEY_BIT_RATE, 125000)
mediaFormat.setInteger(MediaFormat.KEY_FRAME_RATE, 15)
mediaFormat.setInteger(
          MediaFormat.KEY_COLOR_FORMAT,
          MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface
)
mediaFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 5)
// 使用配置好的MediaFormat
mediaCodec!!.configure(mediaFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE)
// 开始编码
mediaCodec!!.start()

在实际应用中,MediaCodec的使用要更加复杂一些,这里只是先简单了解,之后的案例中我们再慢慢分析。

MediaExtractor

音视频分提取器,例如把某视频文件中的音频提取出来保存成一个音频文件。

// 创建一个分离器,还没有指定要分离的部分
val mediaExtractor = MediaExtractor()
// 文件路径
mediaExtractor.setDataSource(file.absolutePath)
// trackCount表示有多少可以分离的轨道,常用的音轨和视轨
val trackNum = mediaExtractor.trackCount
for (i in 0 until trackNum) {
	  // 对应轨道的格式
      val mediaFormat = mediaExtractor.getTrackFormat(i)
      // 音频:“audio/”,视频:“video/”
      val format = mediaFormat.getString("mime")
      if (format.startsWith(prefix)) {
      		// 选择需要的轨道,接下来就可以提取这个轨道的内容了
           videoMediaExtractor.selectTrack(videoIndex)
      }
}
// 读取内容         
val frameSize = mediaExtractor.readSampleData(mReadBuffer, 0)
...
// 释放资源
mediaExtractor.release()

MediaMuxer

音视频合成器,视频音频合成,视频合成等等,常用与刚才的MediaExtractor一起使用

mediaMuxer = MediaMuxer(outPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
val mReadBuffer = ByteBuffer.allocate(MAX_BUFF_SIZE)
// 选择音轨 
val audioMediaExtractor = MediaExtractor()
audioMediaExtractor.setDataSource(path)
val audioIndex = findTrackIndex(audioMediaExtractor, "audio/")
audioMediaExtractor.selectTrack(audioIndex)
// 读取帧数据
val frameSize = mediaExtractor.readSampleData(mReadBuffer, 0)
mReadBuffer.rewind()
// 将数据写入到合成文件中
mediaMuxer!!.writeSampleData(outTrackIndex, mReadBuffer, bufferInfo)
// 释放
mediaMuxer!!.release()

总结

今天我们了解了Android原生常用的API,这些API已经足够满足我们开发中的各种需要,接下来我们要完成以下任务:

  1. MediaRecoder录制音频和视频
  2. MediaPlayer播放音频和视频
  3. MediaCodec播放音频和视频
  4. AudioRecoder录制PCM音频和播放
  5. MediaCodec录制视频
  6. 音视频合成和抽取
  7. 断点录制以及视频合成

(以上任务不分先后,顺序可能会变)

猜你喜欢

转载自blog.csdn.net/u011315960/article/details/96862786