Skip to end of metadata
Go to start of metadata

You are viewing an old version of this page. View the current version.

Compare with Current View Page History

« Previous Version 2 Next »

Пример iOS-приложения с плеером и стримером

Данное приложение может использоваться для публикации WebRTC-видеопотока и воспроизведения любого из следующих типов потоков с Web Call Server:

  • RTSP
  • WebRTC
  • RTMP
  • RTMFP

На скриншоте ниже представлен пример во время публикации и воспроизведени двух разных потоков.

Поля ввода

  • 'WCS URL', где 192.168.2.107 - адрес WCS-сервера
  • 'Publish Stream' - для имени публикуемого потока
  • 'Play Stream' - для имени воспроизводимого потока

Слева отображается видео с камеры, справа воспроизводится другой поток.

Работа с кодом примера

Для разбора кода возьмем версию примера TwoWayStreaming, которая доступена для скачивания в соответствующей сборке 2.5.2.

Класс для основного вида приложения: ViewController (заголовочный файл ViewController.h; файл имплементации ViewController.m).

1. Импорт API. код

#import <FPWCSApi2/FPWCSApi2.h>


2. Создание сессии и подключение к серверу.

FPWCSApi2 createSession, FPWCSApi2Session connect код

В параметрах сессии указываются:

  • URL WCS-сервера
  • имя серверного приложения defaultApp
- (FPWCSApi2Session *)connect {
FPWCSApi2SessionOptions *options = [[FPWCSApi2SessionOptions alloc] init];
options.urlServer = _connectUrl.text;
options.appKey = @"defaultApp";
NSError *error;
FPWCSApi2Session *session = [FPWCSApi2 createSession:options error:&error];
if (!session) {
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:@"Failed to connect"
message:error.localizedDescription
preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction* okButton = [UIAlertAction
actionWithTitle:@"Ok"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[self onDisconnected];
}];

[alert addAction:okButton];
[self presentViewController:alert animated:YES completion:nil];
return nil;
}

[session on:kFPWCSSessionStatusEstablished callback:^(FPWCSApi2Session *rSession){
[self changeConnectionStatus:[rSession getStatus]];
[self onConnected:rSession];
}];

[session on:kFPWCSSessionStatusDisconnected callback:^(FPWCSApi2Session *rSession){
[self changeConnectionStatus:[rSession getStatus]];
[self onDisconnected];
}];

[session on:kFPWCSSessionStatusFailed callback:^(FPWCSApi2Session *rSession){
[self changeConnectionStatus:[rSession getStatus]];
[self onDisconnected];
}];
[session connect];
return session;
}


3. Публикация видеопотока.

FPWCSApi2Session createStream, FPWCSApi2Stream publish код

Методу createStream передаются параметры:

  • имя публикуемого потока
  • вид для локального отображения
  • параметр record = true для записи потока при публикации
  • размеры и FPS публикуемого видео при публикации с iPad


- (FPWCSApi2Stream *)publishStream {
FPWCSApi2Session *session = [FPWCSApi2 getSessions][0];
FPWCSApi2StreamOptions *options = [[FPWCSApi2StreamOptions alloc] init];
options.name = _localStreamName.text;
options.display = _localDisplay;
if ( UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad ) {
options.constraints = [[FPWCSApi2MediaConstraints alloc] initWithAudio:YES videoWidth:640 videoHeight:480 videoFps:15];
}
NSError *error;
FPWCSApi2Stream *stream = [session createStream:options error:&error];
if (!stream) {
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:@"Failed to publish"
message:error.localizedDescription
preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction* okButton = [UIAlertAction
actionWithTitle:@"Ok"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[self onUnpublished];
}];

[alert addAction:okButton];
[self presentViewController:alert animated:YES completion:nil];
return nil;
}
[stream on:kFPWCSStreamStatusPublishing callback:^(FPWCSApi2Stream *rStream){
[self changeStreamStatus:rStream];
[self onPublishing:rStream];
}];

[stream on:kFPWCSStreamStatusUnpublished callback:^(FPWCSApi2Stream *rStream){
[self changeStreamStatus:rStream];
[self onUnpublished];
}];

[stream on:kFPWCSStreamStatusFailed callback:^(FPWCSApi2Stream *rStream){
[self changeStreamStatus:rStream];
[self onUnpublished];
}];
if(![stream publish:&error]) {
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:@"Failed to publish"
message:error.localizedDescription
preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction* okButton = [UIAlertAction
actionWithTitle:@"Ok"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[self onUnpublished];
}];

[alert addAction:okButton];
[self presentViewController:alert animated:YES completion:nil];
}
return stream;
}



4. Переключение камеры во время публикации потока

FPWCSApi2Stream switchCamera код

- (void)switchCameraButton:(UIButton *)button {
if ([FPWCSApi2 getSessions].count) {
FPWCSApi2Session *session = [FPWCSApi2 getSessions][0];
NSArray *streams = [session getStreams];
for (FPWCSApi2Stream *stream in streams ) {
if ([stream isPublished]) {
NSLog(@"Found published stream, switching camera");
[stream switchCamera];
}
}
} else {
NSLog(@"No active sessions found");
}
}


5. Воспроизведение видеопотока.

FPWCSApi2Session createStream, FPWCSApi2Stream play код

Методу createStream передаются параметры:

  • имя воспроизводимого потока
  • вид для отображения потока
- (FPWCSApi2Stream *)playStream {
FPWCSApi2Session *session = [FPWCSApi2 getSessions][0];
FPWCSApi2StreamOptions *options = [[FPWCSApi2StreamOptions alloc] init];
options.name = _remoteStreamName.text;
options.display = _remoteDisplay;
NSError *error;
FPWCSApi2Stream *stream = [session createStream:options error:nil];
if (!stream) {
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:@"Failed to play"
message:error.localizedDescription
preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction* okButton = [UIAlertAction
actionWithTitle:@"Ok"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {
[self onStopped];
}];

[alert addAction:okButton];
[self presentViewController:alert animated:YES completion:nil];
return nil;
}
[stream on:kFPWCSStreamStatusPlaying callback:^(FPWCSApi2Stream *rStream){
[self changeStreamStatus:rStream];
[self onPlaying:rStream];
}];

[stream on:kFPWCSStreamStatusNotEnoughtBandwidth callback:^(FPWCSApi2Stream *rStream){
NSLog(@"Not enough bandwidth stream %@, consider using lower video resolution or bitrate. Bandwidth %ld bitrate %ld", [rStream getName], [rStream getNetworkBandwidth] / 1000, [rStream getRemoteBitrate] / 1000);
[self changeStreamStatus:rStream];
}];

[stream on:kFPWCSStreamStatusStopped callback:^(FPWCSApi2Stream *rStream){
[self changeStreamStatus:rStream];
[self onStopped];
}];
[stream on:kFPWCSStreamStatusFailed callback:^(FPWCSApi2Stream *rStream){
[self changeStreamStatus:rStream];
[self onStopped];
}];
if(![stream play:&error]) {
UIAlertController * alert = [UIAlertController
alertControllerWithTitle:@"Failed to play"
message:error.localizedDescription
preferredStyle:UIAlertControllerStyleAlert];

UIAlertAction* okButton = [UIAlertAction
actionWithTitle:@"Ok"
style:UIAlertActionStyleDefault
handler:^(UIAlertAction * action) {

}];

[alert addAction:okButton];
[self presentViewController:alert animated:YES completion:nil];
}
return stream;
}


6. Остановка воспроизведения видеопотока.

FPWCSApi2Stream stop код

- (void)playButton:(UIButton *)button {
[self changeViewState:button enabled:NO];
if ([button.titleLabel.text isEqualToString:@"STOP"]) {
if ([FPWCSApi2 getSessions].count) {
FPWCSApi2Stream *stream;
for (FPWCSApi2Stream *s in [[FPWCSApi2 getSessions][0] getStreams]) {
if ([[s getName] isEqualToString:_remoteStreamName.text]) {
stream = s;
break;
}
}
if (!stream) {
NSLog(@"Stop playing, nothing to stop");
[self onStopped];
return;
}
NSError *error;
[stream stop:&error];
} else {
NSLog(@"Stop playing, no session");
[self onStopped];
}
} else {
if ([FPWCSApi2 getSessions].count) {
[self changeViewState:_remoteStreamName enabled:NO];
[self playStream];
} else {
NSLog(@"Start playing, no session");
[self onStopped];
}
}
}


7. Остановка публикации видеопотока. ViewController.m, line 274

FPWCSApi2Stream stop код

- (void)publishButton:(UIButton *)button {
[self changeViewState:button enabled:NO];
if ([button.titleLabel.text isEqualToString:@"STOP"]) {
if ([FPWCSApi2 getSessions].count) {
FPWCSApi2Stream *stream;
for (FPWCSApi2Stream *s in [[FPWCSApi2 getSessions][0] getStreams]) {
if ([[s getName] isEqualToString:_localStreamName.text]) {
stream = s;
break;
}
}
if (!stream) {
NSLog(@"Stop publishing, nothing to stop");
[self onUnpublished];
return;
}
NSError *error;
[stream stop:&error];
} else {
NSLog(@"Stop publishing, no session");
[self onUnpublished];
}
} else {
if ([FPWCSApi2 getSessions].count) {
[self changeViewState:_localStreamName enabled:NO];
[self publishStream];
} else {
NSLog(@"Start publishing, no session");
[self onUnpublished];
}
}
}


8. Закрытие соединения.

FPWCSApi2Session disconnect код

- (void)connectButton:(UIButton *)button {
[self changeViewState:button enabled:NO];
if ([button.titleLabel.text isEqualToString:@"DISCONNECT"]) {
if ([FPWCSApi2 getSessions].count) {
FPWCSApi2Session *session = [FPWCSApi2 getSessions][0];
NSLog(@"Disconnect session with server %@", [session getServerUrl]);
[session disconnect];
} else {
NSLog(@"Nothing to disconnect");
[self onDisconnected];
}
} else {
//todo check url is not empty
[self changeViewState:_connectUrl enabled:NO];
[self connect];
}
}


  • No labels