Android 视频开发全攻略
这份教程将分为以下几个核心模块:

- 基础篇:视频播放器开发
- 使用
VideoView快速实现 - 使用
MediaPlayer+SurfaceView完全控制 - 使用现代框架
ExoPlayer(强烈推荐)
- 使用
- 进阶篇:视频录制功能
- 使用
MediaRecorderAPI - 录制流程与关键代码
- 使用
- 实战篇:视频剪辑与处理
- 使用
MovieMaker进行简单拼接 - 使用强大的第三方库
FFmpeg(Android 移植版)
- 使用
- 高级篇:视频流媒体
- 直播推流(RTMP)
- 直播拉流(HLS, DASH)
- 学习资源与最佳实践
基础篇 - 视频播放器开发
视频播放是视频开发最常见的需求,Android 提供了多种方式,从简单易用到高度可控。
使用 VideoView (最简单)
VideoView 是一个封装了 MediaPlayer 和 SurfaceView 的高级组件,适合快速实现播放功能。
布局文件 (activity_main.xml)
<VideoView
android:id="@+id/videoView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_centerInParent="true" />
代码实现 (MainActivity.kt)

import android.net.Uri
import android.os.Bundle
import android.widget.MediaController
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
class MainActivity : AppCompatActivity() {
private lateinit var videoView: VideoView
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
videoView = findViewById(R.id.videoView)
// 1. 设置视频控制器(播放/暂停、进度条等)
val mediaController = MediaController(this)
mediaController.setAnchorView(videoView)
videoView.setMediaController(mediaController)
// 2. 设置视频源
// 可以是本地资源文件
// val videoUri = Uri.parse("android.resource://$packageName/${R.raw.sample_video}")
// 也可以是网络URL
val videoUri = Uri.parse("https://www.example.com/path/to/your/video.mp4")
videoView.setVideoURI(videoUri)
// 3. 设置准备和完成监听
videoView.setOnPreparedListener { mp ->
// 视频准备完成,可以开始播放
mp?.start()
}
videoView.setOnCompletionListener {
// 视频播放完成
Toast.makeText(this, "播放完成", Toast.LENGTH_SHORT).show()
}
videoView.setOnErrorListener { mp, what, extra ->
// 播放出错
Toast.makeText(this, "播放出错: $what, $extra", Toast.LENGTH_SHORT).show()
true
}
}
}
优点: 简单快捷,几行代码就能搞定。
缺点: 功能有限,自定义性差,性能和兼容性不如 ExoPlayer。
使用 MediaPlayer + SurfaceView (完全控制)
这种方式需要你手动管理播放器生命周期和渲染,但提供了最大的灵活性。
布局文件 (activity_main.xml)
<SurfaceView
android:id="@+id/surfaceView"
android:layout_width="match_parent"
android:layout_height="match_parent" />
代码实现 (MainActivity.kt)

import android.media.MediaPlayer
import android.net.Uri
import android.os.Bundle
import android.view.SurfaceHolder
import android.view.SurfaceView
import androidx.appcompat.app.AppCompatActivity
class MediaPlayerActivity : AppCompatActivity(), SurfaceHolder.Callback {
private lateinit var surfaceView: SurfaceView
private lateinit var surfaceHolder: SurfaceHolder
private var mediaPlayer: MediaPlayer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
surfaceView = findViewById(R.id.surfaceView)
surfaceHolder = surfaceView.holder
surfaceHolder.addCallback(this)
// 注意:MediaPlayer的创建和设置应该在Surface准备好之后
}
override fun surfaceCreated(holder: SurfaceHolder) {
// Surface已创建,可以初始化MediaPlayer
mediaPlayer = MediaPlayer().apply {
// 设置显示的Surface
setDisplay(holder)
// 设置数据源
val videoUri = Uri.parse("https://www.example.com/path/to/your/video.mp4")
setDataSource(this@MediaPlayerActivity, videoUri)
// 异步准备
prepareAsync()
setOnPreparedListener { mp ->
mp.start()
}
}
}
override fun surfaceChanged(holder: SurfaceHolder, format: Int, width: Int, height: Int) {
// Surface尺寸改变时调用
}
override fun surfaceDestroyed(holder: SurfaceHolder) {
// Surface被销毁,必须释放MediaPlayer资源
mediaPlayer?.release()
mediaPlayer = null
}
override fun onDestroy() {
super.onDestroy()
// 确保在Activity销毁时释放资源
mediaPlayer?.release()
mediaPlayer = null
}
}
优点: 完全控制播放过程,适合需要自定义渲染逻辑的场景。 缺点: 代码复杂,需要手动处理资源释放,容易出错。
使用 ExoPlayer (现代、强大、推荐)
Google 官方推出的媒体播放框架,是目前 Android 视频播放的首选方案,它支持多种格式、自适应码率流、DRM 加密等高级功能,并且性能极佳。
添加依赖 (app/build.gradle)
dependencies {
implementation "androidx.media3:media3-exoplayer:1.3.1" // 核心库
implementation "androidx.media3:media3-ui:1.3.1" // UI组件 (PlayerView)
implementation "androidx.media3:media3-exoplayer-hls:1.3.1" // HLS支持
implementation "androidx.media3:media3-exoplayer-dash:1.3.1" // DASH支持
}
布局文件 (activity_main.xml)
<androidx.media3.ui.PlayerView
android:id="@+id/playerView"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:use_controller="true" /> <!-- 显示控制器 -->
代码实现 (MainActivity.kt)
import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.media3.common.MediaItem
import androidx.media3.exoplayer.ExoPlayer
import androidx.media3.ui.PlayerView
class ExoPlayerActivity : AppCompatActivity() {
private lateinit var playerView: PlayerView
private var exoPlayer: ExoPlayer? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
playerView = findViewById(R.id.playerView)
// 1. 创建ExoPlayer实例
exoPlayer = ExoPlayer.Builder(this).build()
// 2. 将播放器与PlayerView关联
playerView.player = exoPlayer
// 3. 准备并播放媒体
val mediaItem = MediaItem.fromUri("https://www.example.com/path/to/your/video.mp4")
exoPlayer?.setMediaItem(mediaItem)
exoPlayer?.prepare()
exoPlayer?.playWhenReady = true // 自动播放
}
override fun onStop() {
super.onStop()
// 在后台时暂停播放,节省资源
exoPlayer?.playWhenReady = false
}
override fun onDestroy() {
super.onDestroy()
// 释放播放器资源
exoPlayer?.release()
exoPlayer = null
}
}
优点:
- 功能强大:支持几乎所有现代媒体格式和流媒体协议。
- 性能优越:硬件加速,自适应码率,缓冲策略智能。
- 高度可定制:UI 和播放逻辑都可以深度定制。
- 官方维护:由 Google 维护,稳定性和未来有保障。
- 生命周期管理简单:与
Lifecycle组件集成良好。
缺点: API 相对前两者更复杂,学习成本稍高。
进阶篇 - 视频录制功能
使用 MediaRecorder API 可以实现视频录制。
核心步骤:
- 获取
CameraX或 Camera2 的Surface(用于预览和录制)。 - 配置
MediaRecorder:设置输出文件格式、编码器、视频/音频源等。 - 准备、开始、停止、释放。
代码示例 (简化版):
import android.media.MediaRecorder
import android.os.Bundle
import android.view.Surface
import android.widget.Button
import androidx.appcompat.app.AppCompatActivity
import java.io.File
class RecordActivity : AppCompatActivity() {
private lateinit var mediaRecorder: MediaRecorder
private lateinit var output: File
private var isRecording = false
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_record)
val recordButton: Button = findViewById(R.id.record_button)
// 假设你已经从Camera2/CameraX获取到了previewSurface
val previewSurface: Surface = ...
output = File(getExternalFilesDir(null), "recorded_video.mp4")
recordButton.setOnClickListener {
if (!isRecording) {
startRecording(previewSurface)
recordButton.text = "停止"
} else {
stopRecording()
recordButton.text = "开始"
}
}
}
private fun startRecording(surface: Surface) {
mediaRecorder = MediaRecorder().apply {
setVideoSource(MediaRecorder.VideoSource.SURFACE)
setAudioSource(MediaRecorder.AudioSource.MIC)
setOutputFormat(MediaRecorder.OutputFormat.MPEG_4)
setOutputFile(output.absolutePath)
setVideoEncoder(MediaRecorder.VideoEncoder.H264)
setAudioEncoder(MediaRecorder.AudioEncoder.AAC)
setVideoSize(1920, 1080) // 设置分辨率
setVideoEncodingBitRate(5_000_000) // 设置比特率
setPreviewDisplay(surface) // 设置预览Surface
prepare()
start()
}
isRecording = true
}
private fun stopRecording() {
mediaRecorder.apply {
stop()
reset()
release()
}
isRecording = false
// 录制完成,文件保存在 output.path
}
}
重要提示:
- 权限: 必须在
AndroidManifest.xml中添加CAMERA和RECORD_AUDIO权限,并在运行时动态请求。 - Camera2 API: 现代应用推荐使用 Camera2 API,它比旧的 Camera API 更强大,但也更复杂。
CameraX是对 Camera2 的封装,可以简化开发。 - 生命周期:
MediaRecorder的创建、准备、释放必须在正确的生命周期回调中处理,避免内存泄漏和崩溃。
实战篇 - 视频剪辑与处理
Android 原生 API 对视频剪辑的支持非常有限,通常需要借助第三方库。
使用 MovieMaker (拼接)
MediaCodec API 中的 MediaMuxer 可以将编码后的音视频轨道合成为一个文件,这可以实现简单的拼接(前提是视频格式、分辨率、编码器完全相同)。
流程:
- 使用
MediaExtractor分别从两个视频中分离出视频轨道和音频轨道。 - 使用
MediaCodec解码这些轨道(或者直接复用已编码的数据)。 - 使用
MediaMuxer将轨道A的视频和轨道B的视频(以及音频)写入到一个新的输出文件中。
这种方法非常底层,代码量巨大,不推荐新手尝试。
使用第三方库 (推荐)
FFmpeg (Android 移植版)
FFmpeg 是一个强大的音视频处理命令行工具,在 Android 上,我们可以使用它的移植版,如 FFmpegKit 或 android-ffmpeg。
添加依赖 (以 FFmpegKit 为例)
// 在 project/build.gradle 的 repositories 中添加
maven {
url 'https://jitpack.io'
}
// 在 app/build.gradle 的 dependencies 中添加
implementation 'com.github.arthenica:ffmpeg-kit-android:6.0-essentials-lite' // lite版本包含常用功能
使用 FFmpeg 命令进行剪辑
import io.ffmpeg.kotlin.FFmpegKit
class EditActivity : AppCompatActivity() {
fun trimVideo(inputPath: String, outputPath: String, startTime: String, duration: String) {
// FFmpeg命令: ffmpeg -i input.mp4 -ss 00:00:10 -t 00:00:05 -c copy output.mp4
val command = arrayOf(
"-i", inputPath,
"-ss", startTime, // 开始时间
"-t", duration, // 持续时间
"-c", "copy", // 直接复制流,不重新编码,速度快
outputPath
)
// 执行命令
val session = FFmpegKit.execute(command.joinToString(" "))
if (session.returnCode == 0) {
// 剪辑成功
Log.d("FFmpeg", "剪辑成功: ${session.output}")
} else {
// 剪辑失败
Log.e("FFmpeg", "剪辑失败: ${session.failStackTrace}")
}
}
}
优点: 功能极其强大,几乎可以实现所有音视频处理操作(剪辑、合并、转码、添加滤镜等)。
缺点: 需要学习 FFmpeg 命令,集成和部署库文件(如 .so 文件)相对复杂。
高级篇 - 视频流媒体
直播推流
将手机摄像头捕获的视频和麦克风的声音,实时推送到 RTMP 服务器。
- 技术栈:
- 采集: Camera2 API / AudioRecord
- 编码: MediaCodec (H.264 视频编码, AAC 音频编码)
- 封装: 将编码后的数据打包成 FLV 格式
- 推送: 使用 RTMP 协议通过 Socket 推送到服务器
- 库推荐:
rtmp-rtplibrary(如bytedance/rtmp-rtplibrary),封装了底层细节,简化了推流实现。
直播拉流
从 RTMP 服务器拉取直播流,并进行播放。
- 技术栈:
- 协议: RTMP (主协议), HLS (延迟较高,但兼容性好), DASH
- 播放: 直接使用
ExoPlayer! ExoPlayer 对这些协议有非常好的支持。
- 实现:
// 使用ExoPlayer拉取RTMP流 val mediaItem = MediaItem.fromUri("rtmp://live.example.com/live/stream_key") exoPlayer?.setMediaItem(mediaItem) exoPlayer?.prepare()
学习资源与最佳实践
学习资源
-
官方文档 (必看):
-
GitHub 项目:
-
博客与教程:
- ProAndroidDev: 上面有很多高质量的音视频开发文章。
- 掘金、CSDN: 搜索 "Android ExoPlayer", "Android MediaRecorder" 等关键词,有大量中文教程。
最佳实践
- 优先使用 ExoPlayer: 除非你的项目极其简单,否则都应该将
ExoPlayer作为视频播放的首选。 - 生命周期管理: 始终在
onPause()/onStop()中暂停播放器,在onDestroy()中释放资源,避免内存泄漏和后台播放。 - 处理异常: 网络中断、格式不支持、解码失败等情况是常态,代码中必须有完善的错误处理和重试逻辑。
- 性能优化:
- 对于高清视频,优先使用硬件解码。
- 使用自适应码率流,根据网络状况自动调整清晰度。
- 避免在主线程中执行耗时操作(如视频解码、文件读写)。
- 权限处理: 务必在运行时动态请求相机和录音权限,并处理用户拒绝的情况。
- 考虑第三方库: 对于复杂的推流、剪辑等功能,不要重复造轮子,选择成熟稳定的第三方库可以大大提高开发效率和项目稳定性。
希望这份详细的教程能帮助你顺利开启 Android 视频开发之旅!
