cineio-broadcast-ios - cine.io Broadcast iOS SDK
This is the cine.io Broadcast iOS SDK. This library allows you to do real-time live video streaming from your iOS device to any other device that supports RTMP or HLS streaming (iOS, Android, web).
Table of Contents
Installation
The easiest way to use the SDK is via CocoaPods. Create a new
XCode project with a file named Podfile
that contains at least the
following:
platform :ios, '7.0'
pod 'cineio-broadcast-ios', '~> 0.6'
Then, install the Pod by running the pod install
command:
pod install
Then you can open the project using the <project>.xcworkspace
file:
open <project>.xcworkspace
Example Application
Check out the cineio-broadcast-ios-example-app and cineio-broadcast-ios-swift-example-app repositories for working examples that use this SDK.
Basic Usage
Import the SDK
#import <cineio/CineIO.h>
Instantiate the client
CineClient *client = [[CineClient alloc] init];
Set the client properties
Most of the APIs on the CineClient require that the projectSecretKey
property
has been set. In addition, the getProjectsWithCompletionHandler
API requires
that the masterKey
property has been set. Be sure to set the appropriate
properties for the APIs you wish to use.
client.masterKey = @"YOUR_ACCOUNT_MASTER_KEY";
client.projectSecretKey = @"YOUR_PROJECT_SECRET_KEY";
Get your projects (asynchronously)
[client getProjectsWithCompletionHandler:^(NSError *err, NSArray *projects) {
for (id object in streams) {
CineProject *project = (CineProject *)object;
// do something
}
}];
Get your project (asynchronously)
[client getProjectWithCompletionHandler:^(NSError *error, CineProject *project) {
// do something
}];
Get your streams (asynchronously)
[client getStreamsWithCompletionHandler:^(NSError *err, NSArray *streams) {
for (id object in streams) {
CineStream *stream = (CineStream *)object;
// do something
}
}];
Get an individual stream (asynchronously)
[client getStream:@"<SOME STREAM ID>" withCompletionHandler:^(NSError* error, CineStream* stream) {
// do something
}];
Create a new stream (asynchronously)
[client createStream:@{ @"name" : @"my stream" } withCompletionHandler:^(NSError* error, CineStream* stream) {
// do something
}];
Update a stream (asynchronously)
[client updateStream:@{ @"" : "<SOME STREAM ID>", @"name" : @"my stream" } withCompletionHandler:^(NSError* error, CineStream* stream) {
// do something
}];
Delete a stream (asynchronously)
[client deleteStream:@"<SOME STREAM ID>" withCompletionHandler:^(NSError* error, NSHTTPURLResponse* response) {
// do something, like check for response.statusCode == 200
}];
Get the recordings of a stream (asynchronously)
[client getStreamRecordings:@"<SOME STREAM ID>" withCompletionHandler:^(NSError* error, NSArray* recordings) {
// do something
}];
Delete a stream recording (asynchronously)
[client deleteStreamRecording:@"<SOME STREAM ID>"
withName:@"foo.mp4"
andCompletionHandler:^(NSError* error, NSHTTPURLResponse* response) {
// do something, like check for response.statusCode == 200
}];
CinePlayerView
)
Playback (using To make playback as easy as possible, cineio-ios comes with a ready-made view controller that takes care of most of the heavy-lifting. Using it is pretty straight forward.
Storyboard Setup
If you're using XCode's Storyboards to build your user interface, our UI components should work seamlessly. To use them, follow these steps:
- Make your view controller inherit from
CinePlayerViewController
rather thanUIViewController
. - Ensure that the view controller in your Storyboard has the correct class name set. It should be set to your subclass of
CinePlayererViewController
.
stream
Property
The Your class that inherits from CinePlayerViewController
will have a writeable
stream
property. You'll need to ensure that this property is set with a
valid CineStream
object.
- (void)viewDidLoad
{
[super viewDidLoad];
//-- cine.io setup
// read our cine.io configuration from a plist bundle
NSString *path = [[NSBundle mainBundle] pathForResource:@"cineio-settings" ofType:@"plist"];
NSDictionary *settings = [[NSDictionary alloc] initWithContentsOfFile:path];
// create a new CineClient to fetch our stream information
CineClient *cine = [[CineClient alloc] initWithSecretKey:settings[@"CINE_IO_SECRET_KEY"]];
[cine getStream:settings[@"CINE_IO_STREAM_ID"] withCompletionHandler:^(NSError *error, CineStream *stream) {
if (error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Network error"
message:@"Couldn't get stream settings from cine.io."
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
} else {
self.stream = stream;
}
}];
Starting Playback
To start playback, simply call startStreaming
. This method will first
attempt to (asynchronously) validate that a stream exists at the given HLS
URL, and if it does, will start to play it. Otherwise, an appropriate error
message will be displayed in a UIAlert
.
You likely want to disable the idle timer in this method.
- (IBAction)playButtonPressed:(id)sender
{
playButton.enabled = NO;
playButton.hidden = YES;
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
[self startStreaming];
}
Cleaning up
When the stream has finished playing (for any reason, including the user
quitting, the stream ending, or if errors are encountered), finishStreaming
will be called. You should put any cleanup code that you want executed into
this method (such as re-enabling the idle timer).
- (void)finishStreaming
{
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
playButton.hidden = NO;
playButton.enabled = YES;
}
CineBroadcasterView
and CineBroadcasterViewController
)
Publishing (using To make publishing as easy as possible, cineio-ios comes with some ready-made user-interface components that take care of most of the heavy-lifting. Using them is pretty straight forward.
Setup
Handling Device Rotation
For user-experience reasons, our CineBroadcasterView uses neither "Auto
Layout" nor "Springs and Struts". Instead, the entire user-interface is
constructed programatically. This means that we need to listen for
notifications about when the device changes orientation. The best place to do
this is in the AppDelegate didFinishLaunchingWithOptions
method:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[[UIDevice currentDevice] beginGeneratingDeviceOrientationNotifications];
return YES;
}
Storyboard Setup
If you're using XCode's Storyboards to build your user interface, our UI components should work seamlessly. To use them, follow these steps:
- Make your view controller inherit from
CineBroadcasterViewController
rather thanUIViewController
. - Ensure that the view controller in your Storyboard has the correct class name set. It should be set to your subclass of
CineBroadcasterViewController
. - Ensure that the view in your Storyboard has the correct class name set. It should be set to
CineBroadcasterView
.
Initializing the properties
You'll need to initialize these properties, most likely in your viewDidLoad
method. For example:
- (void)viewDidLoad
{
//-- A/V setup
self.videoSize = CGSizeMake(1280, 720);
self.framesPerSecond = 30;
self.videoBitRate = 1500000;
self.sampleRateInHz = 44100; // either 44100 or 22050
// must be called _after_ we set up our properties, as our superclass
// will use them in its viewDidLoad method
[super viewDidLoad];
//-- cine.io setup
// read our cine.io configuration from a plist bundle
NSString *path = [[NSBundle mainBundle] pathForResource:@"cineio-settings" ofType:@"plist"];
NSDictionary *settings = [[NSDictionary alloc] initWithContentsOfFile:path];
// create a new CineClient to fetch our stream information
CineClient *cine = [[CineClient alloc] initWithSecretKey:settings[@"CINE_IO_SECRET_KEY"]];
[self updateStatus:@"Configuring stream using cine.io ..."];
[cine getStream:settings[@"CINE_IO_STREAM_ID"] withCompletionHandler:^(NSError *error, CineStream *stream) {
if (error) {
[self updateStatus:@"ERROR: couldn't get stream information from cine.io"];
} else {
self.publishUrl = [stream publishUrl];
self.publishStreamName = [stream publishStreamName];
// once we've fully-configured our properties, we can enable the
// UI controls on our view
[self enableControls];
}
}];
}
Streaming Hooks
You may want to take certain actions before or after streaming. You can do that
in the toggleStreaming
method. For example, you will likely want to enable /
disable the idle timer in this method as appropriate.
- (void)toggleStreaming:(id)sender
{
switch(self.streamState) {
case CineStreamStateNone:
case CineStreamStatePreviewStarted:
case CineStreamStateEnded:
case CineStreamStateError:
[[UIApplication sharedApplication] setIdleTimerDisabled:YES];
break;
default:
[[UIApplication sharedApplication] setIdleTimerDisabled:NO];
break;
}
// start / stop the actual stream
[super toggleStreaming:sender];
}
Acknowledgements
Much of the basis for the cine.io iOS SDK comes from the excellent VideoCore library.
Contributing
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request