在AVPlayer中获得averagePowerForChannel

我怎样才能得到在AVPlayer averagePowerForChannel为了使我的音乐应用程序的audio可视化! 我已经做了可视化部分,但我卡在它的引擎(实时音量通道)。

我知道通过使用AVAudioPlayer它可以很容易地使用.meteringEnabled属性,但由于一些已知的原因AVPlayer是必须在我的应用程序! 我真的想用AVAudioPlayer除了AVPlayer获得所需的结果,但它听起来有点混乱的解决方法,如何影响性能和稳定性? 提前致谢

您将需要与AV Foundation结合使用audio处理器类来可视化audio样本,以及将audioaudio单元效果(带通滤波器)应用于audio数据。 你可以在这里find苹果的样品

本质上,你需要添加一个观察者给你AVPlayer,如下所示:

 // Notifications let playerItem: AVPlayerItem! = videoPlayer.currentItem playerItem.addObserver(self, forKeyPath: "tracks", options: NSKeyValueObservingOptions.New, context: nil); NSNotificationCenter.defaultCenter().addObserverForName(AVPlayerItemDidPlayToEndTimeNotification, object: videoPlayer.currentItem, queue: NSOperationQueue.mainQueue(), usingBlock: { (notif: NSNotification) -> Void in self.videoPlayer.seekToTime(kCMTimeZero) self.videoPlayer.play() print("replay") }) 

然后在下面的重写方法中处理通知:

 override func observeValueForKeyPath(keyPath: String?, ofObject object: AnyObject?, change: [String : AnyObject]?, context: UnsafeMutablePointer<Void>) { if (object === videoPlayer.currentItem && keyPath == "tracks"){ if let playerItem: AVPlayerItem = videoPlayer.currentItem { if let tracks = playerItem.asset.tracks as? [AVAssetTrack] { tapProcessor = MYAudioTapProcessor(AVPlayerItem: playerItem) playerItem.audioMix = tapProcessor.audioMix tapProcessor.delegate = self } } } } 

这里有一个链接到GitHub上的示例项目

我在AVPlayer可视化方面遇到了两年的问题。 在我的情况下,它涉及HLS实时stream媒体,在这种情况下,你不会得到它运行,据我所知。

编辑这不会让你访问averagePowerForChannel:方法,但你将获得访问原始数据,例如FFT获得所需的信息。

不过,我用它来处理本地播放。 您基本上等待玩家玩家项目开始运行。 此时您需要将MTAudioProcessingTap修补到audio混合中。

处理抽头将运行您指定的callback,您将可以根据需要计算原始audio数据。

这里是一个简单的例子(对不起,在ObjC中,虽然):

 #import <AVFoundation/AVFoundation.h> #import <MediaToolbox/MediaToolbox.h> void init(MTAudioProcessingTapRef tap, void *clientInfo, void **tapStorageOut) {}; void finalize(MTAudioProcessingTapRef tap) {}; void prepare(MTAudioProcessingTapRef tap, CMItemCount maxFrames, const AudioStreamBasicDescription *processingFormat) {}; void unprepare(MTAudioProcessingTapRef tap) {}; void process(MTAudioProcessingTapRef tap, CMItemCount numberFrames, MTAudioProcessingTapFlags flags, AudioBufferList *bufferListInOut, CMItemCount *numberFramesOut, MTAudioProcessingTapFlags *flagsOut) {}; - (void)play { // player and item setup ... [[[self player] currentItem] addObserver:self forKeyPath:@"tracks" options:kNilOptions context:NULL]; } ////////////////////////////////////////////////////// - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)changecontext:(void *)context if ([keyPath isEqualToString:@"tracks"] && [[object tracks] count] > 0) { for (AVPlayerItemTrack *itemTrack in [object tracks]) { AVAssetTrack *track = [itemTrack assetTrack]; if ([[track mediaType] isEqualToString:AVMediaTypeAudio]) { [self addAudioProcessingTap:track]; break; } } } - (void)addAudioProcessingTap:(AVAssetTrack *)track { MTAudioProcessingTapRef tap; MTAudioProcessingTapCallbacks callbacks; callbacks.version = kMTAudioProcessingTapCallbacksVersion_0; callbacks.clientInfo = (__bridge void *)(self); callbacks.init = init; callbacks.prepare = prepare; callbacks.process = process; callbacks.unprepare = unprepare; callbacks.finalize = finalise; OSStatus err = MTAudioProcessingTapCreate(kCFAllocatorDefault, &callbacks, kMTAudioProcessingTapCreationFlag_PostEffects, &tap); if (err) { NSLog(@"error: %@", [NSError errorWithDomain:NSOSStatusErrorDomain code:err userInfo:nil]); return; } AVMutableAudioMix *audioMix = [AVMutableAudioMix audioMix]; AVMutableAudioMixInputParameters *inputParams = [AVMutableAudioMixInputParameters audioMixInputParametersWithTrack:audioTrack]; [inputParams setAudioTapProcessor:tap]; [audioMix setInputParameters:@[inputParams]]; [[[self player] currentItem] setAudioMix:audioMix]; } 

在两年前我的问题上有一些讨论,所以一定要检查一下。