最近项目里有一个需求,是个直播项目,需要主播在开播端,点击聊天区某条语音信息的播放按钮来播放观众的语音(这里我用的是在语音播放单例添加播放完毕监听;在本vc控制器将出现时为语音播放处理单例添加语音播放完成监听,在vc控制器将要消失时为单例移出监听),并且播放完成,按钮切换为初始状态;而且在主播端开播前会播放一个“倒计时”视频,并且播放视频;但是在这里遇到一个问题:没有语音播放,但是却走了单里里边语音播放完成时监听的方法?
在这里猜测可能是开播前“倒计时”视频播放完毕也发出了播放完毕的通知,并且验证了下,的确是这样的,以后要注意。
代码如下:
单例.m文件,主要是add,remove播放完成通知方法被vc调用.
#import \"JJHVoiceOpenQueue.h\"
#import \"JJHVoiceVentor.h\"
@implementation JJHVoiceOpenQueue
+(JJHVoiceOpenQueue *)sharedQueue {
static JJHVoiceOpenQueue * instance = nil;
static dispatch_once_t predict;
dispatch_once(&predict, ^{
instance = [[JJHVoiceOpenQueue alloc] init];
//朱明俊:初始化的时候不用清除消息和暂停播放器
//[instance otherOperationShouldStopNowPlayAndClearMp3Queue];
});
return instance;
}
//队列添加一个发言语音
-(void)addVoiceChatMp3FileUrlStr:(NSString*)Mp3UrlStr{
if (self.voiceArray.count == 0) {
//说明播放队列是播放完的,或者是刚启动程序初次播放,再加入就直接播放
[self.voiceArray add :Mp3UrlStr];
[self playVoiceArrFirst];
}else{
//说明播放队列没播放完,语音正在播放中,只添加
[self.voiceArray add :Mp3UrlStr];
}
}
//接着播放下一段
-(void)playWithNext{
//流程:先删除播放完的录音->判断队列还有录音没有->有继续播放,没有不做操作
if (self.voiceArray.count>0) {
//删除刚刚播放过的语音
[self.voiceArray remove AtIndex:0];
//如果大于0,继续下一首的播放
[self playVoiceArrFirst];
}
}
-(void)playVoiceArrFirst{
//播放前毕发送通知,重置聊天区语音图标
[[NSNotificationCenter defaultCenter] postNotificationName:VOICE_PLAYED_OVER_MSG :nil userInfo:nil];
//播放下一条
if (self.voiceArray.count>0) {
AVAudioSession *session = [AVAudioSession sharedInstance];
[session setCategory:AVAudioSessionCategoryPlayback error:nil];
[session setActive:YES error:nil];
//http://jjhsound.jjhgame.com/181109105926-2690188-90602998.mp3
NSURL * url = [NSURL URLWithString:[NSString stringWithFormat:@\"%@\",self.voiceArray[0]]];
AVP Item * songItem = [[AVP Item alloc]initWithURL:url];
[self.voiceP replaceCurrentItemWithP Item:songItem];
[self.voiceP play];
//播放发送通知,修改聊天区语音状态,就是修改图片为播放过的图片
NSDictionary *voiceDic = @{@\"urlStr\":[NSString stringWithFormat:@\"%@\",self.voiceArray[0]]};
[[NSNotificationCenter defaultCenter] postNotificationName:VOICE_PLAYED_MSG :nil userInfo:voiceDic];
}
}
//直播间直接点击播放
//播放语音
-(void)playVoiceWithVoiceUrlStr:(NSString*)voiceUrlStr{
//清空播放队列
[self otherOperationShouldStopNowPlayAndClearMp3Queue];
//将获取的url添加到第一个
[self addVoiceChatMp3FileUrlStr:voiceUrlStr];
}
//暂停播放,语音队列清空
//而且如果正在播放,需要暂停
//不必移除播放监听,播放监听只是顺序播放下一首,程序运行期间和本单例一直存在
-(void)otherOperationShouldStopNowPlayAndClearMp3Queue{
[self.voiceP pause];
[self.voiceArray removeAll s];
//其他异常操作发送通知,重置聊天区语音图标,如,正在播放,点击录音等等情况
[[NSNotificationCenter defaultCenter] postNotificationName:VOICE_PLAYED_OVER_MSG :nil userInfo:nil];
}
#pragma - lazy
-(AVP *)voiceP {
if (!_voiceP ) {
_voiceP = [[AVP alloc] initWithP Item:nil];
}
return _voiceP ;
}
//直播间成对调用
-(void)addNoti{
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playbackFinished) name:AVP ItemDidPlayToEndTimeNotification :nil];
}
-(void)removeNoti{
[[NSNotificationCenter defaultCenter] removeObserver:self name:AVP ItemDidPlayToEndTimeNotification :nil];
}
-(void)playbackFinished{
//播放完毕发送通知,重置聊天区语音图标
[[NSNotificationCenter defaultCenter] postNotificationName:VOICE_PLAYED_OVER_MSG :nil userInfo:nil];
NSLog(@\"测试语音和视频播放完毕是否会发出走这个通知\");
//接着播放下一条录音,
//[self playWithNext];
}
//声音url队列
-(NSMutableArray *)voiceArray{
if (_voiceArray == nil) {
_voiceArray = [[NSMutableArray alloc] init];
}
return _voiceArray;
}
@end
然后是vc的主要.m方法
- (void)playMovieBegin {
NSString * path = [[NSBundle mainBundle] pathForResource:@\"xxx\" ofType:@\"mp4\"];
//NSString *path =[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) first ];
NSLog(@\"path - %@\",path);
[self.movieP setContentURL:[NSURL fileURLWithPath:path]];
[self.movieP prepareToPlay];
[self.movieP play];
}
- (MPMovieP Controller *)movieP {
if(!_movieP ){
_movieP = [[MPMovieP Controller alloc]init];
[_movieP .view set :kYBScreenBounds];
///关闭自动播放
[_movieP setShouldAutoplay:NO];
///文件类型
[_movieP setMovieSourceType:MPMovieSourceTypeFile];
///取出控制进度条
[_movieP setControlStyle:MPMovieControlStyleNone];
[[UIApplication sharedApplication].keyWindow addSubview:_movieP .view];
return _movieP ;
}
-(void)viewwillappear{
[super viewwillappear];
[[JJHVoiceOpenQueue sharedQueue] addNoti];
}
然后在没有聊天区语音信息播放的时候却在控制台打印出了
2018-12-19 11:41:54.514349+0800 Daka2[1404:397617] path - /var/containers/Bundle/Application/80173D9D-1D0A-4226-A62F-C2B6EA72392B/Daka2.app/Prepare.mp4
2018-12-19 11:41:58.397335+0800 Daka2[1404:397617] 测试语音和视频播放完毕是否会发出走这个通知
说明mp4视频播放完毕,也会发出AVP ItemDidPlayToEndTimeNotification通知,执行了我以为的语音播放完毕的方法,要注意(使用了MPMovieP Controller和AVP 来播放的文件,不管是声音还是视频,都会发出AVP ItemDidPlayToEndTimeNotification通知),要识别到底是声音播放完毕,还是视频播放完毕,还需要做更细致的区分.
更多交流,请加群讨论:565191947
继续阅读与本文标签相同的文章
-
每月更新两版 完善145个技术点 夸克无障碍版打造信息坦途
2026-05-18栏目: 教程
-
高危预警|RDP漏洞或引发大规模蠕虫爆发,用户可用阿里云免费检测服务自检,建议尽快修复
2026-05-18栏目: 教程
-
云上一指禅:大数据产品DataWorks每日问答
2026-05-18栏目: 教程
-
云数据库RDS是什么?
2026-05-18栏目: 教程
-
2019智能安防工程师大会在杭州成功召开
2026-05-18栏目: 教程
