如何在 WatchOS 3 中播放将在手表扬声器上播放的自定义声音
How can I play a custom sound in WatchOS 3 that will playback on the watch speakers
我了解到我们现在可以在 watchos 3 的 Apple Watch 上播放自定义声音。
根据 Apple 的公告,显然有但我没有测试它的示例:使用 SCNAudioSource 或 SCNAudioPlayer 实现的 3D 空间音频。相反,请使用 playAudioSource:waitForCompletion: 或 WatchKit 声音或触觉 API。在这里找到:https://developer.apple.com/library/prerelease/content/releasenotes/General/WhatsNewInwatchOS/Articles/watchOS3.html
有人可以举一个简单的例子吗?我没有在我的应用程序中使用 SceneKit,因为我不需要它,但如果这是播放自定义声音的唯一方法,那么我想知道完成此操作所需的最少代码。最好在 Objective c 中,但我会采用任何形状。我可以使用 SpriteKit,如果这样也更容易的话。
这是我目前拥有的,但它不起作用:
SCNNode * audioNode = [[SCNNode alloc] init];
SCNAudioSource * audioSource = [SCNAudioSource audioSourceNamed:@"mysound.mp3"];
SCNAudioPlayer * audioPlayer = [SCNAudioPlayer audioPlayerWithSource:audioSource];
[audioNode addAudioPlayer:audioPlayer];
SCNAction * play = [SCNAction playAudioSource:audioSource waitForCompletion:YES];
[audioNode runAction:play];
这是Objective-c但是可以翻译成Swift
我最终使用 AVAudioEngine
和 AVAudioPlayerNode
在 Apple Watch 上播放音频。
操作要点如下:
我在 AudioPlayer 的 init
方法中调用了以下代码(它是封装功能的 NSObject 子类)
_audioPlayer = [[AVAudioPlayerNode alloc] init];
_audioEngine = [[AVAudioEngine alloc] init];
[_audioEngine attachNode:_audioPlayer];
AVAudioFormat *stereoFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:44100 channels:2];
[_audioEngine connect:_audioPlayer to:_audioEngine.mainMixerNode format:stereoFormat];
if (!_audioEngine.isRunning) {
NSError* error;
[_audioEngine startAndReturnError:&error];
}
我有一个缓存设置,所以我不会在每次想要播放声音时都重新创建 AVAudioFile
资源,但您不需要。
接下来创建一个 AVAudioFile
对象:
NSError *error;
NSBundle* appBundle = [NSBundle mainBundle];
NSURL *url = [NSURL fileURLWithPath:[appBundle pathForResource:key ofType:@"aifc"]];
AVAudioFile *asset = [[AVAudioFile alloc] initForReading:url &error];
然后播放该文件:
[_audioPlayer scheduleFile:asset atTime:nil completionHandler:nil];
[_audioPlayer play];
更新:如果应用进入休眠状态或进入后台,音频可能会停止 playing/fade。通过激活音频会话,这将被阻止。
NSError *error;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
if (error) {
NSLog(@"AVAudioSession setCategory ERROR: %@", error.localizedDescription);
}
[[AVAudioSession sharedInstance] setActive:YES error:&error];
if (error) {
NSLog(@"AVAudioSession setActive ERROR: %@", error.localizedDescription);
}
我没有去处理任何错误,但这应该可行。不要忘记在实施文件的顶部 #import <AVFoundation/AVFoundation.h>
。
我可以确认,@ApperleyA 解决方案确实有效!
这里是 swift 版本:
var _audioPlayer : AVAudioPlayerNode!
var _audioEngine : AVAudioEngine!
func playAudio()
{
if (_audioPlayer==nil) {
_audioPlayer = AVAudioPlayerNode()
_audioEngine = AVAudioEngine()
_audioEngine.attach(_audioPlayer)
let stereoFormat = AVAudioFormat(standardFormatWithSampleRate: 44100, channels: 2)
_audioEngine.connect(_audioPlayer, to: _audioEngine.mainMixerNode, format: stereoFormat)
do {
if !_audioEngine.isRunning {
try _audioEngine.start()
}
} catch {}
}
if let path = Bundle.main.path(forResource: "test", ofType: "mp3") {
let fileUrl = URL(fileURLWithPath: path)
do {
let asset = try AVAudioFile(forReading: fileUrl)
_audioPlayer.scheduleFile(asset, at: nil, completionHandler: nil)
_audioPlayer.play()
} catch {
print ("asset error")
}
}
}
这在模拟器中对我有用
let soundPath = Bundle.main.path(forResource: "cheerMP3", ofType: "mp3")
let soundPathURL = URL(fileURLWithPath: soundPath!)
let audioFile = WKAudioFileAsset(url: soundPathURL)
let audioItem = WKAudioFilePlayerItem(asset: audioFile)
let audioPlayer = WKAudioFilePlayer.init(playerItem: audioItem)
if audioPlayer.status == .readyToPlay
{
audioPlayer.play()
}
else
{
print("Not ready!!")
}
但前提是我在 audioPlayer.play() 和最后一个 } 之后都有断点。
dunqan,你在文件的顶部放了什么,导入语句?我无法包含
导入 AVFoundation
使用Xcode 8.2.1
没有错误
我了解到我们现在可以在 watchos 3 的 Apple Watch 上播放自定义声音。
根据 Apple 的公告,显然有但我没有测试它的示例:使用 SCNAudioSource 或 SCNAudioPlayer 实现的 3D 空间音频。相反,请使用 playAudioSource:waitForCompletion: 或 WatchKit 声音或触觉 API。在这里找到:https://developer.apple.com/library/prerelease/content/releasenotes/General/WhatsNewInwatchOS/Articles/watchOS3.html
有人可以举一个简单的例子吗?我没有在我的应用程序中使用 SceneKit,因为我不需要它,但如果这是播放自定义声音的唯一方法,那么我想知道完成此操作所需的最少代码。最好在 Objective c 中,但我会采用任何形状。我可以使用 SpriteKit,如果这样也更容易的话。
这是我目前拥有的,但它不起作用:
SCNNode * audioNode = [[SCNNode alloc] init];
SCNAudioSource * audioSource = [SCNAudioSource audioSourceNamed:@"mysound.mp3"];
SCNAudioPlayer * audioPlayer = [SCNAudioPlayer audioPlayerWithSource:audioSource];
[audioNode addAudioPlayer:audioPlayer];
SCNAction * play = [SCNAction playAudioSource:audioSource waitForCompletion:YES];
[audioNode runAction:play];
这是Objective-c但是可以翻译成Swift
我最终使用 AVAudioEngine
和 AVAudioPlayerNode
在 Apple Watch 上播放音频。
操作要点如下:
我在 AudioPlayer 的 init
方法中调用了以下代码(它是封装功能的 NSObject 子类)
_audioPlayer = [[AVAudioPlayerNode alloc] init];
_audioEngine = [[AVAudioEngine alloc] init];
[_audioEngine attachNode:_audioPlayer];
AVAudioFormat *stereoFormat = [[AVAudioFormat alloc] initStandardFormatWithSampleRate:44100 channels:2];
[_audioEngine connect:_audioPlayer to:_audioEngine.mainMixerNode format:stereoFormat];
if (!_audioEngine.isRunning) {
NSError* error;
[_audioEngine startAndReturnError:&error];
}
我有一个缓存设置,所以我不会在每次想要播放声音时都重新创建 AVAudioFile
资源,但您不需要。
接下来创建一个 AVAudioFile
对象:
NSError *error;
NSBundle* appBundle = [NSBundle mainBundle];
NSURL *url = [NSURL fileURLWithPath:[appBundle pathForResource:key ofType:@"aifc"]];
AVAudioFile *asset = [[AVAudioFile alloc] initForReading:url &error];
然后播放该文件:
[_audioPlayer scheduleFile:asset atTime:nil completionHandler:nil];
[_audioPlayer play];
更新:如果应用进入休眠状态或进入后台,音频可能会停止 playing/fade。通过激活音频会话,这将被阻止。
NSError *error;
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
if (error) {
NSLog(@"AVAudioSession setCategory ERROR: %@", error.localizedDescription);
}
[[AVAudioSession sharedInstance] setActive:YES error:&error];
if (error) {
NSLog(@"AVAudioSession setActive ERROR: %@", error.localizedDescription);
}
我没有去处理任何错误,但这应该可行。不要忘记在实施文件的顶部 #import <AVFoundation/AVFoundation.h>
。
我可以确认,@ApperleyA 解决方案确实有效!
这里是 swift 版本:
var _audioPlayer : AVAudioPlayerNode!
var _audioEngine : AVAudioEngine!
func playAudio()
{
if (_audioPlayer==nil) {
_audioPlayer = AVAudioPlayerNode()
_audioEngine = AVAudioEngine()
_audioEngine.attach(_audioPlayer)
let stereoFormat = AVAudioFormat(standardFormatWithSampleRate: 44100, channels: 2)
_audioEngine.connect(_audioPlayer, to: _audioEngine.mainMixerNode, format: stereoFormat)
do {
if !_audioEngine.isRunning {
try _audioEngine.start()
}
} catch {}
}
if let path = Bundle.main.path(forResource: "test", ofType: "mp3") {
let fileUrl = URL(fileURLWithPath: path)
do {
let asset = try AVAudioFile(forReading: fileUrl)
_audioPlayer.scheduleFile(asset, at: nil, completionHandler: nil)
_audioPlayer.play()
} catch {
print ("asset error")
}
}
}
这在模拟器中对我有用
let soundPath = Bundle.main.path(forResource: "cheerMP3", ofType: "mp3")
let soundPathURL = URL(fileURLWithPath: soundPath!)
let audioFile = WKAudioFileAsset(url: soundPathURL)
let audioItem = WKAudioFilePlayerItem(asset: audioFile)
let audioPlayer = WKAudioFilePlayer.init(playerItem: audioItem)
if audioPlayer.status == .readyToPlay
{
audioPlayer.play()
}
else
{
print("Not ready!!")
}
但前提是我在 audioPlayer.play() 和最后一个 } 之后都有断点。
dunqan,你在文件的顶部放了什么,导入语句?我无法包含
导入 AVFoundation
使用Xcode 8.2.1
没有错误