鸿蒙(API 12 Beta3版)【使用AVPlayer开发音频播放功能(C/C++)】音视播放与录制

本文主要是介绍鸿蒙(API 12 Beta3版)【使用AVPlayer开发音频播放功能(C/C++)】音视播放与录制,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

使用AVPlayer可以实现端到端播放原始媒体资源,本开发指导将以完整地播放一首音乐作为示例,向开发者讲解AVPlayer音频播放相关功能。

播放的全流程包含:创建AVPlayer,设置播放资源,设置播放参数(音量/倍速/焦点模式),播放控制(播放/暂停/跳转/停止),重置,销毁资源。

在进行应用开发的过程中,开发者可以通过AVPlayer的callback主动获取播放过程信息。如果应用在音频播放器处于错误状态时执行操作,系统可能会抛出异常或生成其他未定义的行为。

图1 播放状态变化示意图

1

状态的详细说明请参考[AVPlayerState]。当播放处于prepared / playing / paused / completed状态时,播放引擎处于工作状态,这需要占用系统较多的运行内存。当客户端暂时不使用播放器时,调用reset()或release()回收内存资源,做好资源利用。

开发建议

当前指导仅介绍如何实现媒体资源播放,在应用开发过程中可能会涉及后台播放、播放冲突等情况,请根据实际需要参考以下说明。

  • 如果要实现后台播放或熄屏播放,需要接入[AVSession(媒体会话)]和[申请长时任务],避免播放被系统强制中断。此功能仅提供ArkTS API。
  • 应用在播放过程中,若播放的媒体数据涉及音频,根据系统音频管理策略(参考[处理音频焦点事件]),可能会被其他应用打断,建议应用通过[OH_AVPlayer_SetPlayerCallback()]主动监听音频打断事件[AV_INFO_TYPE_INTERRUPT_EVENT],根据其内容提示,做出相应的处理,避免出现应用状态与预期效果不一致的问题。
  • 面对设备同时连接多个音频输出设备的情况,应用可以通过[OH_AVPlayer_SetPlayerCallback()]主动监听音频输出设备改变事件[AV_INFO_TYPE_AUDIO_OUTPUT_DEVICE_CHANGE],从而做出相应处理。

开发步骤及注意事项

在 CMake 脚本中链接动态库

target_link_libraries(sample PUBLIC libavplayer.so)

开发者通过引入[avplayer.h]、[avpalyer_base.h]和[native_averrors.h]头文件,使用音频播放相关API。

  1. 创建实例OH_AVPlayer_Create(),AVPlayer初始化idle状态。

  2. 设置业务需要的监听事件OH_AVPlayer_SetPlayerCallback(),搭配全流程场景使用。支持的监听事件包括:

    事件类型说明
    OH_AVPlayerOnInfo必要事件,监听播放器的过程信息。
    OH_AVPlayerOnError必要事件,监听播放器的错误信息。
  3. 设置资源:调用OH_AVPlayer_SetURLSource(),设置属性url,AVPlayer进入initialized状态。

  4. (可选)设置音频流类型:调用OH_AVPlayer_SetAudioRendererInfo(),设置AVPlayer音频流类型。

  5. (可选)设置音频打断模式:调用OH_AVPlayer_SetAudioInterruptMode(),设置AVPlayer音频流打断模式。

  6. 准备播放:调用OH_AVPlayer_Prepare(),AVPlayer进入prepared状态,此时可以获取时长,设置音量。

  7. (可选)设置音频音效模式:调用OH_AVPlayer_SetAudioEffectMode(),设置AVPlayer音频音效模式。

  8. 音频播控:播放OH_AVPlayer_Play(),暂停OH_AVPlayer_Pause(),跳转OH_AVPlayer_Seek(),停止OH_AVPlayer_Stop() 等操作。

  9. (可选)更换资源:调用OH_AVPlayer_Reset()重置资源,AVPlayer重新进入idle状态,允许更换资源url。

  10. 退出播放:调用OH_AVPlayer_Release()销毁实例,AVPlayer进入released状态,退出播放。

完整示例

#include "napi/native_api.h"#include <multimedia/player_framework/avplayer.h>
#include <multimedia/player_framework/avplayer_base.h>
#include <multimedia/player_framework/native_averrors.h>static char *Url;void OnInfo(OH_AVPlayer *player, AVPlayerOnInfoType type, int32_t extra)
{int32_t ret;switch (type) {case AV_INFO_TYPE_STATE_CHANGE:switch (extra) {case AV_IDLE: // 成功调用reset接口后触发该状态机上报
//                    ret = OH_AVPlayer_SetURLSource(player, url); // 设置url
//                    if (ret != AV_ERR_OK) {
//                    // 处理异常
//                    }break;case AV_INITIALIZED: ret = OH_AVPlayer_Prepare(player); //设置播放源后触发该状态上报if (ret != AV_ERR_OK) {// 处理异常}break;case AV_PREPARED:            
//                    ret = OH_AVPlayer_SetAudioEffectMode(player, EFFECT_NONE); // 设置音频音效模式
//                    if (ret != AV_ERR_OK) {
//                    //处理异常    
//                    }  ret = OH_AVPlayer_Play(player); // 调用播放接口开始播放if (ret != AV_ERR_OK) {// 处理异常}break;case AV_PLAYING:  
//                    ret = OH_AVPlayer_Pause(player); //调用暂停接口暂停播放
//                    if (ret != AV_ERR_OK) {
//                    // 处理异常
//                    }break;case AV_PAUSED:  
//                    ret = OH_AVPlayer_Play(player); // 再次播放接口开始播放
//                    if (ret != AV_ERR_OK) {
//                    // 处理异常
//                    }break;case AV_STOPPED:  ret = OH_AVPlayer_Release(player); //调用reset接口初始化avplayer状态if (ret != AV_ERR_OK) {// 处理异常}break;case AV_COMPLETED:  ret = OH_AVPlayer_Stop(player);// 调用播放结束接口if (ret != AV_ERR_OK) {// 处理异常}break;default:break;}break;case AV_INFO_TYPE_POSITION_UPDATE:// do somethingbreak;default:break;}
}void OnError(OH_AVPlayer *player, int32_t errorCode, const char *errorMsg)
{// do something
}// 调用播放方法时,需要在index.d.ts文件内描述映射的play方法,需要传入一个string类型的参数
// ets文件调用播放方法时,传入文件路径 testNapi.play("/data/test/test.mp3")
static napi_value Play(napi_env env, napi_callback_info info)
{size_t argc = 1;napi_value args[1] = {nullptr};napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);// 获取参数类型napi_valuetype stringType;if (napi_ok != napi_typeof(env, args[0], &stringType)) {// 处理异常return nullptr;}// 参数校验if (napi_null == stringType) {// 处理异常return nullptr;}// 获取传递的string长度size_t length = 0;if (napi_ok != napi_get_value_string_utf8(env, args[0], nullptr, 0, &length)) {// 处理异常return nullptr;}// 如果传入的是"",则直接返回if (length == 0) {// 处理异常return nullptr;}// 读取传入的string放入buffer中char *url = new char[length + 1];if (napi_ok != napi_get_value_string_utf8(env, args[0], url, length + 1, &length)) {delete[] url;url = nullptr;// 处理异常return nullptr;}Url = url;// 创建播放实例OH_AVPlayer *player = OH_AVPlayer_Create();AVPlayerCallback callback;callback.onInfo = OnInfo;callback.onError = OnError;// 设置回调,监听信息int32_t ret = OH_AVPlayer_SetPlayerCallback(player, callback);if (ret != AV_ERR_OK) {// 处理异常}ret = OH_AVPlayer_SetURLSource(player, url); // 设置urlif (ret != AV_ERR_OK) {// 处理异常}// 设置音频流类型OH_AudioStream_Usage streamUsage = OH_AudioStream_Usage::AUDIOSTREAM_USAGE_UNKNOWN;ret = OH_AVPlayer_SetAudioRendererInfo(player, streamUsage);if (ret != AV_ERR_OK) {//处理异常    }// 设置音频流打断模式OH_AudioInterrupt_Mode interruptMode = OH_AudioInterrupt_Mode::AUDIOSTREAM_INTERRUPT_MODE_INDEPENDENT;ret = OH_AVPlayer_SetAudioInterruptMode(player, interruptMode);if (ret != AV_ERR_OK) {//处理异常    }napi_value value;napi_create_int32(env, 0, &value);return value;
}EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports)
{napi_property_descriptor desc[] = {{ "play", nullptr, Play, nullptr, nullptr, nullptr, napi_default, nullptr }};napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);return exports;
}
EXTERN_C_ENDstatic napi_module demoModule = {.nm_version =1,.nm_flags = 0,.nm_filename = nullptr,.nm_register_func = Init,.nm_modname = "entry",.nm_priv = ((void*)0),.reserved = { 0 },
};extern "C" __attribute__((constructor)) void RegisterEntryModule(void)
{napi_module_register(&demoModule);
}

最后呢

很多开发朋友不知道需要学习那些鸿蒙技术?鸿蒙开发岗位需要掌握那些核心技术点?为此鸿蒙的开发学习必须要系统性的进行。

而网上有关鸿蒙的开发资料非常的少,假如你想学好鸿蒙的应用开发与系统底层开发。你可以参考这份资料,少走很多弯路,节省没必要的麻烦。由两位前阿里高级研发工程师联合打造的《鸿蒙NEXT星河版OpenHarmony开发文档》里面内容包含了(ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等)鸿蒙(Harmony NEXT)技术知识点

如果你是一名Android、Java、前端等等开发人员,想要转入鸿蒙方向发展。可以直接领取这份资料辅助你的学习。下面是鸿蒙开发的学习路线图。

在这里插入图片描述

针对鸿蒙成长路线打造的鸿蒙学习文档。话不多说,我们直接看详细鸿蒙(OpenHarmony )手册(共计1236页)与鸿蒙(OpenHarmony )开发入门视频,帮助大家在技术的道路上更进一步。

  • 《鸿蒙 (OpenHarmony)开发学习视频》
  • 《鸿蒙生态应用开发V2.0白皮书》
  • 《鸿蒙 (OpenHarmony)开发基础到实战手册》
  • OpenHarmony北向、南向开发环境搭建
  • 《鸿蒙开发基础》
  • 《鸿蒙开发进阶》
  • 《鸿蒙开发实战》

在这里插入图片描述

总结

鸿蒙—作为国家主力推送的国产操作系统。部分的高校已经取消了安卓课程,从而开设鸿蒙课程;企业纷纷跟进启动了鸿蒙研发。

并且鸿蒙是完全具备无与伦比的机遇和潜力的;预计到年底将有 5,000 款的应用完成原生鸿蒙开发,未来将会支持 50 万款的应用。那么这么多的应用需要开发,也就意味着需要有更多的鸿蒙人才。鸿蒙开发工程师也将会迎来爆发式的增长,学习鸿蒙势在必行! 自↓↓↓拿
1

这篇关于鸿蒙(API 12 Beta3版)【使用AVPlayer开发音频播放功能(C/C++)】音视播放与录制的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1107544

相关文章

Java中流式并行操作parallelStream的原理和使用方法

《Java中流式并行操作parallelStream的原理和使用方法》本文详细介绍了Java中的并行流(parallelStream)的原理、正确使用方法以及在实际业务中的应用案例,并指出在使用并行流... 目录Java中流式并行操作parallelStream0. 问题的产生1. 什么是parallelS

C++中unordered_set哈希集合的实现

《C++中unordered_set哈希集合的实现》std::unordered_set是C++标准库中的无序关联容器,基于哈希表实现,具有元素唯一性和无序性特点,本文就来详细的介绍一下unorder... 目录一、概述二、头文件与命名空间三、常用方法与示例1. 构造与析构2. 迭代器与遍历3. 容量相关4

Linux join命令的使用及说明

《Linuxjoin命令的使用及说明》`join`命令用于在Linux中按字段将两个文件进行连接,类似于SQL的JOIN,它需要两个文件按用于匹配的字段排序,并且第一个文件的换行符必须是LF,`jo... 目录一. 基本语法二. 数据准备三. 指定文件的连接key四.-a输出指定文件的所有行五.-o指定输出

Linux jq命令的使用解读

《Linuxjq命令的使用解读》jq是一个强大的命令行工具,用于处理JSON数据,它可以用来查看、过滤、修改、格式化JSON数据,通过使用各种选项和过滤器,可以实现复杂的JSON处理任务... 目录一. 简介二. 选项2.1.2.2-c2.3-r2.4-R三. 字段提取3.1 普通字段3.2 数组字段四.

C++中悬垂引用(Dangling Reference) 的实现

《C++中悬垂引用(DanglingReference)的实现》C++中的悬垂引用指引用绑定的对象被销毁后引用仍存在的情况,会导致访问无效内存,下面就来详细的介绍一下产生的原因以及如何避免,感兴趣... 目录悬垂引用的产生原因1. 引用绑定到局部变量,变量超出作用域后销毁2. 引用绑定到动态分配的对象,对象

Linux kill正在执行的后台任务 kill进程组使用详解

《Linuxkill正在执行的后台任务kill进程组使用详解》文章介绍了两个脚本的功能和区别,以及执行这些脚本时遇到的进程管理问题,通过查看进程树、使用`kill`命令和`lsof`命令,分析了子... 目录零. 用到的命令一. 待执行的脚本二. 执行含子进程的脚本,并kill2.1 进程查看2.2 遇到的

详解SpringBoot+Ehcache使用示例

《详解SpringBoot+Ehcache使用示例》本文介绍了SpringBoot中配置Ehcache、自定义get/set方式,并实际使用缓存的过程,文中通过示例代码介绍的非常详细,对大家的学习或者... 目录摘要概念内存与磁盘持久化存储:配置灵活性:编码示例引入依赖:配置ehcache.XML文件:配置

Java 虚拟线程的创建与使用深度解析

《Java虚拟线程的创建与使用深度解析》虚拟线程是Java19中以预览特性形式引入,Java21起正式发布的轻量级线程,本文给大家介绍Java虚拟线程的创建与使用,感兴趣的朋友一起看看吧... 目录一、虚拟线程简介1.1 什么是虚拟线程?1.2 为什么需要虚拟线程?二、虚拟线程与平台线程对比代码对比示例:三

k8s按需创建PV和使用PVC详解

《k8s按需创建PV和使用PVC详解》Kubernetes中,PV和PVC用于管理持久存储,StorageClass实现动态PV分配,PVC声明存储需求并绑定PV,通过kubectl验证状态,注意回收... 目录1.按需创建 PV(使用 StorageClass)创建 StorageClass2.创建 PV

一文详解Python如何开发游戏

《一文详解Python如何开发游戏》Python是一种非常流行的编程语言,也可以用来开发游戏模组,:本文主要介绍Python如何开发游戏的相关资料,文中通过代码介绍的非常详细,需要的朋友可以参考下... 目录一、python简介二、Python 开发 2D 游戏的优劣势优势缺点三、Python 开发 3D