beat365网址官网网站-365体育世界杯专用版-365体育注册送365

Android实现直播功能(附带源码)

Android实现直播功能(附带源码)

一、项目介绍

1. 背景与意义

随着移动互联网和社交媒体的发展,“实时直播”已成为视频领域的核心功能:电商带货、在线教学、游戏直播、活动直播、社交视频等等场景都离不开直播功能。在 Android 端实现直播功能,不仅需要采集摄像头和麦克风数据,还要对视频音频进行实时编码、网络传输、服务器分发,并兼顾延迟、带宽、兼容性与稳定性等多重挑战。

一个完整的 Android 直播方案,通常包括以下模块:

采集:摄像头(Camera1/Camera2/CameraX)、麦克风音频

编码:硬件或软件编码(H.264、AAC)

传输协议:RTMP、WebRTC、SRT、HLS-DASH 等

推流Client:使用 MediaCodec + Socket 或第三方库(e.g. SRS Rtmp-Client、LFLiveKit)

播放:在 Android 端用 ExoPlayer/MediaPlayer 播放 HLS/DASH/WebRTC

服务器:Nginx-RTMP、SRS、Janus、Kurento、Agora、Zego 等分发或 P2P 转发

交互功能:弹幕、聊天室、低延迟互动

质量保证:丢包重传、码率自适应、NetworkCallback 监测

本文将从技术原理、方案对比、环境搭建、核心代码、性能优化与常见问题等多个维度,深入剖析 Android 端实现实时直播的全过程,并提供一套可运行的示例项目。全文约一万字,所有代码统一整合在一个代码块中,用注释分隔不同文件,便于一键复制使用。

二、相关基础知识

2.1 摄像头采集

Camera1 API:兼容性好,但回调线程不灵活

Camera2 API:控制更细粒度,支持 YUV 直接输出

CameraX:Jetpack 组件,封装 Camera2,易用性高

采集到的原始数据通常为 ImageFormat.NV21 或 YUV_420_888,需要转换为 ByteBuffer 给编码器。

2.2 音频采集

使用 AudioRecord 以 PCM 格式获取麦克风输入

参数:sampleRate=44100|16000、channelConfig=CHANNEL_IN_MONO、audioFormat=ENCODING_PCM_16BIT

2.3 媒体编码

MediaCodec(硬件加速)

配置 MIME_VIDEO_AVC(H.264)、MIME_AUDIO_AAC

输出 ByteBuffer 原始帧,需要打包成 RTMP FLV tag 或 WebRTC packet

FFmpeg(软件编码,兼容较老设备,但性能消耗高)

2.4 传输协议

RTMP(实时消息协议)

经典直播协议,基于 TCP,延迟在 1-3 秒

推流到 RTMP 服务器(Nginx-RTMP、SRS),服务器转 HLS/DASH 或推 CDN

HLS/DASH

基于 HTTP 切片,延迟在 10-30 秒,不适合互动

WebRTC

P2P 或 SFU 架构,基于 SRTP/DTLS,端到端低延迟(<500ms),适合互动

SRT/RTSP、QUIC:新协议,延迟/穿透表现各异

2.5 第三方 SDK

Agora/Zego 等商业 SDK,封装一切,免运维

开源库:SRS rtmp-rtsp-stream-client-java、Ant Media Android SDK、Kurento Client

三、方案对比

方案延迟兼容性复杂度运维成本MediaCodec+RTMP1–3 秒所有 Android(API 18+)中高需部署 RTMP 服务器WebRTC<500msAPI 21+高部署 SFU(Janus/Kurento)HLS/DASH10–30 秒所有 Android低CDN 成本商用 SDK (Agora…)<200ms广泛支持低按量付费

本文示例采用 MediaCodec+RTMP 方案:基于开源库 com.pedro.rtplibrary:rtplibrary:2.1.8(SRS 社区版),配合 Camera2 与 MediaCodec 实现一套轻量高效的推流端,服务器端推荐使用 SRS(Simple Realtime Server)。

四、环境与依赖

// app/build.gradle

plugins {

id 'com.android.application'

id 'kotlin-android'

}

android {

compileSdk 34

defaultConfig {

applicationId "com.example.rtmpdemo"

minSdk 21

targetSdk 34

}

buildFeatures.viewBinding true

}

dependencies {

implementation 'androidx.appcompat:appcompat:1.6.1'

implementation 'androidx.core:core-ktx:1.10.1'

implementation 'androidx.constraintlayout:constraintlayout:2.1.4'

// RTMP 推流库

implementation 'com.pedro.rtplibrary:rtplibrary:2.1.8'

// Camera2 封装(可选)

implementation 'com.otaliastudios:cameraview:2.7.1'

}

五、完整代码整合

// =======================================================

// 文件:AndroidManifest.xml

// 描述:申请 CAMERA、RECORD_AUDIO、FOREGROUND_SERVICE 权限

// =======================================================

package="com.example.rtmpdemo">

android:name=".App"

android:theme="@style/Theme.RtmpDemo">

android:exported="true">

// =======================================================

// 文件:App.kt

// 描述:Application,用于初始化日志、通道等

// =======================================================

package com.example.rtmpdemo

import android.app.Application

import android.app.NotificationChannel

import android.app.NotificationManager

import android.os.Build

class App : Application() {

companion object {

const val CHANNEL_ID = "rtmp_service_channel"

}

override fun onCreate() {

super.onCreate()

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {

val ch = NotificationChannel(

CHANNEL_ID, "RTMP Service", NotificationManager.IMPORTANCE_LOW)

getSystemService(NotificationManager::class.java).createNotificationChannel(ch)

}

}

}

// =======================================================

// 文件:res/layout/activity_main.xml

// 描述:主界面布局:CameraView + 控制按钮

// =======================================================

xmlns:android="http://schemas.android.com/apk/res/android"

xmlns:app="http://schemas.android.com/apk/res-auto"

android:layout_width="match_parent" android:layout_height="match_parent">

android:id="@+id/cameraView"

android:layout_width="0dp" android:layout_height="0dp"

app:layout_constraintTop_toTopOf="parent"

app:layout_constraintBottom_toTopOf="@+id/controlPanel"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintEnd_toEndOf="parent"

app:cameraAudio="on"

app:cameraFacing="back"

app:cameraAutoFocus="on" />

android:id="@+id/controlPanel"

android:orientation="horizontal"

android:gravity="center"

android:layout_width="0dp" android:layout_height="wrap_content"

android:padding="8dp"

app:layout_constraintBottom_toBottomOf="parent"

app:layout_constraintStart_toStartOf="parent"

app:layout_constraintEnd_toEndOf="parent">