HarmonyOS 錄音與音頻播放
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)
引言
錄音和音頻播放在app中是一個(gè)很常見(jiàn)的功能,本文將介紹在HarmonyOS 如何使用錄音和音頻播放功能。
功能介紹
1.錄音
1.1 使用錄音前需要先申請(qǐng)錄音權(quán)限
在 config.json文件中添加權(quán)限聲明
- "reqPermissions": [
- {
- "name": "ohos.permission.MICROPHONE",
- "reason": "the app need microphone",
- "usedScene": {
- "ability": [
- "com.iflytek.demo.MainAbility"
- ],
- "when": "always"
- }
- }
- ]
然后在MainAbility中動(dòng)態(tài)申請(qǐng)麥克風(fēng)權(quán)限
- private void requestPermission() {
- if (verifySelfPermission("ohos.permission.MICROPHONE") != IBundleManager.PERMISSION_GRANTED) {
- // 應(yīng)用未被授予權(quán)限
- if (canRequestPermission("ohos.permission.MICROPHONE")) {
- // 是否可以申請(qǐng)彈框授權(quán)(首次申請(qǐng)或者用戶未選擇禁止且不再提示)
- requestPermissionsFromUser(new String[]{"ohos.permission.MICROPHONE"}, REQUEST_MICROPHONE);
- } else {
- // 顯示應(yīng)用需要權(quán)限的理由,提示用戶進(jìn)入設(shè)置授權(quán)
- }
- } else {
- // 權(quán)限已被授予
- }
- }
- /**
- * 權(quán)限回調(diào)
- */
- @Override
- public void onRequestPermissionsFromUserResult(int requestCode,
- String[] permissions,
- int[] grantResults) {
- switch (requestCode) {
- case REQUEST_MICROPHONE: {
- // 匹配requestPermissions的requestCode
- if (grantResults.length > 0 && grantResults[0] == IBundleManager.PERMISSION_GRANTED) {
- // 權(quán)限被授予
- // 注意:因時(shí)間差導(dǎo)致接口權(quán)限檢查時(shí)有無(wú)權(quán)限,所以對(duì)那些因無(wú)權(quán)限而拋異常的接口進(jìn)行異常捕獲處理
- AppLog.e("MainAbility", "已經(jīng)獲取到錄音權(quán)限");
- } else {
- // 權(quán)限被拒絕
- AppLog.e("MainAbility", "錄音權(quán)限被拒絕");
- }
- }
- }
- }
1.2 錄音功能使用的是 AudioCapturer類,主要接口如下:
初始化AudioCapturer,先通過(guò) AudioStreamInfo設(shè)置錄音音頻基本參數(shù),再通過(guò)AudioCapturerInfo設(shè)置錄音源等信息。
- /**
- * 創(chuàng)建默認(rèn)的錄音對(duì)象
- */
- public void initConfig() {
- if (audioCapturer != null && audioCapturer.getState() != AudioCapturer.State.STATE_STOPPED) {
- audioCapturer.release();
- }
- audioCapturer = null;
- AudioStreamInfo audioStreamInfo = new AudioStreamInfo.Builder()
- // 音頻采樣率 16000
- .sampleRate(AUDIO_SAMPLE_RATE)
- // 錄音數(shù)據(jù)格式 16-bit PCM
- .encodingFormat(AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT)
- // 聲道設(shè)置 單聲道
- .channelMask(AudioStreamInfo.ChannelMask.CHANNEL_IN_MONO)
- .build();
- AudioCapturerInfo audioCapturerInfo = new AudioCapturerInfo.Builder()
- .audioStreamInfo(audioStreamInfo)
- // 錄音源
- .audioInputSource(AudioCapturerInfo.AudioInputSource.AUDIO_INPUT_SOURCE_MIC)
- .build();
- audioCapturer = new AudioCapturer(audioCapturerInfo);
- bufferSizeInBytes = AudioCapturer.getMinBufferSize(AUDIO_SAMPLE_RATE, 1, 2);
- }
開(kāi)始錄音,通過(guò) audioCapturer.read() 獲取音頻。
- /**
- * 開(kāi)始錄音
- *
- * @param listener 音頻流的監(jiān)聽(tīng)回調(diào)
- */
- public void startRecord(final RecordListener listener) {
- if (audioCapturer.getState() == AudioCapturer.State.STATE_UNINITIALIZED) {
- throw new IllegalStateException("AudioCapturer need init first");
- }
- if (isRecording()) {
- throw new IllegalStateException("AudioCapturer is in recording now");
- }
- // 開(kāi)始錄音
- audioCapturer.start();
- final byte[] audioData = new byte[bufferSizeInBytes];
- while (isRecording()) {
- int size = audioCapturer.read(audioData, 0, bufferSizeInBytes);
- if (size > 0 && listener != null) {
- if (size == bufferSizeInBytes) {
- // 通過(guò)回掉回傳錄音數(shù)據(jù)
- listener.onRead(audioData);
- } else {
- // 通過(guò)回掉回傳錄音數(shù)據(jù)
- final byte[] copy = new byte[size];
- System.arraycopy(audioData, 0, copy, 0, size);
- listener.onRead(copy);
- }
- }
- }
- if (finishCallBack != null) {
- finishCallBack.onFinish();
- }
- }
停止錄音
- /**
- * 停止錄音
- */
- public synchronized void stopRecord() {
- if (isRecording()) {
- audioCapturer.stop();
- }
- }
- /**
- * 釋放資源
- */
- public synchronized void release() {
- if (audioCapturer != null) {
- audioCapturer.release();
- audioCapturer = null;
- }
- }
2. 音頻播放
HarmonyOS 中,播放音頻主要有 AudioRenderer 、Player 、SoundPlayer 3個(gè)類
AudioRenderer 用于播放pcm音頻流
Player 主要用于播放mp3、m4a等格式的音頻
SoundPlayer 用于播放短音頻
2.1 AudioRenderer播放pcm音頻
- /**
- * 播放pcm
- *
- * @param file pcm文件
- */
- private void playPcm(File file) {
- if (file == null || !file.exists()) {
- showToast("文件不存在");
- return;
- }
- AudioStreamInfo streamInfo = new AudioStreamInfo.Builder()
- // 16kHz
- .sampleRate(16000)
- // 混音
- .audioStreamFlag(AudioStreamInfo.AudioStreamFlag.AUDIO_STREAM_FLAG_MAY_DUCK)
- // 16-bit PCM
- .encodingFormat(AudioStreamInfo.EncodingFormat.ENCODING_PCM_16BIT)
- // 單聲道輸出
- .channelMask(AudioStreamInfo.ChannelMask.CHANNEL_OUT_MONO)
- // 媒體類音頻
- .streamUsage(AudioStreamInfo.StreamUsage.STREAM_USAGE_MEDIA)
- .build();
- AudioRendererInfo audioRendererInfo = new AudioRendererInfo.Builder().audioStreamInfo(streamInfo)
- // pcm格式的輸出流
- .audioStreamOutputFlag(AudioRendererInfo.AudioStreamOutputFlag.AUDIO_STREAM_OUTPUT_FLAG_DIRECT_PCM)
- .bufferSizeInBytes(1280)
- // false表示分段傳輸buffer并播放,true表示整個(gè)音頻流一次性傳輸?shù)紿AL層播放
- .isOffload(false)
- .build();
- AudioRenderer renderer = new AudioRenderer(audioRendererInfo, AudioRenderer.PlayMode.MODE_STREAM);
- renderer.start();
- try {
- FileInputStream inputStream = new FileInputStream(file);
- byte[] temp = new byte[1280];
- while (inputStream.available() > temp.length) {
- int read = inputStream.read(temp);
- // 寫(xiě)入pcm到播放器
- renderer.write(temp, 0, read);
- }
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
2.2 Player 播放mp3
- /**
- * 播放音頻
- *
- * @param file 源文件位置
- */
- private void playMp3(File file) {
- try {
- player = new Player(getContext());
- FileInputStream in = new FileInputStream(file);
- // 從輸入流獲取FD對(duì)象
- FileDescriptor fd = in.getFD();
- player.setSource(new Source(fd));
- player.prepare();
- player.play();
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
想了解更多內(nèi)容,請(qǐng)?jiān)L問(wèn):
51CTO和華為官方合作共建的鴻蒙技術(shù)社區(qū)