Пишем iOS видео-плеер и рекодер за 5 минут

  • Tutorial
Привет хабра-люди,

Под катом пошаговая инструкция как создать свое приложение с потоковым видео под iOS. Понадобится XCode, СДК с клиентским АПИ, ровные руки (в принципе необязательно) и чашечка кофе.



Сегодня мы покажем как просто и быстро с помощью BaaS платформы Backendless написать iOS приложение, которое может записывать видео на сервере и впоследствии проигрывать его.

(Кто пропустил первый пост русскоязычного обзора всех АПИ нашей платформы, может найти его здесь.)

Описание медиа сервиса
Media Services API (медиа потоки) – набор сервисов обеспечивающих “проигрывание по запросу” и живое потоковое видео и аудио. Приложения могут публиковать потоки с видеокамеры и микрофона для записи или живого вещания. Записанное медиа (видео или аудио) и живые стримы можно воспроизводить на других клиентах.

Пояснение: Медиа сервис позволяет стримать видео или аудио с клиентского приложения на сервер и воспроизводить этот поток на других устройствах. Так же можно воспроизводить медиа контент загруженый с помощью файл сервиса.

Примеры применения: видео-конференция, видео-чат, живая видео-трансляция одновременно с или на все устройства (с телефона, планшета, камеры ПК), запись видео или аудио сразу на сервер, живая аудио-трансляция (радио, музыка)

Дополнительную информацию и алгоритм работы АПИ медиа сервиса можно узнать из документации.

Итак, чтобы начать запустите «XCode»

Идем File->New->Project
-> Выберите «Single View Application» и кликните кнопку «Next»
-> Введите название приложения, на пр. «SimpleVideoService»
-> Выберите «iPhone» как устройство и нажмите «Next»
-> Выберите место для хранения вашего проекта

Теперь у вас есть проект с single view.
Приложению, подключаемому к платформе Backendless, нужно присвоить ID и прописать секретный ключ. Это делается в AppDelegate.m:

1 #import "AppDelegate.h"
2 #import "Backendless.h"
3 
4 // *** ВАМ НУЖНО НАСТРОИТЬ ЭТО ЧТОБЫ ВАШЕ ПРИЛОЖЕНИЕ БЫЛО ЗАРЕГЕСТРИРОВАНО***
5 
6 static NSString *APP_ID = @"";
7 static NSString *SECRET_KEY = @"";
8 static NSString *VERSION_NUM = @"v1";
9 
10 @implementation AppDelegate
11 
12 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
13 {
14 [backendless initApp:APP_ID secret:SECRET_KEY version:VERSION_NUM];
15 return YES;
16 }
17 
18 .....

Значения для APP_ID и SECRET_KEY нужно получить в веб-консоли разработчика. Залогиньтесь в консоль, «create/select» (выбор или создание нового приложения) и кликните иконку «Manage». Подраздел по умолчанию — App Settings:



Используйте кнопки “Copy” для копирования значений ID и секретного ключа приложения для iOS в ваш код. Скопированные значения присвоить к “APP_ID” и “SECRET_KEY” соответсвенно.

Перетяните и бросьте компонент «View» в ваше главное окно



Для удобства измените цвет фона рабочей области



Добавьте кнопки для управления видео потоком



Загрузите СДК для iOS http://backendless.com/downloads, распакуйте и перетяните библиотеку на файлы вашего проекта:



Также нам потребуются следующие стандартные библиотеки:
  • AudioToolbox.framework
  • AVFoundation.framework
  • CoreData.framework
  • CoreGraphics.framework
  • CoreMedia.framework
  • CoreVideo.framework
  • Libz.dylib
  • Security.framework



Откройте ViewController.m, импортируйте backendless и определите константы как показано ниже:

1 #import "Backendless.h"
2
3 #define VIDEO_TUBE @"videoTube"
4 #define STREAM_NAME @"defaultStreamName"

Присвойте следующие переменные:

1 @interface ViewController ()
2 {
3    MediaPublisher *_publisher;
4    MediaPlayer *_player;
5 } 

Откройте ViewController.h и объявите *preview свойство для получения картинки с камеры и *playbackView для проигрывания записанного видео:

1 @property (strong, nonatomic) IBOutlet UIView *preview;
2 @property (strong, nonatomic) IBOutlet UIImageView *playbackView;

Свойство *preview нужно связать с «View». Для того чтобы сделать это выберите компонент «view», перетяните и бросьте «New Referencing Outlet» на «preview».



Данный «view» будет использоваться для камеры. Также нам нужен «view» для проигрывания видео. Добавьте “Image View” и свяжите его с *playbackView.

Теперь нам нужно создать хэндлеры управления кнопками и добавить их сигнатуру в ViewController.h:

1 -(IBAction)onStopBtn:(id)sender;
2 -(IBAction)onPlayBtn:(id)sender;
3 -(IBAction)onRecordBtn:(id)sender;

Добавьте реализацию методов в ViewController.m.

Запись Видео

1 - (void)onRecordBtn:(id)sender
2 {
3  MediaPublishOptions *options = [MediaPublishOptions recordStream:self.preview];
4 _publisher =[backendless.mediaService publishStream: STREAM_NAME tube:VIDEO_TUBE options:options responder:self];
5 }

В строке 3 создаем инстанс MediaPublishOptions и привязываем компонент UI, который покажет записываемое видео.

В строке 4 мы создаем publisher. Конструктор паблишера принимает название потока, название канала, опции и респондер. Когда пользователь останавливает запись, мы проверяем или в данный момент паблишим (транслируем) видео, затем отсоединяемся от потока и присваиваем паблишеру и плееру nil.

1 -(void)onStopBtn:(id)sender
2 {
3     if (_publisher)
4     {
5         [_publisher disconnect];
6         _publisher = nil;
7     }
8      
9     if (_player)
10  {
11        [_player disconnect];
12        _player = nil;
13    }
14 }

Проигрывание Записанного Видео

1 - (void)onPlayBtn:(id)sender
2 {
3   MediaPlaybackOptions *options = [MediaPlaybackOptions recordStream:self.playbackView];
4    _player = [backendless.mediaService playbackStream:STREAM_NAME tube:VIDEO_TUBE: options:options responder:self];
5}

В строке 3 мы создаем инстанс MediaPlaybackOptions и передаем на компонент UI, который покажет записанное видео.

В строке 4 мы создаем медиа плеер. Конструктор принимает название потока, название канала, опции и респондер. Так как респонедр указывает на себя, то класс ViewController должен реализовывать IMediaStreamerDelegate.

Так как мы реализуем IMediaStreamerDelegate нам нужно добавить следующий код, чтобы реагировать на изменения в потоке:

1 -(void) streamConnectFailed:(id)sender code:(int)code description:(NSString *)description
2 {
3    NSLog(@"<IMediaStreamerDelegate> streamConnectFailed: %d = %@", (int)code, description);
4    [self onStopBtn:sender];
5    
6    NSString *message = (code == -1) ?
7    @"Unable to connect to the server. Make sure the hostname/IP address and port number are valid\n" :
8    [NSString stringWithFormat:@"connectFailedEvent: %@ \n", description];
9    UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Error:" message:message delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
10    [av show];
11 }
12
13 -(void) streamStateChanged:(id)sender state:(StateMediaStream)state description:(NSString *)description
14 {
15   switch (state) {
16            
17        case MEDIASTREAM_DISCONNECTED: {
18            
19            [self onStopBtn:sender];
20            break;
21        }
22            
23        case MEDIASTREAM_PAUSED: {
24            
25            [self onStopBtn:sender];
26            break;
27        }
28            
29        case MEDIASTREAM_PLAYING: {
30            
31            // PUBLISHER
32            if (_publisher) {
33                
34                if (![description isEqualToString:@"NetStream.Publish.Start"]) {
35                    [self onStopBtn:sender];
36                    break;
37                }
38            }
39            
40            // PLAYER
41            if (_player) {
42                
43                if (![description isEqualToString:@"NetStream.Play.Start"]) {
44                    UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Error:" message:[NSString stringWithString:description] delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
45                    [av show];
46                    break;
47                }
48                
49                self.playbackView.hidden = NO;
50            }
51            break;
52        }
53            
54        default:
55            break;
56    }
57 }

Почти все готово, осталось связать кнопки с хэндлерами.



Повторите то же самое для остальных кнопок.

Все :). Кофе допито, плеер работает. Код проекта можно скачать здесь.

Only registered users can participate in poll. Log in, please.

Насколько данный пост заинтересовал вас попробовать BaaS?

  • 38.8%обязательно попробую109
  • 23.5%врядли пригодится66
  • 37.7%мне пофиг106
Backendless
Company
Ads
AdBlock has stolen the banner, but banners are not teeth — they will be back

More

Comments 10

    0
    Спасибо за туториал-обзор.
    PS
    Потом после прочтения таких «пятиминутных» статей ко мне приходит начальник и говорит: «Юли ты так медленно работаешь?!» XD
      0
      Пожалуйста. На какую тему вы хотели бы здесь увидеть следующий тьюториал?
        +2
        Видимо как сделать так, чтобы начальник вообще не приходил)
          0
          Нет. Ну чего ж сразу.
          Интересно то, чего нет в Parse — например версионность.
      +2
      На какую тему вы хотели бы здесь увидеть следующий тьюториал


      Аудио рекордер с сохранением записей на сервер в популярных форматах.
        0
        Вы относите FLV формат к списку «популарных»?
          +3
          Нет. Отношу mp3, wav и aac.
            +1
            Ну если мы про iOS то и .caf можно в списочек (но это чисто для проги).
        +1
        Запахло андроид стайлом. Может это из-за названий функций так кажется?
        А вы написали этот пост потому что это одна из лучших либ для этих целей, или просто так? Есть подводные камни?
          0
          Лучше б потратили на пять минут больше, но отформатировали код.

          Only users with full accounts can post comments. Log in, please.