You need to enable JavaScript to run this app.
导航
为什么通过系统音量无法调节背景音乐音量
最近更新时间:2025.01.23 17:52:28首次发布时间:2025.01.23 17:31:13

问题详述

在移动设备中,用户在后台播放背景音乐,加入 RTC 频道后,用户无法通过调节系统音量去改变背景音乐的音量。

问题解答

移动设备的音量类型分为通话音量和媒体音量。一般而言,音视频通话时使用通话音量,播放背景音乐时使用媒体音量。关于两者的区别请参看通话音量和媒体音量有什么区别?

用户加入 RTC 频道后, RTC SDK 控制的音量类型决定了系统音量控制的音量类型。当 SDK 控制通话音量,背景音乐使用媒体音量时,系统音量只能控制通话音量,无法调节背景音乐的音量。

你可通过以下三种方法进行解决:

方案一:将背景音乐通过 RTC 托管播放

你可以使用混音功能播放背景音乐,让 SDK 同时控制背景音乐和通话声音。不论 SDK 使用的是通话音量还是媒体音量,用户都可以通过系统音量同时调节背景音乐和通话声音的音量。关于该功能的使用方法参看使用混音功能

方案二:切换媒体模式

你可以通过调用 setAudioScenario 设置 SDK 的音频场景类型,确保你使用的场景下音频设备使用的是媒体音量。成功设置后,用户可以通过系统音量同时调节背景音乐和通话声音的音量。

方案三:通过系统 API 监听音量变化并调节

Android

你可以通过监听通话音量变化,调用 AudioManager让媒体音量跟随通话音量,达到调节通话音量时媒体音量同步变化。

具体实现步骤如下:

  1. 创建 RTC 引擎并注册音量变化监听;
  2. 使用手机硬件音量键或声音调节 UI 调整声音时,收到系统声音变化广播;
  3. 判断音量变化声音类型,如果为通话音量则计算当前通话音量与可设置最大通话音量比例,按照比例同步调用系统 API 调整媒体音量;
  4. 销毁引擎并取消音量变化的监听;

你可参看以下示例代码实现:

/**
* RTC 引擎的创建方法
*/
public void createVolcEngine() {
    //省略无关代码 ......
    //初始化音量变化管理器,管理器构造方法中初始化并注册音量变化监听广播及首次将通话音量同步至媒体音量
    if (mContext != null) {
        mVolumeChangeManager = new VolumeChangeManager(mContext.getApplicationContext());
    }
    //创建火山引擎,createRTCVideo
    //省略无关代码 ...... 
}

/**
*RTC 引擎销毁方法
*/
@Override
public void destory() {
    //省略无关代码 ...... 
    //销毁火山引擎同时取消音量变化的监听
    if (mVolumeChangeManager != null) {
        mVolumeChangeManager.unregisterVolumeReceiver();
    }
    //销毁火山引擎,destoryRTCVideo
    //省略无关代码 ...... 
}
/**
 * 音量变化管理器:内部封装对通过系统API获取媒体最大音量,媒体最小音量,通话最大音量,设置通话音量等API的调用,音量变化监听的注册和反注册
 */
public static class VolumeChangeManager {

    public static final String VOLUME_CHANGE_ACTION = "android.media.VOLUME_CHANGED_ACTION";

    private Context mContext;
    private AudioManager mAudioManager;
    private VolumeBroadCastReceiver mVolumeBroadCastReceiver;

    private int mMediaMaxVolume = 0;
    private int mMediaMinVolume = 0;
    private int mCallMaxVolume = 0;


    private VolumeChangeManager(@NotNull Context context) {
        mContext = context;
        //获取系统声音管理器
        mAudioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE);
        if (mAudioManager == null) {
            Logger.e("VolcEngine syncMediaCallVolume mAudioManager is null!");
            return;
        }
        //获取媒体最大音量
        mMediaMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
        //获取媒体最小音量
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
            mMediaMinVolume = mAudioManager.getStreamMinVolume(AudioManager.STREAM_MUSIC);
        } else {
            mMediaMinVolume = 0;
        }
        //获取通话最大音量
        mCallMaxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_VOICE_CALL);
        mVolumeBroadCastReceiver = new VolumeBroadCastReceiver();
        //初始化音量变化监听器
        mVolumeBroadCastReceiver.setVolumeChangeManager(this);
        //注册音量变化监听广播
        context.registerReceiver(mVolumeBroadCastReceiver, new IntentFilter(VOLUME_CHANGE_ACTION));
        //首次将通话音量同步至媒体音量,防止本身媒体音量太小
        syncMediaCallVolumeWhenInit();
    }

    private void syncMediaCallVolumeWhenInit() {
        int callVolume = getCallVolume();
        int mediaVolume = getMediaVolume();
        double callProgress = (double) callVolume / (double)mCallMaxVolume;
        double mediaProgress = (double) mediaVolume / (double)mMediaMaxVolume;
        if (mediaProgress >= callProgress) {
            return;
        }
        double progress = callProgress > 0.8 ? 0.8 : callProgress;
        int volume = (int)(progress * mMediaMaxVolume);
        Logger.i("VolcEngine syncMediaCallVolumeWhenInit volume:" + volume + ", maxVolume:" + mMediaMaxVolume);
        setMediaVolume(volume);
    }
    
    private void syncMediaCallVolume() {
        int callVolume = getCallVolume();
        //按照当前设置的通话音量比例计算应该设置的媒体音量
        int volume = (int) ((callVolume / (float) mCallMaxVolume) * mMediaMaxVolume);
        setMediaVolume(volume);
    }

    /**
     * 取消声音变化监听
     */
    private void unregisterVolumeReceiver() {
        if (mVolumeBroadCastReceiver != null && mContext != null) {
            mContext.unregisterReceiver(mVolumeBroadCastReceiver);
            mVolumeBroadCastReceiver.setVolumeChangeManager(null);
            mVolumeBroadCastReceiver = null;
            mAudioManager = null;
            mContext = null;
        }
    }

    /**
     * 设置媒体音量
     *
     * @param volume 媒体最新音量
     */
    private void setMediaVolume(int volume) {
        if (mAudioManager != null) {
            if (volume > mMediaMaxVolume) {
                volume = mMediaMaxVolume;
            }
            if (volume < mMediaMinVolume) {
                volume = mMediaMinVolume;
            }
            mAudioManager.setStreamVolume(AudioManager.STREAM_MUSIC, volume, AudioManager.FLAG_PLAY_SOUND);
        }
    }

    /**
     * 获取当前通话音量
     */
    private int getCallVolume() {
        if (mAudioManager != null) {
            return mAudioManager.getStreamVolume(AudioManager.STREAM_VOICE_CALL);
        }
        return 1;
    }
    
    /**
     * 获取当前媒体音量
     */
    private int getMediaVolume() {
        if (mAudioManager != null) {
            return mAudioManager.getStreamVolume(AudioManager.STREAM_MUSIC);
        }
        return 1;
    }
}
/**
 * 声音变化监听器
 */
public static class VolumeBroadCastReceiver extends BroadcastReceiver {
    
    public static final String EXTRA_VOLUME_STREAM_TYPE = "android.media.EXTRA_VOLUME_STREAM_TYPE";
    
    private VolumeChangeManager mVolumeChangeHelper;

    public void setVolumeChangeManager(VolumeChangeManager volumeChangeHelper) {
        mVolumeChangeHelper = volumeChangeHelper;
    }

    @Override
    public void onReceive(Context context, Intent intent) {
        //获取音量变化的声音类型
        int changeVolumeType = intent.getIntExtra(EXTRA_VOLUME_STREAM_TYPE, -1);
        if (mVolumeChangeHelper != null) {
            changeMediaVolume(changeVolumeType);
        }
    }

    public void changeMediaVolume(int volumeType) {
        //如果音量变化的声音类型为通话音量,则同步改变媒体音量
        if (volumeType == AudioManager.STREAM_VOICE_CALL) {
            mVolumeChangeHelper.syncMediaCallVolume();
        }
    }
}

iOS

你可以通过调用 MPVolumeView 实现通过 UI 调节音量条,滑动调节媒体音量。