このトピックでは、ネイティブRTS SDKをApsaraVideo Player SDKに統合して、iOSクライアントにリアルタイムストリーミング (RTS) を実装する方法について説明します。
前提条件
CocoaPodsは開発環境にインストールされています。
SDKの統合
CocoaPodsを使用してApsaraVideo Player SDKとNative RTS SDKをインストールします。
ターミナルウィンドウを開きます。
プロジェクトのディレクトリで次のコマンドを実行して、Podfileを作成します。
pod init
Podfileで、SDKの最新バージョンを依存関係として追加します。
pod 'RtsSDK' pod 'AliPlayerSDK_iOS' pod 'AliPlayerSDK_iOS_ARTC'
説明AliPlayerSDK_iOS_ARTC
とRtsSDK
の依存関係を追加すると、RTS SDKはプラグインとしてApsaraVideo Player SDKに自動的に統合されます。別のバージョンのSDKを使用する場合は、バージョン番号を指定します。 例:
pod 'RtsSDK','2.1.0 '
ApsaraVideo Player SDK For iOSの最新バージョンの詳細については、「ApsaraVideo Player SDK for iOSのリリースノート」をご参照ください。 RTS SDK For iOSの最新バージョンの詳細については、「SDKのダウンロード」をご参照ください。Native RTS SDKのバージョンは、ApsaraVideo Player SDKのバージョンと一致する必要があります。 詳細については、「リリースノート」をご参照ください。
次のコマンドを実行してSDKをインストールします。 SDKのインストール後、*.xcworkspaceファイルが生成されます。
pod install
ApsaraVideo Player SDKが提供するメソッドを呼び出す
ApsaraVideo Player SDK for iOSが提供するメソッドを呼び出して、RTS機能を実装します。 ApsaraVideo Player SDKのその他の機能については、「高度な機能」と「ApsaraVideo Player SDK For AndroidのAPI操作」をご参照ください。
このセクションでは、キーコードのスニペットを提供します。 完全なサンプルコードについては、オープンソースプロジェクトMONE_demo_opensource_iOSのAUILiveRtsPlayコンポーネントの下にあるAUILiveRtsPlayPullViewControllerクラスを参照してください。
ApsaraVideo Player SDKを使用してRTS経由でストリームをプルする場合、一時停止メソッドを呼び出してストリームの再生を一時停止することはできません。 ストリームの再生を一時停止するには、stopメソッドを呼び出して再生を停止し、prepareメソッドを呼び出して再生を再開します。
ApsaraVideo Player SDKを使用してRTS経由でストリームをプルする場合、シークはサポートされません。
AliPlayerの初期化
- (AliPlayer *)aliPlayer{ if (!_aliPlayer) { _aliPlayer = [[AliPlayer alloc] init]; _aliPlayer.scalingMode = AVP_SCALINGMODE_SCALEASPECTFIT; _aliPlayer.rate = 1; // If you want to use AVPDelegate, add the following line: _aliPlayer.delegate = self; // Configure the user interface (UI) view and apply the UI view to AliPlayer. _aliPlayer.playerView = self.basePlayerView.playerView; _aliPlayer.autoPlay = YES; } return _aliPlayer; }
ストリーミングURLの設定
AVPUrlSource *source = [[AVPUrlSource alloc] urlWithString:_url]; [self.aliPlayer setUrlSource:source];
再生パラメーターの設定
RTSのパフォーマンスを向上させるために、次の再生パラメーターを設定します。
prepare
メソッドを呼び出す前に、パラメーターを設定する必要があります。 それ以外の場合、設定は有効になりません。AVPConfig *config = self.aliPlayer.getConfig; // The maximum streaming latency. [config setMaxDelayTime:1000]; // The buffer period. [config setHighBufferDuration:10]; // The maximum startup latency. [config setStartBufferDuration:10]; [_aliPlayer setConfig:config]; // By default, hardware decoding is enabled. If hardware decoding fails during the preparation stage of the player, the player automatically switches to software decoding. _aliPlayer.enableHardwareDecoder = YES;
ロギングの有効化または無効化
// Enable logging. [AliPlayer setEnableLog:YES]; [AliPlayer setLogCallbackInfo:LOG_LEVEL_TRACE callbackBlock:nil]; // Disable logging. [AliPlayer setEnableLog:NO]; [AliPlayer setLogCallbackInfo:LOG_LEVEL_NONE callbackBlock:nil];
説明ストリームがRTMP (Real-Time Messaging Protocol) を介してプルされている場合は、物理デバイスでデバッグするときにログを無効にすることを推奨します。
プレーヤーを制御する
[self.aliPlayer prepare]; [self.aliPlayer stop]; [self.aliPlayer destroy]; [self.aliPlayer reload];
再生前にデリゲートを登録する
-(void)createAliPlayer { // 1. Create a player instance. AliPlayer *aliPlayer = [[AliPlayer alloc] init]; AVPConfig *config = [aliPlayer getConfig]; config.maxDelayTime = 1000; config.highBufferDuration = 10; config.startBufferDuration = 10; // 2. Register a delegate. aliPlayer.delegate = self; [aliPlayer setConfig:config]; aliPlayer.autoPlay = YES; NSString *url = "artc://xxxx"; AVPUrlSource *source = [[AVPUrlSource alloc] urlWithString:self.url]; [aliPlayer setUrlSource:source]; [aliPlayer prepare]; } // 3. Listen for player events. -(void)onPlayerEvent:(AliPlayer*)player eventWithString:(AVPEventWithString )eventWithString description:(NSString *)description { }
標準ストリーミングに戻す
RTSの再生に失敗したときに標準ストリーミングに戻すには、artc:// というプレフィックスが付いたストリーミングURLをHTTP-FLV形式に変換し、新しいURLを再生に使用します。
self.playUrl = @"artc://xxxx"; // Stop the playback. [self.aliplayer stop]; // Obtain the prefix of the streaming URL. NSArray *urlSeparated = [self.playUrl componentsSeparatedByString:@"://"]; NSString *urlPrefix = urlSeparated.firstObject; // Check whether the prefix of the URL is artc. If the prefix is artc, convert the URL to the HTTP-FLV format. if ([urlPrefix isEqualToString:@"artc"]) { self.playUrl = @"http://xxxx.flv"; // Set the value to your actual streaming URL in the HTTP-FLV format. // Re-configure the playback source and prepare for playback. AVPConfig *config = [self.player getConfig]; config.maxDelayTime = 10000; config.highBufferDuration = 100; config.startBufferDuration = 100; [self.aliplayer setConfig:config]; AVPUrlSource *source = [[AVPUrlSource alloc] urlWithString:self.playUrl]; [self.aliplayer setUrlSource:source]; // Start the playback. [self.aliplayer prepare]; }
イベントリスナーを使用して、RTS SDKが期待どおりに実行されるかどうかを確認します。 イベントリスナーが再生開始またはライブストリーミング中にプレーヤーコンポーネントからメッセージを受信した場合、codeパラメーターを使用してメッセージからRTS SDKの詳細を抽出します。 コードパラメーターの値がE_DNS_FAIL、E_AUTH_FAIL、E_CONN_TIMEOUT、E_SUB_TIMEOUT、またはE_SUB_NO_STREAMの場合、標準ストリーミングに戻ります。 値がE_STREAM_BROKENの場合、再生を1回再試行します。 再生を再試行した後、値がE_STREAM_BROKENの場合は、標準ストリーミングに戻ります。 値がE_RECV_STOP_SIGNALの場合は、引き続きRTSを使用できます。
このロジックを実装するには、必ずRTS SDKの必要なAPIをインポートします。
#import <RtsSDK/rts_messages.h>
イベントリスナーのサンプルコード:
self.retryStartPlay = YES; ...... /** @brief The callback for player events. @param player The pointer for the player. @param eventWithString The type of the player event. @param description The description of the player event. @see AVPEventType */ - (void)onPlayerEvent:(AliPlayer*)player eventWithString:(AVPEventWithString)eventWithString description:(NSString *)description { switch (eventWithString) { case EVENT_PLAYER_DIRECT_COMPONENT_MSG: { NSDictionary *descriptionDic = [[description rts_toDictionary] copy]; NSString *contentStr = [descriptionDic objectForKey:@"content"]; NSDictionary *kv = [contentStr rts_paramsToDictionaryWithSeparator:@"="]; NSNumber *type = [kv objectForKey:@"code"]; switch (type.intValue) { case E_DNS_FAIL: // DNS resolution failed. case E_AUTH_FAIL: // Authentication failed. case E_CONN_TIMEOUT: // Connection timed out. case E_SUB_TIMEOUT: // An error occurred during subscription or subscription timed out. case E_SUB_NO_STREAM: // The stream to which the user subscribes does not exist. { // Revert to Standard Streaming. } break; case E_STREAM_BROKEN: // Audio and video packet transmission were interrupted due to a timeout. { // The first time you receive the message, retry the playback once. if (self.retryStartPlay) { [self onStartPlay]; self.retryStartPlay = NO; } else { // If you receive the message again, revert to Standard Streaming. } } break; case E_RECV_STOP_SIGNAL: { // Stop the playback. [self.aliplayer stop]; } break; default: break; } } break; default: break; } } ...... #pragma mark -- Categorize NSString, extract common methods, and parse the JSON string. - (NSDictionary *)rts_toDictionary { if (self == nil) { return nil; } NSData *jsonData = [self dataUsingEncoding:NSUTF8StringEncoding]; NSError *err; NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&err]; if(err) { NSLog(@"JSON parsing failed: %@",err); return nil; } return dic; } - (NSDictionary *)rts_paramsToDictionaryWithSeparator:(NSString*)split { if (self == nil) { return nil; } NSMutableDictionary *multiDic = @{}.mutableCopy; NSString *content = [self stringByReplacingOccurrencesOfString:@"\"" withString:@""]; NSArray *arr = [content componentsSeparatedByString:@","]; if (arr.count>0) { for (NSString *str in arr) { NSArray *kvArr = [str componentsSeparatedByString:split]; if (kvArr.count==2) { [multiDic setValue:kvArr[1] forKey:kvArr[0]]; } } } return multiDic; }
RTS TraceIDの取得
イベントリスナーを使用してRTS TraceIDを取得します。 イベントリスナーがプレーヤーコンポーネントからメッセージを受信した場合、codeパラメーターを使用してメッセージからRTS SDKの詳細を抽出します。 codeパラメーターの値がE_HELP_SUPPORT_ID_SUBSCRIBEの場合、返されるJSON文字列の "-sub-" の後にTraceIdが追加されます。
- (void)onPlayerEvent:(AliPlayer*)player eventWithString:(AVPEventWithString)eventWithString description:(NSString *)description { switch (eventWithString) { case EVENT_PLAYER_DIRECT_COMPONENT_MSG: { NSDictionary *descriptionDic = [[description rts_toDictionary] copy]; NSString *contentStr = [descriptionDic objectForKey:@"content"]; NSDictionary *kv = [contentStr rts_paramsToDictionaryWithSeparator:@"="]; NSNumber *type = [kv objectForKey:@"code"]; switch (type.intValue) { case E_HELP_SUPPORT_ID_SUBSCRIBE: // Obtain the TraceId. { NSString *desc = [kv objectForKey:@"desc"]; if ([desc containsString:@"-sub-"]) { NSString *traceId = [desc componentsSeparatedByString:@"-sub-"].lastObject; self.traceId = traceId; } } break; default: break; } } break; default: break; } }