You need to enable JavaScript to run this app.
文档中心
实时音视频

实时音视频

复制全文
下载 pdf
实现音视频通话
Android
复制全文
下载 pdf
Android
本文介绍如何集成火山引擎 RTC SDK,并实现实时音视频通话。根据如下步骤操作,即可从 0 开始构建一个简单的音视频通话应用。​
你也可以参考示例项目,了解更完整的项目实现。​
前提条件​
在开始集成 RTC SDK 前,请确保满足以下要求:​
  • Android Studio Arctic Fox | 2020.3.1 或以上版本(本文使用 Android Studio Giraffe | 2022.3.1 版本)​
  • Android 4.4 或以上版本的 Android 真机或模拟器​
说明​
推荐使用真机进行调试,连接指南参看在硬件设备上运行应用。​
  • Android 设备和开发电脑可以正常访问互联网​
创建和配置项目​
新建项目​
  1. 打开 Android Studio。在 Welcome to Android Studio 窗口中,单击 New Project。​
  1. 在项目模板页选择 Empty Views Activity,然后单击 Next。​
  1. 在项目配置页,设置项目名称、软件包名称、存储路径等信息,开发语言选择 Java,最低 API 级别选择 19 或以上,build 配置语言选择 Groovy,完成后单击 Finish。经过一段时间的处理后,Android Studio 主窗口会出现,此时你已经构建好了 Android 工程,可以开始编码了。​
配置权限​
SDK 已在内部声明所需权限,无需手动添加。对于敏感权限,你需要在 Activity 中动态申请,本文动态申请权限章节将提供示例代码。​
说明​
  • 如果你的应用以 Android 11(API 级别 30)或更高版本为目标平台,且希望在应用退到后台时仍能进行麦克风采集,则需在 AndroidManifest.xml 文件中声明前台服务类型 android:foregroundServiceType:microphone。此外,如果你的应用以 Android 14(API 级别 34)或更高版本为目标平台,则必须针对前台服务将要执行的工作类型请求 FOREGROUND_SERVICE_MICROPHONE 权限。摄像头权限同理。详细说明和示例代码参看前台服务权限适配方法。​
集成 SDK​
通过 Maven 集成​
  1. 在 Android Studio 左上角将工程视图切换为 Project 模式,在项目根目录的 settings.gradle 文件配置 Maven 仓库地址。​
  • ​
    dependencyResolutionManagement {​
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)​
    repositories {​
    ...​
    maven { url 'https://artifact.bytedance.com/repository/Volcengine/' }​
    }​
    }​
    ​
说明​
如果你的 Android Gradle Plugin 版本低于 v7.1.0,则应在项目根目录的 build.gradle 文件配置 Maven 仓库地址。​
​
allprojects {​
repositories {​
...​
maven { url 'https://artifact.bytedance.com/repository/Volcengine/' }​
}​
}​
​
  1. 在 App 的 build.gradle 文件中添加 RTC SDK 依赖。​
说明​
你需要将 '3.x.y.z' 替换为具体的版本号,最新版本号请参看下载 SDK。​
  • ​
    dependencies {​
    ...​
    implementation 'com.volcengine:VolcEngineRTC:3.x.y.z' // 填写需要接入的 RTC SDK 版本号​
    }​
    ​
  1. 在项目根目录的 gradle.properties 文件中添加 android.enableJetifier=true,解决兼容性问题。​
  1. 设置完成后,单击 Sync now 完成同步。​
手动集成​
说明​
本章节介绍全量集成 RTC SDK 的方法。如需减小 App 体积,请参看按需集成插件。​
  1. 下载并解压火山引擎 RTC SDK文件。​
  1. 在 Android Studio 左上角将工程视图切换为 Project 模式,将解压后的 VolcEngineRTC-lite.aar、effectAAR-release_V4.4.3Lite.aar 放在 app/libs 目录下,解压的四个架构文件夹放置在 app/jniLibs 目录下。​
  • ​图片​​
  1. 在 App 的 build.gradle 文件中添加 RTC SDK 依赖和 .so 文件依赖。​
  • ​
    android {​
    ...​
    sourceSets {​
    main {​
    // 指定 .so 文件所在目录​
    jniLibs.srcDirs = ['jniLibs']​
    }​
    }​
    }​
    ...​
    dependencies {​
    ...​
    // 集成主库​
    implementation files('libs/VolcEngineRTC-lite.aar')​
    // 集成特效库,用于实现美颜和特效相关功能​
    implementation files('libs/effectAAR-release_V4.4.3Lite.aar')​
    }​
    ​
  1. 在项目根目录的 gradle.properties 文件中添加 android.enableJetifier=true,解决兼容性问题。​
  1. 设置完成后,单击 Sync now 完成同步。​
创建用户界面​
根据场景需要,为你的项目创建音视频通话的用户界面。为实现基本的音视频通话,建议用户界面中至少包含本地视频窗口、远端视频窗口、加入房间按钮、退出房间按钮。​
将以下示例代码在 src/main/res/layout/activity_main.xml 中进行替换,即可快速创建用户界面。​
​
<?xml version="1.0" encoding="utf-8"?>​
<androidx.appcompat.widget.LinearLayoutCompat xmlns:android="http://schemas.android.com/apk/res/android"​
xmlns:app="http://schemas.android.com/apk/res-auto"​
xmlns:tools="http://schemas.android.com/tools"​
android:layout_width="match_parent"​
android:layout_height="match_parent"​
android:orientation="vertical"​
tools:context=".examples.QuickStartActivity"​
android:layout_marginHorizontal="15dp">​
​
<LinearLayout​
android:layout_width="match_parent"​
android:layout_height="300dp"​
android:orientation="horizontal">​
​
<FrameLayout​
android:id="@+id/local_view_container"​
android:layout_width="0dp"​
android:layout_height="match_parent"​
android:layout_weight="1"​
app:layout_constraintTop_toTopOf="parent"​
/>​
​
<FrameLayout​
android:id="@+id/remote_view_container"​
android:layout_width="0dp"​
android:layout_height="match_parent"​
android:layout_weight="1"​
app:layout_constraintTop_toTopOf="parent"​
/>​
</LinearLayout>​
​
<androidx.appcompat.widget.AppCompatButton​
android:id="@+id/btn_join_room"​
android:layout_width="match_parent"​
android:layout_height="wrap_content"​
android:text="加入房间"/>​
​
<androidx.appcompat.widget.AppCompatButton​
android:id="@+id/btn_leave_room"​
android:layout_width="match_parent"​
android:layout_height="wrap_content"​
android:text="退出房间"/>​
​
</androidx.appcompat.widget.LinearLayoutCompat>​
​
实现音视频通话​
本章节将先向你提供 API 调用时序图和完整的实现代码,再对具体的实现步骤展开介绍。​
时序图​
下图为使用火山引擎 RTC SDK 实现基础音视频通话的 API 调用时序图。​
​图片​​
完整示例代码​
复制以下示例代码,替换 MainActivity.java 文件中 package com.example.<projectname>; 后的全部内容,此处的 com.example.<projectname> 即为你新建项目时指定的软件包名称。连接并选择你的 Android 设备,单击 Android Studio 窗口右上角的运行按钮(Run 'app' ),即可快速实现音视频通话。​
说明​
你需要将代码中的 roomId、userId、APP_ID、token 替换为你在控制台上生成临时 Token 时所使用的房间 ID 和用户 ID,以及获取到的 AppID 和临时 Token。​
​
// package com.example.<projectname>; 你的软件包名称​
​
import androidx.appcompat.app.AppCompatActivity;​
import androidx.appcompat.widget.AppCompatButton;​
import androidx.core.content.ContextCompat;​
​
import android.Manifest;​
import android.content.pm.PackageManager;​
import android.os.Build;​
import android.os.Bundle;​
import android.view.TextureView;​
import android.widget.FrameLayout;​
​
​
import com.ss.bytertc.engine.RTCEngine;​
import com.ss.bytertc.engine.RTCRoom;​
import com.ss.bytertc.engine.RTCRoomConfig;​
import com.ss.bytertc.engine.UserInfo;​
import com.ss.bytertc.engine.VideoCanvas;​
import com.ss.bytertc.engine.data.EngineConfig;​
import com.ss.bytertc.engine.data.RemoteStreamKey;​
import com.ss.bytertc.engine.data.StreamIndex;​
import com.ss.bytertc.engine.handler.IRTCEngineEventHandler;​
import com.ss.bytertc.engine.handler.IRTCRoomEventHandler;​
import com.ss.bytertc.engine.type.ChannelProfile;​
​
public class MainActivity extends AppCompatActivity {​
​
private static final String APP_ID = ""; // 填写 appId​
private static final String roomId = ""; // 填写房间号​
private static final String userId = ""; // 填写 userId​
private static final String token = ""; // 填写临时 token​
​
private FrameLayout localViewContainer;​
private FrameLayout remoteViewContainer;​
​
private RTCEngine rtcEngine;​
private RTCRoom rtcRoom;​
​
@Override​
protected void onCreate(Bundle savedInstanceState) {​
super.onCreate(savedInstanceState);​
setContentView(R.layout.activity_main);​
requestPermission();​
​
localViewContainer = findViewById(R.id.local_view_container);​
remoteViewContainer = findViewById(R.id.remote_view_container);​
​
((AppCompatButton) findViewById(R.id.btn_join_room)).setOnClickListener(v -> {​
joinRoom(roomId);​
});​
​
((AppCompatButton) findViewById(R.id.btn_leave_room)).setOnClickListener(v -> {​
leaveRoom();​
});​
​
// 创建引擎​
EngineConfig engineConfig = new EngineConfig();​
engineConfig.context = this;​
engineConfig.appID = APP_ID;​
rtcEngine = RTCEngine.createRTCEngine(engineConfig, engineEventHandler);​
// 设置本端渲染视图​
setLocalRenderView();​
// 开启音视频采集​
rtcEngine.startVideoCapture();​
rtcEngine.startAudioCapture();​
}​
​
public void requestPermission() {​
String[] PERMISSIONS_STORAGE = {​
Manifest.permission.RECORD_AUDIO,​
Manifest.permission.CAMERA};​
​
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {​
if (ContextCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED​
|| ContextCompat.checkSelfPermission(this, "android.permission.RECORD_AUDIO") != PackageManager.PERMISSION_GRANTED) {​
requestPermissions(PERMISSIONS_STORAGE, 22);​
}​
}​
}​
​
/**​
* 设置本地渲染视图,支持TextureView和SurfaceView​
*/​
private void setLocalRenderView() {​
TextureView textureView = new TextureView(this);​
localViewContainer.removeAllViews();​
localViewContainer.addView(textureView);​
​
VideoCanvas videoCanvas = new VideoCanvas();​
videoCanvas.renderView = textureView;​
videoCanvas.renderMode = VideoCanvas.RENDER_MODE_HIDDEN;​
// 设置本地视频渲染视图​
rtcEngine.setLocalVideoCanvas(videoCanvas);​
}​
​
private void setRemoteRenderView(String streamId) {​
TextureView remoteTextureView = new TextureView(this);​
remoteViewContainer.removeAllViews();​
remoteViewContainer.addView(remoteTextureView);​
VideoCanvas videoCanvas = new VideoCanvas();​
videoCanvas.renderView = remoteTextureView;​
videoCanvas.renderMode = VideoCanvas.RENDER_MODE_HIDDEN;​
​
// 设置远端视频渲染视图​
rtcEngine.setRemoteVideoCanvas(streamId, videoCanvas);​
}​
​
private void removeRemoteView(String streamId) {​
rtcEngine.setRemoteVideoCanvas(streamId, null);​
}​
​
/**​
* 引擎回调信息​
*/​
IRTCEngineEventHandler engineEventHandler = new IRTCEngineEventHandler() {​
};​
​
IRTCRoomEventHandler rtcRoomEventHandler = new IRTCRoomEventHandler() {​
​
@Override​
public void onUserPublishStreamVideo(String streamId, StreamInfo streamInfo, boolean isPublish) {​
if (isPublish) {​
runOnUiThread(() -> setRemoteRenderView(streamInfo.streamId));​
} else {​
runOnUiThread(() -> removeRemoteView(streamInfo.streamId));​
}​
}​
};​
​
/**​
* 加入房间​
* @param roomId 房间ID​
*/​
private void joinRoom(String roomId) {​
rtcRoom = rtcEngine.createRTCRoom(roomId);​
rtcRoom.setRTCRoomEventHandler(rtcRoomEventHandler);​
// 用户信息​
UserInfo userInfo = new UserInfo(userId, "");​
boolean isAutoPublishAudio = true;​
boolean isAutoPublishVideo = true;​
boolean isAutoSubscribeAudio = true;​
boolean isAutoSubscribeVideo = true;​
​
RTCRoomConfig roomConfig = new RTCRoomConfig(​
ChannelProfile.CHANNEL_PROFILE_CHAT_ROOM,​
null,​
isAutoPublishAudio,​
isAutoPublishVideo,​
isAutoSubscribeAudio,​
isAutoSubscribeVideo​
);​
​
// 加入房间​
rtcRoom.joinRoom(token, userInfo, true, roomConfig);​
}​
​
/**​
* 离开房间​
*/​
private void leaveRoom() {​
if (rtcRoom != null) {​
rtcRoom.leaveRoom();​
rtcRoom.destroy();​
rtcRoom = null;​
}​
}​
​
@Override​
protected void onDestroy() {​
super.onDestroy();​
if (rtcEngine != null) {​
rtcEngine.stopVideoCapture();​
rtcEngine.stopAudioCapture();​
}​
RTCEngine.destroyRTCEngine();​
}​
}​
​
实现步骤详解​
引入类​
引入 SDK 需要的类。​
​
import com.ss.bytertc.engine.RTCRoom;​
import com.ss.bytertc.engine.RTCRoomConfig;​
import com.ss.bytertc.engine.RTCEngine;​
import com.ss.bytertc.engine.UserInfo;​
import com.ss.bytertc.engine.VideoCanvas;​
import com.ss.bytertc.engine.data.RemoteStreamKey;​
import com.ss.bytertc.engine.data.StreamIndex;​
import com.ss.bytertc.engine.handler.IRTCRoomEventHandler;​
import com.ss.bytertc.engine.handler.IRTCEngineEventHandler;​
import com.ss.bytertc.engine.type.ChannelProfile;​
import com.ss.bytertc.engine.data.EngineConfig;​
​
动态申请权限​
启动应用程序时,检查是否已在 App 中授予了所需的权限。​
​
public void requestPermission() {​
String[] PERMISSIONS_STORAGE = {​
Manifest.permission.RECORD_AUDIO,​
Manifest.permission.CAMERA};​
​
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {​
if (ContextCompat.checkSelfPermission(this, "android.permission.CAMERA") != PackageManager.PERMISSION_GRANTED​
|| ContextCompat.checkSelfPermission(this, "android.permission.RECORD_AUDIO") != PackageManager.PERMISSION_GRANTED) {​
requestPermissions(PERMISSIONS_STORAGE, 22);​
}​
}​
}​
​
初始化引擎​
调用 createRTCEngine 初始化 RTCEngine 引擎,所有 RTC 相关的 API 调用都要在创建引擎之后。​
​
// 创建引擎​
EngineConfig engineConfig = new EngineConfig();​
engineConfig.context = this;​
engineConfig.appID = APP_ID;​
rtcEngine = RTCEngine.createRTCEngine(engineConfig, engineEventHandler);​
​
采集音视频​
创建引擎后,调用 startVideoCapture 开启视频采集,调用 startAudioCapture 开启音频采集。​
​
// 开启音视频采集​
rtcEngine.startVideoCapture();​
rtcEngine.startAudioCapture();​
​
设置本地渲染视图​
调用 setLocalVideoCanvas 设置本端渲染窗口,支持 TextureView 和 SurfaceView。​
​
/**​
* 设置本地渲染视图,支持TextureView和SurfaceView​
*/​
private void setLocalRenderView() {​
TextureView textureView = new TextureView(this);​
localViewContainer.removeAllViews();​
localViewContainer.addView(textureView);​
​
VideoCanvas videoCanvas = new VideoCanvas();​
videoCanvas.renderView = textureView;​
videoCanvas.renderMode = VideoCanvas.RENDER_MODE_HIDDEN;​
// 设置本地视频渲染视图​
rtcEngine.setLocalVideoCanvas(videoCanvas);​
}​
​
创建并加入房间​
按以下步骤创建并加入房间:​
  1. 调用 createRTCRoom 创建 RTC 房间,所有和房间相关的 API 都在 RTCRoom 类。​
  1. 调用 setRTCRoomEventHandler 设置房间回调监听。​
  1. 调用 joinRoom 加入房间。​
​
/**​
* 加入房间​
* @param roomId 房间ID​
*/​
private void joinRoom(String roomId) {​
rtcRoom = rtcEngine.createRTCRoom(roomId);​
rtcRoom.setRTCRoomEventHandler(rtcRoomEventHandler);​
// 用户信息​
UserInfo userInfo = new UserInfo(userId, "");​
// 设置房间配置​
boolean isAutoPublishAudio = true;​
boolean isAutoPublishVideo = true;​
boolean isAutoSubscribeAudio = true;​
boolean isAutoSubscribeVideo = true;​
​
RTCRoomConfig roomConfig = new RTCRoomConfig(​
ChannelProfile.CHANNEL_PROFILE_CHAT_ROOM,​
null,​
isAutoPublishAudio,​
isAutoPublishVideo,​
isAutoSubscribeAudio,​
isAutoSubscribeVideo​
);​
​
// 加入房间​
rtcRoom.joinRoom(token, userInfo, true, roomConfig);;​
}​
​
设置、解除远端渲染视频​
当远端用户加入频道并发布视频流时,在 onUserPublishStreamVideo 或 onFirstRemoteVideoFrameDecoded 回调中调用 setRemoteVideoCanvas 设置并渲染远端视图。建议您在 onFirstRemoteVideoFrameDecoded 回调中设置视频渲染,确保视频渲染在视频解码完成后进行,以避免卡顿。​
在 onUserPublishStreamVideo 回调中,当 isPublish 参数为 false 时,触发解除远端视频渲染视图绑定的逻辑。调用用户自定的 removeRemoteView 方法来解除渲染远端视图。​
​
IRTCEngineEventHandler rtcEngineEventHandler = new IRTCEngineEventHandler() {​
@Override​
public void onFirstRemoteVideoFrameDecoded(String streamId, int width, int height, int rotation) {​
// 设置远端视频渲染视图​
runOnUiThread(() -> setRemoteRenderView(streamInfo.streamId));​
}​
};​
​
IRTCRoomEventHandler rtcRoomEventHandler = new IRTCRoomEventHandler() {​
@Override​
public void onUserPublishStreamVideo(String streamId, StreamInfo streamInfo, boolean isPublish) {​
if (!isPublish) {​
// 解除远端视频渲染视图绑定​
runOnUiThread(() -> removeRemoteView(streamInfo.streamId));​
}​
}​
​
};​
​
private void setRemoteRenderView(String streamId) {​
TextureView remoteTextureView = new TextureView(this);​
remoteViewContainer.removeAllViews();​
remoteViewContainer.addView(remoteTextureView);​
VideoCanvas videoCanvas = new VideoCanvas();​
videoCanvas.renderView = remoteTextureView;​
videoCanvas.renderMode = VideoCanvas.RENDER_MODE_HIDDEN;​
​
// 设置远端视频渲染视图​
rtcEngine.setRemoteVideoCanvas(streamId, videoCanvas);​
}​
​
private void removeRemoteView(String streamId) {​
rtcEngine.setRemoteVideoCanvas(streamId, null);​
}​
​
离开房间​
调用 leaveRoom 离开房间, 并调用 destroy 销毁房间实例。​
​
/**​
* 离开房间​
*/​
private void leaveRoom() {​
if (rtcRoom != null) {​
rtcRoom.leaveRoom();​
rtcRoom.destroy();​
rtcRoom = null;​
}​
}​
​
销毁引擎​
退出 app 时,调用 destroyRTCEngine 销毁 RTCEngine 引擎。​
​
RTCEngine.destroyRTCEngine();​
​
编译与运行​
  1. 开启 Android 设备的开发者选项,打开 USB 调试,通过 USB 连接线将 Android 设备接入电脑,并在 Android 设备选项中勾选你的 Android 设备。详情参看在硬件设备上运行应用。​
  1. 单击 Android Studio 窗口右上角的运行按钮(Run 'app' )开始编译。​
  1. 你的 Android 设备会自动打开 Demo 应用,在弹窗中选择开启摄像头和麦克风权限。​
  1. (可选)在第二台设备上使用相同的 AppID 和 RoomID,更换 UserID 并生成新的临时 Token,即可加入同一个房间体验双端通话。​
后续步骤​
在实现音视频通话后,如遇无声音、无画面、视频卡顿等问题时,您可以使用诊断工具快速排查和定位异常房间及用户,并获取异常根因分析、处理建议、分析报告等。​
常见问题​
​
最近更新时间:2026.09.21 16:45:00
这个页面对您有帮助吗?
有用
有用
无用
无用