We all deal with inter- What? Not now, I’m in the middle of something. . . Sorry, let’s try that again; we all deal with interruptions. From chatty co-workers to adorable cat video distractions, something always manages to turn that five-minute task into an all day endeavor. When an incoming phone call cuts in the middle of your Red5 Pro live stream, well that’s just outright disruptive. Fortunately, the following steps show you how to deal with these interruptions on your iPhone.
Now I know what you’re thinking; “That’s all well and good, but what about Android?”. No worries, we will deal with Android in a future blog post. So bear with us for a bit and we will have more instructions for Android users as well.
For those trying to quickly get back to that “five-minute” task, basically you can use the R5RecordTypeAppend
publish type for the R5Stream:publish:type
API while providing the stream name used prior to the interruption.
In this example, we will show how to resume a broadcast from an iOS Interruption, such as a Phone Call or Siri activation.
We can explain our feature(s) of resumable interrupt recording as such:
*Given* I have started a broadcast session*When* I receive an interrupt in my App (e.g., Phone Call, Siri Activation)*Then* My recording session is paused
*Given* I have started a broadcast session*And* I receive an interrupt in my App (e.g., Phone Call, Siri Activation)*When* I return from the interrupt (e.g., Decline of Phone Call)*Then* My recording is resumed from the point of interruption
*Given* I have started a broadcast session*And* I receive an interrupt in my App (e.g., Phone Call, Siri Activation)*When* I enter my App into the background (e.g., Accept of Phone Call)*And* I re-launch the App*Then* A new broadcast session is started
In order to implement the expectations of our feature specification, we need to first establish the Givens in of our scenarios which describe the creation of a broadcast session.
We will use an R5VideoViewController
from the Red5 Pro SDK as the base for our broadcast session and logic for maintaining our interrupt and background recording feature specifications.
For additional information on creating a
ViewController
for streaming on iOS, visit the documentation at https://www.red5pro.com/docs/streaming/ios/.
PublishViewController.h
@interface PublishViewController : R5VideoViewController<R5StreamDelegate>- (void)start:(NSString *)theStreamName;- (void)stop;- (void)resume:(NSString *)theStreamName;@end
PublishViewController.m
#import "PublishViewController.h"#import <R5Streaming/R5Streaming.h>@interface PublishViewController () { R5Configuration *config; R5Stream *stream; NSString *streamName; BOOL isResumable;}@end@implementation PublishViewController {- (void)start:(NSString *)streamName {}- (void)stop {}- (void)resume:(NSString *)streamName {}}@end
This serves as the initial class template for a ViewContoller that will handle the logic of the feature specifications, with the internal property declarations to manage the configuration and stream.
We’ll create a method to generate a class-local configuration that can be used throughout the recording sessions on the PublishViewController
:
PublishViewController.m
- (void)createConfiguration { config = [R5Configuration new]; config.host = @"localhost"; config.port = 8554; config.contextName = @"live";
The following method will establish a connection and make a broadcast session eligible for publishing:
PublishViewController.m
- (void)preview { NSArray *cameras = [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo]; AVCaptureDevice *cameraDevice = [cameras lastObject]; R5Camera *camera = [[R5Camera alloc] initWithDevice:cameraDevice andBitRate:512]; AVCaptureDevice *audioDevice= [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio]; R5Microphone *microphone = [[R5Microphone new] initWithDevice:audioDevice]; R5Connection *connection = [[R5Connection new] initWithConfig:config]; stream = [[R5Stream new] initWithConnection:connection]; [stream attachVideo:camera]; [stream attachAudio:microphone]; [stream setDelegate:self]; [self attachStream:stream]; [self showPreview:YES];}
In order to start showing a Broadcasters video without publishing to the Red5 Pro server, we will invoke the configuration and preview in the viewDidLoad
override of PublishViewController
:
PublishViewController.m
- (void)viewDidLoad { [super viewDidLoad]; [self createConfiguration]; [self preview];}
Now that we have established the references for config
and stream
, we can think about the specifics of the actions within a broadcast session.
In the start:streamName
method, we will use the stream created upon viewDidLoad
and start a publishing session with the publish type of R5RecordTypeRecord
:
PublishViewController.m
- (void)start:(NSString *)theStreamName { streamName = theStreamName; [self showPreview:NO]; [stream publish:streamName type:R5RecordTypeRecord];}
In the stop
method, we will stop the publishing session, deallocate the currently established stream and reset the preview:
PublishViewController.m
- (void)stop { [stream stop]; [stream setDelegate:nil]; stream = nil;}
The resume:streamName
method is relatively similar to the start:streamName
method, however in resume:
we do not assign the class-local streamName
(using its value already defined) and specify the R5RecordTypeAppend
type:
- (void)resume:(NSString *)theStreamName { [self showPreview:NO]; [self publish:theStreamName type:R5RecordTypeAppend];}
In order to properly handle interrupts and background entrance of your App, assign NSNotification
handlers in the viewDidLoad
override of PublishViewController
:
PublishViewController.m
- (void)viewDidLoad { [super viewDidLoad]; [self createConfiguration]; [self preview]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidEnterBackgroundNotification:) name:UIApplicationDidEnterBackgroundNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationWillResignActiveNotification:) name:UIApplicationWillResignActiveNotification object:nil]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationDidBecomeActiveNotification:) name:UIApplicationDidBecomeActiveNotification object:nil];}
When your iOS device enters an “interrupt”, your application is still active – meaning not in the background – and is waiting for a response to the interrupt. Such interruptions can be a Phone Call or the activation of Siri. During such interruptions, the User action will determine the following state and notification.
If you chose, for instance, to Decline a phone call, the subsequent notification dispatched will be applicationDidBecomeActiveNotification
. If you chose to Accept the phone call, the subsequent notification dispatched will be applicationDidEnterBackgroundNotification
and your App will be put into the background.
The applicationWillResignActiveNotification
is notified on the observer when the device enters an “interrupt”. In such a case, we want to stop or broadcast session, but retain the possibility of resuming the broadcast if the user declines or dismisses the “interrupt” without the application going into the background. A most common case is the Decline of an incoming Phone Call.
- (void)applicationWillResignActiveNotification:(NSNotification *)notification { if (stream != nil && stream.mode == r5_stream_mode_publish) { isResumable = YES; } [self stop]; [self preview];}
We first check if we have a stream established and are currently in a publishing session. If so, then we can consider the app in an isResumable
state if we were to come back from an “interrupt” without the app going into the background.
The applicationDidBecomeActiveNotification
is notified in two cases:
In the first case, we have defined the App in an isResumable
state in case we return from an “interrupt” without sending the App into the background. In such as case, we want to invoke the resume:streamName
method:
- (void)applicationDidBecomeActiveNotification:(NSNotification *)notification { if (isResumable) { isResumable = NO; [self resume:streamName]; }}
In the second case, we do not want to consider the broadcast resumable. As such, we need to handle when the App does go into the background following an “interrupt”.
- (void)applicationDidEnterBackgroundNotification:(NSNotification *)notification { isResumable = NO; [self stop];}
In this example, we created a resumable broadcast from an iOS interrupt – such as from a Decline from Phone Call. We used the R5RecordTypeAppend
option for R5Stream:publish:type
when the App was considered in an isResumable
state following an “interrupt” without sending the App into the background.
As organizations evaluate live streaming solutions, Amazon Interactive Video Service (IVS) has emerged as a…
Let’s go over the latest updates introduced in Red5 Cloud since our previous blog covering…
When businesses need ultra-low latency streaming capabilities, the choice of platform can significantly influence the…
1Understanding AWS IVS: Strengths and Limitations2Red5: A More Flexible Alternative3When to Choose Red5 Over AWS…
Let’s take a look at the latest Red5 Pro and Red5 Cloud releases introduced since…
1Quick Comparison Overview2The Complete Evolution: VP8 → VP9 → AV13Technical Comparison: VP8 vs VP9 vs…