鸿蒙开发实践——基于AudioRenderer音频播放

方案选择

如何选择音频播放开发方式

  • AudioRenderer :用于音频输出的ArkTS/JS API,仅支持PCM格式,需要应用持续写入音频数据进行工作。应用可以在输入前添加数据预处理,如设定音频文件的采样率、位宽等,要求开发者具备音频处理的基础知识,适用于更专业、更多样化的媒体播放应用开发。

  • AVPlayer:用于音频播放的ArkTS/JS API,集成了流媒体和本地资源解析、媒体资源解封装、音频解码和音频输出功能。可用于直接播放wav、mp3、m4a等格式的音频文件。

在播放音频方面用的最多的就是系统提供的AudioRenderer和AVPlayer。AudioRenderer是音频渲染器,用于播放PCM(Pulse Code Modulation)音频数据,相比AVPlayer而言,可以在输入前添加数据预处理,更适合有音频开发经验的开发者,以实现更灵活的播放功能。使用AudioRenderer播放音频涉及到AudioRenderer实例的创建、音频渲染参数的配置、渲染的开始与停止、资源的释放等。

方案描述

使用 AudioRenderer 播放音频

配置音频渲染参数并创建AudioRenderer实例。在创建AudioRenderer实例之前可以先设置音频流信息AudioStreamInfo,音频流信息如下:

名称

类型

必填

说明

samplingRate

AudioSamplingRate

音频文件的采样率。

channels

AudioChannel

音频文件的通道数。

sampleFormat

AudioSampleFormat

音频采样格式。

encodingType

AudioEncodingType

音频编码类型。

其中编码模式只支持PCM编码,所以代码里默认是ENCODING_TYPE_RAW。

然后是设置音频渲染器信息,音频渲染器信息如下:

名称

类型

必填

说明

usage

StreamUsage

音频流使用类型。

rendererFlags

number

音频文件的通道数。

其中rendererFlags,0代表普通音频渲染器,1代表低时延音频渲染器。ArkTS接口暂不支持低时延音频渲染器,所以默认为0。

     let  audioStreamInfo: audio.AudioStreamInfo = {
      samplingRate: audio.AudioSamplingRate[this.samplingRate], // 采样率
      channels: audio.AudioChannel[this.channels], // 通道
      sampleFormat: audio.AudioSampleFormat[this.sampleFormat], // 采样格式
      encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW // 编码格式
    }
    let  audioRendererInfo: audio.AudioRendererInfo = {
      usage: audio.StreamUsage[this.usage], // 音频流使用类型
      rendererFlags: 0 // 音频渲染器标志
    }
    let  audioRendererOptions: audio.AudioRendererOptions = {
      streamInfo: audioStreamInfo,
      rendererInfo: audioRendererInfo
    }

select提供下拉选择菜单,可以让用户在多个选项之间选择,和text组件一起使用就可以实现让用户自由选择配置信息的能力,这里以采样率下拉菜单为例子。 

Text('采样率')
        .fontSize(16)
        .fontWeight(FontWeight.Bold)
        .textAlign(TextAlign.End)
        .margin({ right: 4 })
 
      Select([{ value: 'SAMPLE_RATE_8000' },
        { value: 'SAMPLE_RATE_11025' },
        { value: 'SAMPLE_RATE_12000' },
        { value: 'SAMPLE_RATE_16000' },
        { value: 'SAMPLE_RATE_22050' },
        { value: 'SAMPLE_RATE_24000' },
        { value: 'SAMPLE_RATE_32000' },
        { value: 'SAMPLE_RATE_44100' },
        { value: 'SAMPLE_RATE_48000' },
        { value: 'SAMPLE_RATE_64000' },
        { value: 'SAMPLE_RATE_88200' },
        { value: 'SAMPLE_RATE_96000' },
        { value: 'SAMPLE_RATE_176400' },
        { value: 'SAMPLE_RATE_192000' },])
        .selected(this.index)
        .value(this.samplingRate)
        .font({ size: 16, weight: 500 })
        .fontColor('#182431')
        .selectedOptionFont({ size: 16, weight: 400 })
        .optionFont({ size: 16, weight: 400 })
        .space(this.space)
        .arrowPosition(this.arrowPosition)
        .menuAlign(MenuAlignType.START, { dx: 0, dy: 0 })
        .optionWidth(200)
        .optionHeight(300)
        .onSelect((index: number, text?: string | undefined) => {
          console.info('Select:' + index)
          this.index = index;
          if (text) {
            this.samplingRate = text;
            if (samplingRateData.get(this.samplingRate)) {
              this.samplingRate1 = samplingRateData.get(this.samplingRate)
            }
          }
        })
  • 调用on('writeData')方法,订阅监听音频数据写入回调。

import { BusinessError } from '@ohos.base';
import fs from '@ohos.file.fs';
 
let bufferSize: number = 0;
class Options {
  offset?: number;
  length?: number;
}
 
 
let path = getContext().cacheDir;
//确保该路径下存在该资源
let filePath = path + '/result_48000_1.pcm';
let file: fs.File = fs.openSync(filePath, fs.OpenMode.READ_ONLY);
let writeDataCallback = (buffer: ArrayBuffer) => {
  let options: Options = {
    offset: bufferSize,
    length: buffer.byteLength
  }
  fs.readSync(file.fd, buffer, options);
  bufferSize += buffer.byteLength;
}
 
audioRenderer.on('writeData', writeDataCallback);
  • 调用start()方法进入running状态,开始渲染音频。

import { BusinessError } from '@ohos.base';
 
audioRenderer.start((err: BusinessError) => {
  if (err) {
    console.error(`Renderer start failed, code is ${err.code}, message is ${err.message}`);
  } else {
    console.info('Renderer start success.');
  }
});
  • 调用stop()方法停止渲染。

import { BusinessError } from '@ohos.base';
 
audioRenderer.stop((err: BusinessError) => {
  if (err) {
    console.error(`Renderer stop failed, code is ${err.code}, message is ${err.message}`);
  } else {
    console.info('Renderer stopped.');
  }
});
  • 调用release()方法销毁实例,释放资源。

import { BusinessError } from '@ohos.base';
 
audioRenderer.release((err: BusinessError) => {
  if (err) {
    console.error(`Renderer release failed, code is ${err.code}, message is ${err.message}`);
  } else {
    console.info('Renderer released.');
  } 
});

select 下拉菜单的展示效果图

 

 

### 鸿蒙系统开发中的音量设置功能 在鸿蒙系统中,实现音量设置的功能主要涉及两个方面:一是对系统音量的管理;二是针对特定音频流音量的调整。以下是具体的实现方法以及相关代码示例。 #### 系统音量管理 系统音量指的是整个设备的总体音量水平。可以通过 `AudioManager` 类来获取当前系统的音量并对其进行修改。具体操作如下: ```javascript import audio from '@ohos.multimedia.audio'; // 获取 AudioManager 实例 let audioManager = audio.getAudioManager(audio.AudioSystemVolumeType.STREAM_MUSIC); // 设置系统音量 audioManager.setStreamVolume({ streamType: audio.AudioSystemVolumeType.STREAM_MUSIC, volumeLevel: 10, // 调整到指定音量等级 }).then(() => { console.log('系统音量已成功设置'); }).catch((err) => { console.error(`设置系统音量失败: ${err}`); }); ``` 此部分代码展示了如何通过 `setStreamVolume` 方法调整音乐类型的系统音量[^3]。 --- #### 音频流音量管理 除了全局的系统音量外,还可以单独控制某个音频流的音量。这通常用于应用程序内部播放的声音或媒体文件。以下是一个简单的例子,展示如何创建一个音频渲染器 (`AudioRenderer`) 并动态调整其音量: ```javascript import audio from '@ohos.multimedia.audio'; async function createAndSetVolume() { try { // 创建 AudioRenderer 实例 let rendererOptions = new audio.RendererOptions(); rendererOptions.streamInfo = { contentType: 'MUSIC', scene: 'MEDIA' }; const audioRenderer = await audio.createAudioRenderer(rendererOptions); // 启动音频渲染器 await audioRenderer.start(); // 设置音频流音量 await audioRenderer.setVolume(0.8); // 将音量设为最大值的 80% console.log('音频流音量已成功设置'); // 停止音频渲染器(仅作为演示) setTimeout(async () => { await audioRenderer.stop(); await audioRenderer.release(); }, 5000); } catch (error) { console.error(`音频流音量设置失败: ${error.message}`); } } createAndSetVolume(); ``` 在此代码片段中,`setVolume` 方法允许开发者以浮点数形式设定音量级别,范围是从 0 到 1 表示静音至满音量之间的比例[^2]。 --- #### 用户交互界面设计 如果希望提供一种更直观的方式来让用户调节音量,则可以结合触摸事件或者手势识别完成这一目标。例如,在屏幕上滑动手指即可改变音量大小。下面是一段伪代码描述该逻辑: ```typescript @Entry @Component struct VolumeControlComponent { @State currentVolume: number = 0; build() { Column() { Slider({ value: this.currentVolume, onChange: newValue => this.updateVolume(newValue) }) .width('90%') .height('40px') Text(`Current Volume Level: ${(this.currentVolume * 10).toFixed(0)}%`) .fontSize(20) .fontColor('#FFFFFF') }.padding(16) } private updateVolume(newVal: number): void { import audio from '@ohos.multimedia.audio'; let adjustedValue = Math.floor(newVal * 15); // 映射到实际音量级数 audio.getAudioManager(audio.AudioSystemVolumeType.STREAM_MUSIC) .setStreamVolume({ streamType: audio.AudioSystemVolumeType.STREAM_MUSIC, volumeLevel: adjustedValue }).then(() => { console.info(`Updated system volume to level ${adjustedValue}`); }); this.currentVolume = newVal; } } ``` 这里利用了一个滑块控件让用户体验更加友好,并且每次拖拽都会触发回调函数去更新对应的硬件参数[^4]。 --- #### 总结说明 以上介绍了三种不同的方式来进行鸿蒙应用内的音量配置——直接操控系统级别的声音强度、精细化处理单一路径下的数据包响度以及构建图形化前端供最终使用者自行定义偏好选项。每种途径都有各自适用场景,请依据实际情况选取合适的技术路线加以实践
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值