AVPlayer(或 AVAudioSession?)在我离开 ViewController 后播放,当我 return 两个正在播放时
AVPlayer (or AVAudioSession?) plays after I leave the ViewController, and when I return two are then playing
我有一个 viewController 可以从网络流式传输音频。当我离开应用程序的那个页面时,音频会继续播放(这很好)。但是,当我返回时,viewdidload 方法创建了第二个音频播放器。我可以一遍又一遍地这样做,直到我有这么多的 AVplayer。这听起来令人难以置信的回声。这是我所有的相关代码。
#import "ListenViewController.h"
#import <AVFoundation/AVAudioPlayer.h>
#import <AVFoundation/AVPlayerItem.h>
#import <AVFoundation/AVPlayer.h>
#import <AVFoundation/AVFoundation.h>
#import "RSPlayPauseButton.h"
@interface ListenViewController () <AVAudioPlayerDelegate, AVAudioSessionDelegate>
@property (nonatomic, strong) AVPlayer *player;
@property (nonatomic, strong) AVPlayerItem *playerItem;
@property (nonatomic, strong) RSPlayPauseButton *playPauseButton;
@property (nonatomic, copy) NSDate *now;
@end
@implementation ListenViewController
static int min = -2;
-(void) viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
//[self.player pause];
min = -2;
}
-(void) viewDidLoad
{
[super viewDidLoad];
/*
if ([AVAudioSession sharedInstance].isInputAvailable) {
NSLog(@"XXXXXXXXX");
}
*/
NSURL *streamingURL = [NSURL URLWithString:@"http://URL.m3u"];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:streamingURL];
self.playerItem = playerItem;
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
[player setAllowsExternalPlayback:NO];
CMTime tm = CMTimeMake(1, 1);
[player addPeriodicTimeObserverForInterval:tm
queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
/*
NSDateFormatter *DateFormatter=[[NSDateFormatter alloc] init];
[DateFormatter setDateFormat:@"yyyy-MM-dd hh:mm:ss:mmm"];
NSLog(@"%@",[DateFormatter stringFromDate:[NSDate date]]);
*/
if (!self.now) {
self.now = [NSDate date];
}
/*
NSDate *now = [NSDate date];
NSTimeInterval interval = [now timeIntervalSinceDate:self.now];
self.interval += 0.01;
interval -= (10 * self.rw2);
interval -= (60 * self.rw3);
interval += (10 * self.ff2);
self.timeLabel.text = [NSString stringWithFormat:@"%f", interval];
NSLog(@"INTERVAL: %@", [NSString stringWithFormat:@"%f", self.interval]);
*/
if (CMTimeGetSeconds(self.player.currentTime) >= 0) {
self.timeLabel.text = [NSString stringWithFormat:@"%.0f", CMTimeGetSeconds(self.player.currentTime)];
NSTimeInterval time = CMTimeGetSeconds(self.player.currentTime);
//int min = time/60;
int sec = lroundf(time) % 60;
if (sec == 0) {
++min;
}
NSLog(@"sec: %d", sec);
// update your UI with timeLeft
self. timeLabel.text = [NSString stringWithFormat:@"%.2d:%.2d", min,sec];
}
}];
[self setPlayer:player];
[player play];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
if (!self.playPauseButton) {
self.playPauseButton = [[RSPlayPauseButton alloc] initWithFrame:self.view.frame];
self.playPauseButton.tintColor = [UIColor colorWithRed:1.0 green:155.0/255.0 blue:0.0 alpha:1.0];
self.playPauseButton.animationStyle = RSPlayPauseButtonAnimationStyleSplitAndRotate;
self.playPauseButton.paused = NO;
[self.playPauseButton addTarget:self action:@selector(playPauseButtonDidPress:) forControlEvents:UIControlEventTouchUpInside];
}
[self.view addSubview:self.playPauseButton];
}
- (IBAction)rewind:(id)sender
{
//NSLog(@"currenttime: %f", CMTimeGetSeconds(self.player.currentTime));
//NSLog(@"timescale: %d", self.player.currentTime.timescale);
CMTime cmTime = CMTimeMake(CMTimeGetSeconds(self.player.currentTime) - 1.0, 1);
CMTime zero = CMTimeMake(1, 2);
if (CMTimeGetSeconds(cmTime) > CMTimeGetSeconds(zero)) {
[self.player.currentItem seekToTime:cmTime];
NSLog(@"!");
}
NSLog(@"RW");
}
- (IBAction)rewind2:(id)sender
{
/*
CMTime cmTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(self.player.currentTime) - 10.0, self.player.currentTime.timescale);
CMTime zero = CMTimeMake(0, 10000);
if (CMTimeGetSeconds(cmTime) > CMTimeGetSeconds(zero)) {
[self.player.currentItem seekToTime:cmTime];
self.rw2 += 1;
NSLog(@"RW2!");
}
*/
NSLog(@"RW2");
CMTime cmTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(self.player.currentTime) - 10.0, self.player.currentTime.timescale);
CMTime zero = CMTimeMake(1, 2);
NSLog(@"cmTime: %f", CMTimeGetSeconds(cmTime));
NSLog(@"zero: %f", CMTimeGetSeconds(zero));
if (CMTimeGetSeconds(cmTime) > CMTimeGetSeconds(zero)) {
[self.player.currentItem seekToTime:cmTime];
NSLog(@"!");
} else {
[self rewindAll];
}
}
- (IBAction)rewind3:(id)sender
{
CMTime cmTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(self.player.currentTime) - 60.0, self.player.currentTime.timescale);
CMTime zero = CMTimeMake(0, 10000);
if (CMTimeGetSeconds(cmTime) > CMTimeGetSeconds(zero)) {
[self.player.currentItem seekToTime:cmTime];
NSLog(@"RW3!");
}
NSLog(@"RW3");
}
- (void) rewindAll
{
CMTime one = CMTimeMake(1, 1);
[self.player.currentItem seekToTime:one];
}
- (IBAction)fastForward:(id)sender
{
CMTime cmTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(self.player.currentTime) + 5.0, self.player.currentTime.timescale);
NSDate *now = [NSDate date];
NSTimeInterval interval = [now timeIntervalSinceDate:self.now];
CMTime seekingCM = CMTimeMake(interval, 1);
if (CMTimeGetSeconds(cmTime) < CMTimeGetSeconds(seekingCM)) {
[self.player.currentItem seekToTime:cmTime];
}
}
- (IBAction)fastForward2:(id)sender
{
CMTime cmTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(self.player.currentTime) + 10.0, self.player.currentTime.timescale);
NSDate *now = [NSDate date];
NSTimeInterval interval = [now timeIntervalSinceDate:self.now];
CMTime seekingCM = CMTimeMake(interval, 1);
if (CMTimeGetSeconds(cmTime) < CMTimeGetSeconds(seekingCM)) {
[self.player.currentItem seekToTime:cmTime];
NSLog(@"FF2!");
} else {
[self fastForward3:nil];
}
}
- (IBAction)fastForward3:(id)sender
{
NSDate *now = [NSDate date];
NSLog(@"FIRSTDATE: %@", self.now);
NSTimeInterval interval = [now timeIntervalSinceDate:self.now];
interval -= 0.5f;
NSLog(@"INT: %f", interval);
CMTime seekingCM = CMTimeMake(interval, 1);
/*
NSTimeInterval interval = self.interval - 1.0;
CMTime seekingCM = CMTimeMake(interval, 1);
[self.player.currentItem seekToTime:seekingCM];
*/
//CMTime seekingCM = CMTimeMake(self.interval, 1);
[self.player.currentItem seekToTime:seekingCM];
NSLog(@"FF3!");
}
- (NSTimeInterval)currentPlaybackTime
{
return CMTimeGetSeconds(self.player.currentItem.currentTime);
}
- (void)setCurrentPlaybackTime:(NSTimeInterval)time
{
CMTime cmTime = CMTimeMakeWithSeconds(time, NSEC_PER_SEC);
[self.player.currentItem seekToTime:cmTime];
}
- (void)viewDidLayoutSubviews
{
[self.playPauseButton sizeToFit];
self.playPauseButton.center = CGPointMake(self.view.frame.size.width / 2.0, self.view.frame.size.height / 1.2);
}
- (void)playPauseButtonDidPress:(RSPlayPauseButton *)playPauseButton
{
[playPauseButton setPaused:!playPauseButton.isPaused animated:YES];
if (playPauseButton.isPaused) {
[self.player pause];
}
else {
[self.player play];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
顺便说一句,有一个 UIlabel 给出了播放器的当前时间,但如果我离开页面并返回,标签会自动从 00:00 重新开始。这是因为它给出了新 AVPlayer 的当前时间。有没有办法让它给出原始AVPlayer的当前时间?
这是我来自 swift 的视图控制器,如果它可以帮助你,那很好,我已经在那里实现了所有无线电的东西:
我会创建一个单例对象来控制 AVPlayer
,因此无论您有多少个视图控制器,它们都会与这个单一播放器控制器通信。所以基本上我建议您将 viewDidLoad
中的所有代码移动到一些 MYPlayerController
单例 class.
我有一个 viewController 可以从网络流式传输音频。当我离开应用程序的那个页面时,音频会继续播放(这很好)。但是,当我返回时,viewdidload 方法创建了第二个音频播放器。我可以一遍又一遍地这样做,直到我有这么多的 AVplayer。这听起来令人难以置信的回声。这是我所有的相关代码。
#import "ListenViewController.h"
#import <AVFoundation/AVAudioPlayer.h>
#import <AVFoundation/AVPlayerItem.h>
#import <AVFoundation/AVPlayer.h>
#import <AVFoundation/AVFoundation.h>
#import "RSPlayPauseButton.h"
@interface ListenViewController () <AVAudioPlayerDelegate, AVAudioSessionDelegate>
@property (nonatomic, strong) AVPlayer *player;
@property (nonatomic, strong) AVPlayerItem *playerItem;
@property (nonatomic, strong) RSPlayPauseButton *playPauseButton;
@property (nonatomic, copy) NSDate *now;
@end
@implementation ListenViewController
static int min = -2;
-(void) viewDidDisappear:(BOOL)animated
{
[super viewDidDisappear:animated];
//[self.player pause];
min = -2;
}
-(void) viewDidLoad
{
[super viewDidLoad];
/*
if ([AVAudioSession sharedInstance].isInputAvailable) {
NSLog(@"XXXXXXXXX");
}
*/
NSURL *streamingURL = [NSURL URLWithString:@"http://URL.m3u"];
AVPlayerItem *playerItem = [AVPlayerItem playerItemWithURL:streamingURL];
self.playerItem = playerItem;
AVPlayer *player = [AVPlayer playerWithPlayerItem:playerItem];
[player setAllowsExternalPlayback:NO];
CMTime tm = CMTimeMake(1, 1);
[player addPeriodicTimeObserverForInterval:tm
queue:dispatch_get_main_queue() usingBlock:^(CMTime time) {
/*
NSDateFormatter *DateFormatter=[[NSDateFormatter alloc] init];
[DateFormatter setDateFormat:@"yyyy-MM-dd hh:mm:ss:mmm"];
NSLog(@"%@",[DateFormatter stringFromDate:[NSDate date]]);
*/
if (!self.now) {
self.now = [NSDate date];
}
/*
NSDate *now = [NSDate date];
NSTimeInterval interval = [now timeIntervalSinceDate:self.now];
self.interval += 0.01;
interval -= (10 * self.rw2);
interval -= (60 * self.rw3);
interval += (10 * self.ff2);
self.timeLabel.text = [NSString stringWithFormat:@"%f", interval];
NSLog(@"INTERVAL: %@", [NSString stringWithFormat:@"%f", self.interval]);
*/
if (CMTimeGetSeconds(self.player.currentTime) >= 0) {
self.timeLabel.text = [NSString stringWithFormat:@"%.0f", CMTimeGetSeconds(self.player.currentTime)];
NSTimeInterval time = CMTimeGetSeconds(self.player.currentTime);
//int min = time/60;
int sec = lroundf(time) % 60;
if (sec == 0) {
++min;
}
NSLog(@"sec: %d", sec);
// update your UI with timeLeft
self. timeLabel.text = [NSString stringWithFormat:@"%.2d:%.2d", min,sec];
}
}];
[self setPlayer:player];
[player play];
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:nil];
[[AVAudioSession sharedInstance] setActive: YES error: nil];
if (!self.playPauseButton) {
self.playPauseButton = [[RSPlayPauseButton alloc] initWithFrame:self.view.frame];
self.playPauseButton.tintColor = [UIColor colorWithRed:1.0 green:155.0/255.0 blue:0.0 alpha:1.0];
self.playPauseButton.animationStyle = RSPlayPauseButtonAnimationStyleSplitAndRotate;
self.playPauseButton.paused = NO;
[self.playPauseButton addTarget:self action:@selector(playPauseButtonDidPress:) forControlEvents:UIControlEventTouchUpInside];
}
[self.view addSubview:self.playPauseButton];
}
- (IBAction)rewind:(id)sender
{
//NSLog(@"currenttime: %f", CMTimeGetSeconds(self.player.currentTime));
//NSLog(@"timescale: %d", self.player.currentTime.timescale);
CMTime cmTime = CMTimeMake(CMTimeGetSeconds(self.player.currentTime) - 1.0, 1);
CMTime zero = CMTimeMake(1, 2);
if (CMTimeGetSeconds(cmTime) > CMTimeGetSeconds(zero)) {
[self.player.currentItem seekToTime:cmTime];
NSLog(@"!");
}
NSLog(@"RW");
}
- (IBAction)rewind2:(id)sender
{
/*
CMTime cmTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(self.player.currentTime) - 10.0, self.player.currentTime.timescale);
CMTime zero = CMTimeMake(0, 10000);
if (CMTimeGetSeconds(cmTime) > CMTimeGetSeconds(zero)) {
[self.player.currentItem seekToTime:cmTime];
self.rw2 += 1;
NSLog(@"RW2!");
}
*/
NSLog(@"RW2");
CMTime cmTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(self.player.currentTime) - 10.0, self.player.currentTime.timescale);
CMTime zero = CMTimeMake(1, 2);
NSLog(@"cmTime: %f", CMTimeGetSeconds(cmTime));
NSLog(@"zero: %f", CMTimeGetSeconds(zero));
if (CMTimeGetSeconds(cmTime) > CMTimeGetSeconds(zero)) {
[self.player.currentItem seekToTime:cmTime];
NSLog(@"!");
} else {
[self rewindAll];
}
}
- (IBAction)rewind3:(id)sender
{
CMTime cmTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(self.player.currentTime) - 60.0, self.player.currentTime.timescale);
CMTime zero = CMTimeMake(0, 10000);
if (CMTimeGetSeconds(cmTime) > CMTimeGetSeconds(zero)) {
[self.player.currentItem seekToTime:cmTime];
NSLog(@"RW3!");
}
NSLog(@"RW3");
}
- (void) rewindAll
{
CMTime one = CMTimeMake(1, 1);
[self.player.currentItem seekToTime:one];
}
- (IBAction)fastForward:(id)sender
{
CMTime cmTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(self.player.currentTime) + 5.0, self.player.currentTime.timescale);
NSDate *now = [NSDate date];
NSTimeInterval interval = [now timeIntervalSinceDate:self.now];
CMTime seekingCM = CMTimeMake(interval, 1);
if (CMTimeGetSeconds(cmTime) < CMTimeGetSeconds(seekingCM)) {
[self.player.currentItem seekToTime:cmTime];
}
}
- (IBAction)fastForward2:(id)sender
{
CMTime cmTime = CMTimeMakeWithSeconds(CMTimeGetSeconds(self.player.currentTime) + 10.0, self.player.currentTime.timescale);
NSDate *now = [NSDate date];
NSTimeInterval interval = [now timeIntervalSinceDate:self.now];
CMTime seekingCM = CMTimeMake(interval, 1);
if (CMTimeGetSeconds(cmTime) < CMTimeGetSeconds(seekingCM)) {
[self.player.currentItem seekToTime:cmTime];
NSLog(@"FF2!");
} else {
[self fastForward3:nil];
}
}
- (IBAction)fastForward3:(id)sender
{
NSDate *now = [NSDate date];
NSLog(@"FIRSTDATE: %@", self.now);
NSTimeInterval interval = [now timeIntervalSinceDate:self.now];
interval -= 0.5f;
NSLog(@"INT: %f", interval);
CMTime seekingCM = CMTimeMake(interval, 1);
/*
NSTimeInterval interval = self.interval - 1.0;
CMTime seekingCM = CMTimeMake(interval, 1);
[self.player.currentItem seekToTime:seekingCM];
*/
//CMTime seekingCM = CMTimeMake(self.interval, 1);
[self.player.currentItem seekToTime:seekingCM];
NSLog(@"FF3!");
}
- (NSTimeInterval)currentPlaybackTime
{
return CMTimeGetSeconds(self.player.currentItem.currentTime);
}
- (void)setCurrentPlaybackTime:(NSTimeInterval)time
{
CMTime cmTime = CMTimeMakeWithSeconds(time, NSEC_PER_SEC);
[self.player.currentItem seekToTime:cmTime];
}
- (void)viewDidLayoutSubviews
{
[self.playPauseButton sizeToFit];
self.playPauseButton.center = CGPointMake(self.view.frame.size.width / 2.0, self.view.frame.size.height / 1.2);
}
- (void)playPauseButtonDidPress:(RSPlayPauseButton *)playPauseButton
{
[playPauseButton setPaused:!playPauseButton.isPaused animated:YES];
if (playPauseButton.isPaused) {
[self.player pause];
}
else {
[self.player play];
}
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
顺便说一句,有一个 UIlabel 给出了播放器的当前时间,但如果我离开页面并返回,标签会自动从 00:00 重新开始。这是因为它给出了新 AVPlayer 的当前时间。有没有办法让它给出原始AVPlayer的当前时间?
这是我来自 swift 的视图控制器,如果它可以帮助你,那很好,我已经在那里实现了所有无线电的东西:
我会创建一个单例对象来控制 AVPlayer
,因此无论您有多少个视图控制器,它们都会与这个单一播放器控制器通信。所以基本上我建议您将 viewDidLoad
中的所有代码移动到一些 MYPlayerController
单例 class.