Переглянути джерело

播放器打断功能优化

Steven 7 місяців тому
батько
коміт
f7bd2f26df

+ 1 - 1
KulexiuForTeacher/KulexiuForTeacher/Common/Base/AccompanyWebView/AudioEnginePlayer.h

@@ -19,7 +19,7 @@
 
 - (void)enginePlayerIsReadyPlay:(AudioEnginePlayer *_Nonnull)player;
 
-- (void)enginePlayerDidError:(AudioEnginePlayer *_Nonnull)player error:(NSError *_Nonnull)error;
+- (void)enginePlayerDidError:(AudioEnginePlayer *_Nonnull)player error:(NSError *_Nullable)error;
 
 @end
 

+ 61 - 17
KulexiuForTeacher/KulexiuForTeacher/Common/Base/AccompanyWebView/AudioEnginePlayer.m

@@ -26,6 +26,8 @@
 
 @property (nonatomic, assign) AVAudioFramePosition startPosition; // 开始位置
 
+@property (nonatomic, assign) BOOL isInterrupt; // 是否被打断
+
 @end
 
 @implementation AudioEnginePlayer
@@ -55,6 +57,26 @@
         NSLog(@"----- exception --- %@", exception);
     } @finally {
         [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleInterruption:) name:AVAudioSessionInterruptionNotification object:audioSession];
+        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleRouteChange:) name:AVAudioSessionRouteChangeNotification object:audioSession];
+    }
+}
+
+- (void)handleRouteChange:(NSNotification *)notification {
+    NSDictionary *info = notification.userInfo;
+    AVAudioSessionRouteChangeReason reason = [info[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
+    if (reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
+        // 耳机拔出时暂停音频
+        if (self.bgPlayer.isPlaying) {
+            NSError *error = nil;
+            [self sendInterruptError:error];
+        }
+        
+    } else if (reason == AVAudioSessionRouteChangeReasonNewDeviceAvailable) {
+        // 耳机插入时恢复音频
+        if (self.bgPlayer.isPlaying) {
+            NSError *error = nil;
+            [self sendInterruptError:error];
+        }
     }
 }
 
@@ -65,22 +87,37 @@
     AVAudioSessionInterruptionType type = [info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
     if (type == AVAudioSessionInterruptionTypeBegan) {
         //Handle InterruptionBegan
-        if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayerDidError:error:)]) {
+        if (self.isInterrupt == NO) {
+            if (self.bgPlayer.isPlaying) {
+                [self.bgPlayer stop];
+            }
+            self.isInterrupt = YES;
             NSError *error = [[NSError alloc] initWithDomain:NSCocoaErrorDomain code:99999 userInfo:@{@"errorDesc" : @"播放被打断"}];
-            [self.delegate enginePlayerDidError:self error:error];
+            [self sendInterruptError:error];
         }
     }
-    else {
+    else if (type == AVAudioSessionInterruptionTypeEnded) {
         AVAudioSessionInterruptionOptions options = [info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
-        if (options == AVAudioSessionInterruptionOptionShouldResume) {
+        if (options == AVAudioSessionInterruptionOptionShouldResume && self.isInterrupt) {
             //Handle Resume
             
-            [[AVAudioSession sharedInstance] setActive:YES error:nil];
-//            [self startEngine];
+            NSError *error = nil;
+            [[AVAudioSession sharedInstance] setActive:YES error:&error];
+            if (error) {
+                NSLog(@"------ error desc %@", error.description);
+            }
+            
+            NSLog(@"---- 播放恢复");
+            self.isInterrupt = NO;
         }
     }
 }
 
+- (void)sendInterruptError:(NSError *)error {
+    if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayerDidError:error:)]) {
+        [self.delegate enginePlayerDidError:self error:error];
+    }
+}
 
 - (void)configEngine {
     [self setupAudioSession];
@@ -104,9 +141,7 @@
     } @finally {
         if (error) {
             // 错误回调
-            if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayerDidError:error:)]) {
-                [self.delegate enginePlayerDidError:self error:error];
-            }
+            [self sendInterruptError:error];
         }
     }
     
@@ -143,28 +178,27 @@
     } @finally {
         if (error) {
             self.audioEngine = nil;
-            // 错误回调
-            if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayerDidError:error:)]) {
-                [self.delegate enginePlayerDidError:self error:error];
-            }
+            [self sendInterruptError:error];
         }
     }
 }
 
 - (void)startPlay {
+    if (self.isInterrupt) {
+        [self sendInterruptError:nil];
+        return;
+    }
     if (self.audioEngine.isRunning == NO) {
         [self startEngine];
     }
     if (self.audioEngine.isRunning) {
         [self.bgPlayer play];
-        self.isPlaying = YES;
         [self startTimer];
     }
 }
 
 - (void)stopPlay {
     [self stopTimer];
-    self.isPlaying = NO;
     if (self.bgPlayer.isPlaying) {
         [self.bgPlayer stop];
     }
@@ -172,6 +206,10 @@
 
 // 从某个位置开始播放 ms
 - (void)seekToTimePlay:(NSInteger)time {
+    if (self.isInterrupt) {
+        [self sendInterruptError:nil];
+        return;
+    }
     if (self.audioEngine.isRunning == NO) {
         [self startEngine];
     }
@@ -201,7 +239,6 @@
         if (self.audioEngine.isRunning) {
             [self.bgPlayer play];
             [self startTimer];
-            self.isPlaying = YES;
         }
     }
     else { // 已无后续片段
@@ -215,7 +252,7 @@
 
 - (void)freePlayer {
     
-    if (self.isPlaying) {
+    if (self.bgPlayer.isPlaying) {
         [self stopPlay];
     }
 }
@@ -306,4 +343,11 @@
     }
 }
 
+- (BOOL)isPlaying {
+    if (self.bgPlayer) {
+        return self.bgPlayer.isPlaying;
+    }
+    return NO;
+}
+
 @end

+ 1 - 1
KulexiuForTeacher/KulexiuForTeacher/Common/MediaMerge/AudioMerge/MergePlayer/KSMergeEnginePlayer.h

@@ -26,7 +26,7 @@
 
 - (void)enginePlayerIsReadyPlay:(KSMergeEnginePlayer *_Nonnull)player;
 
-- (void)enginePlayerDidError:(KSMergeEnginePlayer *_Nonnull)player error:(NSError *_Nonnull)error;
+- (void)enginePlayerDidError:(KSMergeEnginePlayer *_Nonnull)player error:(NSError *_Nullable)error;
 
 @end
 

+ 43 - 21
KulexiuForTeacher/KulexiuForTeacher/Common/MediaMerge/AudioMerge/MergePlayer/KSMergeEnginePlayer.m

@@ -50,6 +50,8 @@
 
 @property (nonatomic, strong) dispatch_semaphore_t volumeChangeSemaphore;
 
+@property (nonatomic, assign) BOOL isInterrupt; // 是否被打断
+
 @end
 
 
@@ -109,9 +111,7 @@
         if (error) {
             self.audioEngine = nil;
             // 错误回调
-            if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayerDidError:error:)]) {
-                [self.delegate enginePlayerDidError:self error:error];
-            }
+            [self sendInterruptError:error];
         }
     }
 }
@@ -276,11 +276,6 @@
     
     AVAudioFrameCount minFrameCount = MIN(bgBuffer.frameLength, recordBuffer.frameLength);
     AVAudioFrameCount offsetFrame = labs(offsetTime)/1000.0 * recordBuffer.format.sampleRate;
-    // 检查 floatChannelData 是否为空
-    if (!bgBuffer.floatChannelData[0] || !bgBuffer.floatChannelData[1] || !recordBuffer.floatChannelData[0]) {
-        NSLog(@"Error: Float channel data is null");
-        return;
-    }
     
     float *bgLeftChannel = bgBuffer.floatChannelData[0];
     float *bgRightChannel = bgBuffer.floatChannelData[1];
@@ -342,36 +337,55 @@
     AVAudioSessionInterruptionType type = [info[AVAudioSessionInterruptionTypeKey] unsignedIntegerValue];
     if (type == AVAudioSessionInterruptionTypeBegan) {
         //Handle InterruptionBegan
-        if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayerDidError:error:)]) {
+        if (self.isInterrupt == NO) {
+            // 停止播放
+            if (self.nodePlayer.isPlaying) {
+                [self.nodePlayer stop];
+            }
+            self.isInterrupt = YES;
             NSError *error = [[NSError alloc] initWithDomain:NSCocoaErrorDomain code:99999 userInfo:@{@"errorDesc" : @"播放被打断"}];
-            [self.delegate enginePlayerDidError:self error:error];
+            [self sendInterruptError:error];
         }
     }
     else if (type == AVAudioSessionInterruptionTypeEnded) {
         AVAudioSessionInterruptionOptions options = [info[AVAudioSessionInterruptionOptionKey] unsignedIntegerValue];
-        if (options == AVAudioSessionInterruptionOptionShouldResume) {
+        if (options == AVAudioSessionInterruptionOptionShouldResume && self.isInterrupt) {
             //Handle Resume
-            [[AVAudioSession sharedInstance] setActive:YES error:nil];
+            NSError *error = nil;
+            [[AVAudioSession sharedInstance] setActive:YES error:&error];
+            if (error) {
+                NSLog(@"------ error desc %@", error.description);
+            }
+            NSLog(@"---- 播放恢复");
+            self.isInterrupt = NO;
         }
     }
 }
 
 - (void)handleRouteChange:(NSNotification *)notification {
-    
     NSDictionary *info = notification.userInfo;
-    if ([notification.name isEqualToString:AVAudioSessionRouteChangeNotification]) {
-        AVAudioSessionRouteChangeReason routeChangeReason = [[info valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
-        if (routeChangeReason == AVAudioSessionRouteChangeReasonCategoryChange) {
-            return;
+    AVAudioSessionRouteChangeReason reason = [info[AVAudioSessionRouteChangeReasonKey] unsignedIntegerValue];
+    if (reason == AVAudioSessionRouteChangeReasonOldDeviceUnavailable) {
+        // 耳机拔出时暂停音频
+        if (self.nodePlayer.isPlaying) {
+            NSError *error = nil;
+            [self sendInterruptError:error];
         }
-        if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayerDidError:error:)]) {
-            NSError *error = [[NSError alloc] initWithDomain:NSCocoaErrorDomain code:99999 userInfo:@{@"errorDesc" : @"播放被打断"}];
-            [self.delegate enginePlayerDidError:self error:error];
+        
+    } else if (reason == AVAudioSessionRouteChangeReasonNewDeviceAvailable) {
+        // 耳机插入时恢复音频
+        if (self.nodePlayer.isPlaying) {
+            NSError *error = nil;
+            [self sendInterruptError:error];
         }
     }
 }
 
-
+- (void)sendInterruptError:(NSError *)error {
+    if (self.delegate && [self.delegate respondsToSelector:@selector(enginePlayerDidError:error:)]) {
+        [self.delegate enginePlayerDidError:self error:error];
+    }
+}
 #pragma mark ------ play action
 
 - (void)changeRecordDelay:(NSInteger)delayMs {
@@ -379,6 +393,10 @@
 }
 
 - (void)seekToTimePlay:(NSInteger)time {
+    if (self.isInterrupt) {
+        [self sendInterruptError:nil];
+        return;
+    }
     if (self.audioEngine.isRunning == NO) {
         [self startEngine];
     }
@@ -397,6 +415,10 @@
 }
 
 - (void)seekToTime:(NSInteger)time {
+    if (self.isInterrupt) {
+        [self sendInterruptError:nil];
+        return;
+    }
     if (self.audioEngine.isRunning == NO) {
         [self startEngine];
     }