WAAPI+Python使用中的相关问题和学习记录
首先鸣谢:溪夜大佬的博客:https://blog.audiokinetic.com/zh/everyone-can-use-waapi-overview/
本文环境:
Wwise 2019.1.9.7221
python 3.6.2(Anaconda3)
UE4 4.24.3
防伪刮刮乐:原文地址:https://www.cnblogs.com/lingchuL/p/14364085.html
一、配置环境
自己平时都是python 3.6.3裸奔,这次想试试Anaconda3,不得不说,有一个管理环境的工具确实要方便一些。
不要使用python 3.8!因为目前(2021.2),WAAPI的源码无法完全兼容python3.8。虽然pypl上写着自己支持3.8和3.9,但就是会因为time.block这个方法被3.8舍弃而没法import waapi-client。
1. Anaconda3的安装:https://segmentfault.com/a/1190000022797661
2. 配置 Anaconda 并在本地环境中通过 pip 添加 waapi-client:
https://zhuanlan.zhihu.com/p/25198543
3. 更新pip
默认的pip应该都是9.0.1的,但就安装不了waapi-client。要先更新一下pip。
但是最tm离谱的是,用pip install --upgrade pip来更新的话,很有可能因为网络原因反而继续提示你用--upgrade来更新pip。十足的鸡生蛋。根据这篇文章,使用如下命令:
python -m pip install --upgrade pip -i https://pypi.douban.com/simple
大概是镜像吧。
二、使用中的记录
1. pprint的作用
https://blog.csdn.net/qq_24185239/article/details/80977556
总的来说,pprint打印json的排版比print的更好看。通过 from pprint import pprint 来使用pprint。
2. WAAPI是什么?
如果你有阅读一点Wwise中对于WAAPI的介绍,你应该知道AK官方提供了几种方式来连接到Wwise:WAMP、HTTP POST和Wwise插件。
我这就只会记录WAMP,毕竟它最nb。
你可能很想知道Wwise的WAMP到底是什么,总之,先记住WAMP就类似于一种网络连接,理论上它可以连通你的程序和另一台电脑的Wwise,但它默认情况下只负责连接你的电脑和你自己电脑里的Wwise。如果你有使用过Unity/Unreal和Wwise进行实时调试,应该也会对上述过程有所理解(这一切就类似于,在Profiler视图中点击的Connect)。可以粗暴地想象为Wwise是个网站,而这个网站默认情况下就建在你的电脑里。总之,WAMP就是这样一个和Wwise通信的方式,而WAAPI就是Wwise官方推出的、钦定的,和Wwise通信使用的一系列方法、语法和规则。
2.1 连接建立
先来看下和Wwise通信的代码在python中大致模样。感觉首先知道代码大概长什么样,每部分在干什么,然后再去学WAAPI里那些细节的规则会更高效。
这部分大概说来我就是翻译了一下waapi-client库在其github页面中readme的部分内容,其余部分可以通过原文学习:https://github.com/audiokinetic/waapi-client-python
总的来说,先要引入WaapiClient。记忆角度而言的话:刚才说了,WAMP就相当于你的电脑/你自己编写的程序去连接Wwise。所以你现在在写的python代码/程序相当于就是Client(客户端)。Wwise就是那个服务器。
from waapi import WaapiClient
然后,有两种方法进行“客户端”的建立。
(1)
with WaapiClient() as client:
然后,就可以使用client进行后续的和Wwise的通信。但官方表示,这种方式会导致,client在with程序块之后会自动关闭。所以如果你希望,只是定义一个client,并且随时进行通信,可以使用第二种建立方式。
(2)
client=WaapiClient()
然后你就可以随时使用client进行通信了。
如果你有一定python基础,建议你看看WwapiClient()类的源码,还是比较清晰的:https://github.com/audiokinetic/waapi-client-python/blob/0d746223f56be6749dfaf0d78a6f10ffd2904c23/waapi/client/client.py#L30
如果你没有基础,那就继续看我的记录吧。
2.2 有了Client后要做什么
首先默认你拥有最基本的“面向对象”的编程知识,如果你是一名纯音效设计师没有学过编程,你可以考虑去廖雪峰的python教程中学习一下面向对象的基本知识。
client有一些方法,如果你没有基础,但又跳过了上面这段话的建议。我稍微说下,client就相当于游戏里一个角色,这对游戏音效设计师的你来说应该很熟悉吧?然后这个角色可能有很多技能,在面向对象的编程世界里,我们就把“角色、角色的技能”称为“对象、对象的方法”。
大致方法列举如下,再次推荐浏览源码,注释非常清晰。
2.2.1 call(self, _uri, *args, **kwargs)
这个方法,用来进行远程程序调用(Remote Procedure Call, RPC),这六个字在Wwise官网也能见到。
self,*args,**kwargs都是很多方法都会有的东西。而_uri则是远程程序的URI,它的所需类型为str。不用太在意URI原意是什么,因为其实这个位置上我们只需要指定WAAPI为我们提供的远程程序就行了。比如如果要获取wwise的基本信息,我们会使用名为ak.wwise.core.getInfo的这个远程程序!你可能还是一脸懵逼,但这部分暂时还不用太过在意!后文会详细地介绍它。总之你就记住,官方WAAPI已经提供了一大堆诸如刚才提到的getInfo的远程程序,然后这些程序都有各自的功能!
虽然说*args,**kwargs是所有程序都会有的东西,但WAAPI里有的远程程序可能需要额外的参数,这些参数在编写代码时候也有着各自的规定!具体的规定对每个远程程序而言都是不一样的。比如刚才的getInfo,就不需要任何参数。这部分也会在之后介绍!现在只需要记住后面这两个东西之后还有一出戏份就好了!因为我们现在还是在介绍client的方法本身。
2.2.2 subscribe(self, _uri, callback_or_handler=None, *args, **kwargs)
没骗你吧?self,*args,**kwargs都是很多方法都会有的东西。而_uri也和刚才的意思一样。
这个方法,用来进行订阅主题(Subscribe to a topic)。是不是很不明所以,但官方就是这么叫它的,可能这就是程序员的浪漫吧(不是)。
这个方法配合它的远程程序会比较好懂,所以在这里先举个例子吧:比如,这个方法有一个配套远程程序叫做ak.wwise.core.audio.imported,看这串名字都看出来了吧,它是一个,会在你在wwise导入文件后通知你的程序。也就是说,你使用subscribe连接到这个audio.imported的远程程序。然后远程程序会开始持续检测你是否导入文件,并且会在检测到导入操作后,以回传的方式通知你。而回传的接口,就是你在callback_or_handler中给它的一个函数句柄。
源码中明确提醒,callback会从另一个线程返回,所以需要你的程序自行处理线程之间的冲突/竞争条件问题。所以再次建议强行读到这里的人,通过上文提到的廖雪峰的python教程,了解下面向对象和多线程编程,再来学习WAAPI。否则光是多线程的冲突就可能有麻烦的坑。
值得一记的是所谓的callback_or_handler,总之只要是可以调用的东西就可以了。比如,函数,对象方法,甚至是实现了__call__方法的类实例,特别地,还有lambda函式。lambda的用法可以粗暴地如下记忆:函数名=lambda 参数列表:函数表达式。比如,test=lambda a,b:print(a+b),这样,就可以用test(1,2)之类的函数表达了。是不是超没用?反正我觉得挺装杯的,知道就行了。
还值得一提的是,subscribe的返回值类型是一个Wwise官方自己定义的抽象类,叫做EventHandler,有基础的话也可以去看看它的源码。但是我们只要知道几点这个类有用的方法就行了。
unsubscribe:用于随时取消订阅。
bind:用于绑定一个新的接受返回通知的callback_or_handler。其实,官方源码也写了,之所以写了这个抽象类,就是为了方便我们随时切换绑定的接受返回通知函数。
以上可能有一点杂乱了,但是比对着下面这段代码应该就会立刻思路清晰!
from waapi import WaapiClient # 连接Wwise (使用默认URL,也就是说会连接到自己电脑上的Wwise)
client = WaapiClient() # 使用client的call方法,进行远程程序调用,调用的是叫做getInfo的远程程序,然后远程程序会把它运行的结果返回给result。
result = client.call("ak.wwise.core.getInfo") # 使用client的subscribe方法,进行订阅主题,订阅的是object.created的远程程序,这个程序会在有wwise对象被创建时返回通知。handler用于持续地控制这个订阅。
handler = client.subscribe(
"ak.wwise.core.object.created",
lambda object: print("Object created: " + str(object))
) # 随时都可以切换接收通知的函数
def my_callback(object):
print("Different callback: " + str(object)) handler.bind(my_callback) # 使用handler的方法unsubscribe取消订阅
handler.unsubscribe() # 使用client的方法disconnect断开和Wwise的连接
client.disconnect()
2.3 远程程序详细介绍
首先,其实Wwise自身提供的文档介绍非常详细:https://www.audiokinetic.com/zh/library/edge/?source=SDK&id=waapi_index.html
用一个结构相对比较简单且有特殊结构的远程程序来举例,它就是ak.wwise.core.object.get。
调用这个程序,需要给予Wwise两大类参数:Arguments和Options。首先,前者的Wwise文档如图。

根据表格最下方的标注,带星号的项目都是必要的参数。对这里的get而言,就是from参数必须。(因为transform本身不是必须的,所以虽然它下面有一些transform.select是必须的,但总的来说并不是必须的。)
还有就是,中间的Type列中,会有一些行内容为 one of、any of,其实这就是在说,下面几行的都可以。比如from,既可以用id指定,也可以用path指定,你会发现每一个都对应了下面带星号的Name。
一定要注意中间Type为每个参数指定的类型,按照类型来书写参数才不会出错。
而对于Options,则没有什么必须提供的参数。并且其书写规则与上面Arguments表的书写规则一致。

虽然熟悉了之后这表看着也挺快的,但这种书写格式对你可能不够亲切。如果那样的话,你可以使用json格式转换器,把上面Arguments那张图最底下的Arguments Schema里的内容,转换换为较易阅读的格式,转换后如图:

首先是这个样子,最大类别中有一个required的参数,为from。符合我们上面直接读表的结论。接下来,是全部properties的内容如图。

所有的参数,共有from和transform两大类。这也与我们上面直接读表的结论一致。最后,再象征性地展开properties里的from和transform看看。

可以发现,分别显示了六个和四个可选参数类型,其实如果再点开,就会发现它们分别对应于上面我们在表里from和transform对应的Type里看见的几个参数名了。这可能会适合一些人的思维习惯吧。
2.4 把至此为止的知识结合起来
然后,在写代码的时候,需要注意,call方法只能调用Functions的远程函数,而subscribe只能调用Topics的远程函数!
而2.3中提到的这一大堆参数,在书写时,官方有几种格式可供选择。但推荐使用类似于以下的格式。
args={
"from": {
"id": [
"{A076AA65-B71A-45BB-8841-5A20C52CE727}",
"{2028C899-8300-4667-ADD0-ED10467BD91E}",
"{24979032-B170-43E3-A2E4-469E0193E2C3}"
] }
}
总之就是类似于python中的字典的形式。细心的话会发现这里只有args,那说好的kwargs呢,其实官方实现了一个能将输入参数合并的内部方法,刚才说的“几种格式可供选择”也是得益于此。
然后,调用call的时候,就是形如以下代码:
client.call("ak.wwise.core.object.get",args)
(持续补充)
WAAPI+Python使用中的相关问题和学习记录的更多相关文章
- Python全栈工程师系列学习之学习记录
@ 目录 前言 Day 01 一.python的历史和种类 二.安装python解释器以及配置环境变量 三.变量.常量和注释 Day 02 Day 03 Day 04 Day 05 Day 06 一. ...
- python 加密算法及其相关模块的学习(hashlib,random,string,math)
加密算法介绍 一,HASH Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种 ...
- python加密算法及其相关模块的学习(hashlib,RSA,random,string,math)
加密算法介绍 一,HASH Hash,一般翻译做“散列”,也有直接音译为”哈希”的,就是把任意长度的输入(又叫做预映射,pre-image),通过散列算法,变换成固定长度的输出,该输出就是散列值.这种 ...
- Python标准库之核心模块学习记录
内建函数和异常 包括__builtin__模块和exceptions模块 操作系统接口模块 包括提供文件和进程处理功能的os模块,提供平台独立的文件名处理(分拆目录名,文件名,后缀等)的os.path ...
- 流畅的python第二十章属性描述符学习记录
描述符是对多个属性运用相同存取逻辑的一种方式.例如,Django ORM 和 SQL Alchemy等 ORM 中的字段类型是描述符,把数据库记录中字段里的数据与 Python 对象的属性对应起来.描 ...
- 流畅的python第五章一等函数学习记录
在python中,函数是一等对象,一等对象是满足以下条件的程序实体 1在运行时创建 2能复制给变量或数据结构的元素 3能作为参数传给函数 4能作为函数的返回结果 高阶函数(接受函数作为参数或者把函数作 ...
- Python学习记录day6
title: Python学习记录day6 tags: python author: Chinge Yang date: 2016-12-03 --- Python学习记录day6 @(学习)[pyt ...
- Python学习记录day5
title: Python学习记录day5 tags: python author: Chinge Yang date: 2016-11-26 --- 1.多层装饰器 多层装饰器的原理是,装饰器装饰函 ...
- Python之路,Day21 - 常用算法学习
Python之路,Day21 - 常用算法学习 本节内容 算法定义 时间复杂度 空间复杂度 常用算法实例 1.算法定义 算法(Algorithm)是指解题方案的准确而完整的描述,是一系列解决问题的 ...
随机推荐
- 浅入 .NET Core 中的内存和GC知识
目录 托管代码 自动内存管理 参考资料: [1]https://docs.microsoft.com/zh-cn/dotnet/standard/managed-code [2]:https://do ...
- Salesforce 大数据量处理篇(二)Index
本篇参考: https://developer.salesforce.com/docs/atlas.en-us.202.0.salesforce_large_data_volumes_bp.meta/ ...
- WPF Line 的颜色过度动画
<Line Grid.Column="2" Grid.ColumnSpan="2" VerticalAlignment="Center" ...
- Java 并发编程要点
使用线程 有三种使用线程的方法: 实现 Runnable 接口: 实现 Callable 接口: 继承 Thread 类. 实现 Runnable 和 Callable 接口的类只能当做一个可以在线程 ...
- LeetCode109 将有序链表转为二叉搜索树
给定一个单链表,其中的元素按升序排序,将其转换为高度平衡的二叉搜索树. 本题中,一个高度平衡二叉树是指一个二叉树每个节点 的左右两个子树的高度差的绝对值不超过 1. 示例: 给定的有序链表: [-10 ...
- js的函数-function
function函数 function的英文是[功能],[数] 函数:职责:盛大的集会的意思 在js里,就是函数的意思.在Java里叫做方法. 定义函数 function fun(参数){ //函数体 ...
- 【Linux】以001格式循环到100保证位数是3位
这里有一个前提,要保证数位是相同的 确实数字是1-100 但是数位是不同的,需要统一一下位数必须是3位的 这个问题在很多论坛上用的都是printf这个命令,确实可以达到这个效果,但是没有我下面介绍的 ...
- 【Linux】添加硬盘不需要重启服务器
添加硬盘之后,不用重启服务器 执行下面的语句 ls /sys/class/scsi_host 查看下面有多少host 我这里有三个host 分别执行 echo "- - -" &g ...
- VBScript调用winscp,实现sftp操作
最新有一个需求,需要在ssis中调用sftp下载文件,由于服务器上只有framework2.0,并且需要用sqlserver代理调用作业,限制了很多. 首先用的是脚本任务,进程调用winscp.com ...
- Py-时间,随机,os,sys,jsonpickle序列化,shelve,xml模块
内置模块 1.时间模块 第一:time.time()是时间戳 时间戳默认是 从1970年到现在过的秒数,是一个很长的数值它可以做时间的计算以及显示 第二:localtime() 获取当前的时间,按元组 ...