我们在直播中,为了增强真实感,烘托场景氛围需要播放的简短效果音。例如:掌声、笑声、礼物音效、提示音等。在游戏中,有时也需要播放子弹声、碰撞打击声等。
ZegoExpress SDK 提供音效文件播放器,通过 ZegoAudioEffectPlayer 统一管理音效,支持音效播放(可以多音效重叠播放)、播放控制(如暂停播放、音量调节、设置播放进度)、预加载音效等功能。
音效文件播放器支持播放 MP3、M4A、AAC、WAV 格式的本地音频文件。
请参考 下载示例源码 获取源码。
相关源码请查看 “/ZegoExpressExample/Examples/AdvancedAudioProcessing/AudioEffectPlayer” 目录下的文件。
在实现音效文件播放器功能之前,请确保:
调用 ZegoExpressEngine 的 createAudioEffectPlayer 方法创建音效播放器实例。
引擎当前只支持同时创建一个实例,超出后将返回 nil。
@property (nonatomic, strong) ZegoAudioEffectPlayer *audioEffectPlayer;
self.audioEffectPlayer = [[ZegoExpressEngine sharedEngine] createAudioEffectPlayer];
if (!self.audioEffectPlayer) {
NSLog(@"创建音效播放器失败");
}
可以根据需要调用音效播放器的 setEventHandler 方法为播放器设置事件回调,用于监听“音效播放状态改变”等通知。
[self.audioEffectPlayer setEventHandler:self];
- (void)audioEffectPlayer:(ZegoAudioEffectPlayer *)audioEffectPlayer audioEffectID:(unsigned int)audioEffectID playStateUpdate:(ZegoAudioEffectPlayState)state errorCode:(int)errorCode {
NSLog(@"Play state update. ID:%d, state:%lu, err:%d", audioEffectID, (unsigned long)state, (int)errorCode);
}
调用 start 方法播放音效,目前仅支持同时播放 12 个,且只能为本地文件,不支持播放网络资源。 其中 “audioEffectID” 需要保持全局唯一。
loadResource 方法预先加载了音效,则只需要传入预加载时的 “audioEffectID”,“path”(音效资源的路径)字段传空即可。ZegoAudioEffectPlayConfig 中 “playCount” 配置重复次数。如果设置为 “0”,则表示无限重复播放,直到用户手动调用 stop 停止。// 此处示例获取已存放于 App Bundle 内的 test.wav 资源
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"wav"];
ZegoAudioEffectPlayConfig *config = [[ZegoAudioEffectPlayConfig alloc] init];
config.playCount = 1; // 播放一次
config.isPublishOut = YES; // 播放混入推流中
// 使用 0 作为此次的 audioEffectID
[self.audioEffectPlayer start:0 path:filePath config:config];
pause 指定的音效,调用 pauseAll 方法则暂停所有正在播放的音效。resume 方法可以恢复播放 “audioEffectID” 指定的音效,调用 resumeAll 方法则恢复所有已暂停音效。stop 指定的音效,调用 stopAll 方法则停止播放所有音效。// 暂停 0 号 audioEffectID 资源的播放
[self.audioEffectPlayer pause:0];
// 恢复 0 号 audioEffectID 资源的播放
[self.audioEffectPlayer resume:0];
// 停止 0 号 audioEffectID 资源的播放
[self.audioEffectPlayer stop:0];
// 暂停所有资源的播放
[self.audioEffectPlayer pauseAll];
// 恢复所有资源的播放
[self.audioEffectPlayer resumeAll];
// 停止所有资源的播放
[self.audioEffectPlayer stopAll];
setVolume 方法可以设置 “audioEffectID” 指定的音效音量,取值范围为 [0, 200],默认值为 “100”。setVolumeAll 方法则同时设置所有音效音量,取值范围为 [0, 200],默认值为 “100”。// 设置 0 号 audioEffectID 的音量为 100
[self.audioEffectPlayer setVolume:100 audioEffectID:0];
// 设置所有资源的音量为 100
[self.audioEffectPlayer setVolumeAll:100];
getTotalDuration 方法获取单个音效的总时长。getCurrentProgress 方法获取音效当前播放进度。seekTo 方法可以根据需要设置播放进度。// 获取 0 号 audioEffectID 的总时长
unsigned long long totalDuration = [self.audioEffectPlayer getTotalDuration:0];
// 获取 0 号 audioEffectID 的当前播放进度
unsigned long long currentProgress = [self.audioEffectPlayer getCurrentProgress:0];
// 设置 0 号 audioEffectID 的播放进度为总进度的一半
[self.audioEffectPlayer seekTo:(unsigned long long)(totalDuration / 2) audioEffectID:0 callback:^(int errorCode) {
NSLog(@"seekTo result: %d", errorCode);
}];
在频繁播放相同音效场景中,SDK 为了优化重复读文件并解码的性能,提供了预加载音效文件到内存中的功能。
调用 loadResource 方法加载音效资源,可通过 “callback” 参数来监听加载的结果,显示加载成功后方可播放。最多支持同时预加载 15 个本地音效文件(不支持网络资源),并且单个音效文件时长不能超过 30 s,否则加载会报错。
当加载的音效使用完成后,可以调用 unloadResource 接口卸载,以释放相关资源。否则 SDK 将在 ZegoAudioEffectPlayer 实例释放时会自动卸载已加载的音效。
预加载为非必须操作,为了提高性能或者需要反复播放某个特定的音效时推荐使用。
// 此处示例获取已存放于 App Bundle 内的 test.wav 资源
NSString *filePath = [[NSBundle mainBundle] pathForResource:@"test" ofType:@"wav"];
[self.audioEffectPlayer loadResource:filePath audioEffectID:0 callback:^(int errorCode) {
NSLog(@"loadResource result, errorCode: %d", errorCode);
}];
使用完音效播放器后,需要及时调用 destroyAudioEffectPlayer 方法销毁,释放该播放器占用的资源。
[[ZegoExpressEngine sharedEngine] destroyAudioEffectPlayer:self.audioEffectPlayer];
| 方法 | 描述 |
|---|---|
createAudioEffectPlayer |
创建音效播放器实例 |
setEventHandler |
设置音效播放器回调 |
start |
播放音效 |
pause |
暂停播放单个音效 |
pauseAll |
暂停播放所有音效 |
resume |
恢复播放单个音效 |
resumeAll |
恢复播放所有音效 |
stop |
停止播放单个音效 |
stopAll |
停止播放所有音效 |
setVolume |
调节音效音量 |
setVolumeAll |
调节所有音效音量 |
getTotalDuration |
控制播放进度 |
getCurrentProgress |
获取当前播放进度 |
seekTo |
设置指定的播放进度 |
loadResource |
预加载资源 |
unloadResource |
卸载资源 |
destroyAudioEffectPlayer |
销毁音效播放器实例 |
这里有一个很好的答案解释了如何在Ruby中下载文件而不将其加载到内存中:https://stackoverflow.com/a/29743394/4852737require'open-uri'download=open('http://example.com/image.png')IO.copy_stream(download,'~/image.png')我如何验证下载文件的IO.copy_stream调用是否真的成功——这意味着下载的文件与我打算下载的文件完全相同,而不是下载一半的损坏文件?documentation说IO.copy_stream返回它复制的字节数,但是当我还没有下
我正在尝试解析一个文本文件,该文件每行包含可变数量的单词和数字,如下所示:foo4.500bar3.001.33foobar如何读取由空格而不是换行符分隔的文件?有什么方法可以设置File("file.txt").foreach方法以使用空格而不是换行符作为分隔符? 最佳答案 接受的答案将slurp文件,这可能是大文本文件的问题。更好的解决方案是IO.foreach.它是惯用的,将按字符流式传输文件:File.foreach(filename,""){|string|putsstring}包含“thisisanexample”结果的
所以我开始关注ruby,很多东西看起来不错,但我对隐式return语句很反感。我理解默认情况下让所有内容返回self或nil但不是语句的最后一个值。对我来说,它看起来非常脆弱(尤其是)如果你正在使用一个不打算返回某些东西的方法(尤其是一个改变状态/破坏性方法的函数!),其他人可能最终依赖于一个返回对方法的目的并不重要,并且有很大的改变机会。隐式返回有什么意义?有没有办法让事情变得更简单?总是有返回以防止隐含返回被认为是好的做法吗?我是不是太担心这个了?附言当人们想要从方法中返回特定的东西时,他们是否经常使用隐式返回,这不是让你组中的其他人更容易破坏彼此的代码吗?当然,记录一切并给出
给定以下方法:defsome_method:valueend以下语句按我的预期工作:some_method||:other#=>:valuex=some_method||:other#=>:value但是下面语句的行为让我感到困惑:some_method=some_method||:other#=>:other它按预期创建了一个名为some_method的局部变量,随后对some_method的调用返回该局部变量的值。但为什么它分配:other而不是:value呢?我知道这可能不是一件明智的事情,并且可以看出它可能有多么模棱两可,但我认为应该在考虑作业之前评估作业的右侧...我已经在R
我在我的Rails3示例应用程序上使用CarrierWave。我想验证远程位置上传,因此当用户提交无效URL(空白或非图像)时,我不会收到标准错误异常:CarrierWave::DownloadErrorinImageController#createtryingtodownloadafilewhichisnotservedoverHTTP这是我的模型:classPaintingtrue,:length=>{:minimum=>5,:maximum=>100}validates:image,:presence=>trueend这是我的Controller:classPaintingsC
我正在尝试找到一种方法来规范化字符串以将其作为文件名传递。到目前为止我有这个:my_string.mb_chars.normalize(:kd).gsub(/[^\x00-\x7F]/n,'').downcase.gsub(/[^a-z]/,'_')但第一个问题:-字符。我猜这个方法还有更多问题。我不控制名称,名称字符串可以有重音符、空格和特殊字符。我想删除所有这些,用相应的字母('é'=>'e')替换重音符号,并将其余的替换为'_'字符。名字是这样的:“Prélèvements-常规”“健康证”...我希望它们像一个没有空格/特殊字符的文件名:“prelevements_routin
电脑0x0000001A蓝屏错误怎么U盘重装系统教学分享。有用户电脑开机之后遇到了系统蓝屏的情况。系统蓝屏问题很多时候都是系统bug,只有通过重装系统来进行解决。那么蓝屏问题如何通过U盘重装新系统来解决呢?来看看以下的详细操作方法教学吧。 准备工作: 1、U盘一个(尽量使用8G以上的U盘)。 2、一台正常联网可使用的电脑。 3、ghost或ISO系统镜像文件(Win10系统下载_Win10专业版_windows10正式版下载-系统之家)。 4、在本页面下载U盘启动盘制作工具:系统之家U盘启动工具。 U盘启动盘制作步骤: 注意:制作期间,U盘会被格式化,因此U盘中的重要文件请注
1.错误信息:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:requestcanceledwhilewaitingforconnection(Client.Timeoutexceededwhileawaitingheaders)或者:Errorresponsefromdaemon:Gethttps://registry-1.docker.io/v2/:net/http:TLShandshaketimeout2.报错原因:docker使用的镜像网址默认为国外,下载容易超时,需要修改成国内镜像地址(首先阿里
我正在研究使用EventMachine支持的twitter-streamrubygem来跟踪和捕获推文。我对整个事件编程有点陌生。我如何判断我在事件循环中所做的任何处理是否导致我落后?有没有简单的检查方法? 最佳答案 您可以通过使用周期性计时器并打印出耗时来确定延迟。如果您使用的是1秒的计时器,您应该已经过了大约1秒,如果它更长,您就知道您正在减慢react器的速度。@last=Time.now.to_fEM.add_periodic_timer(1)doputs"LATENCY:#{Time.now.to_f-@last}"@
啊,正则表达式有点困惑。我正在尝试删除字符串末尾所有可能的标点符号:ifstr[str.length-1]=='?'||str[str.length-1]=='.'||str[str.length-1]=='!'orstr[str.length-1]==','||str[str.length-1]==';'str.chomp!end我相信有更好的方法来做到这一点。有什么指点吗? 最佳答案 str.sub!(/[?.!,;]?$/,'')[?.!,;]-字符类。匹配这5个字符中的任何一个(注意,。在字符类中并不特殊)?-前一个字符或组