ApsaraVideo VOD iOS アップロード SDK を使用すると、アプリから動画ファイルと画像ファイルを VOD ストレージに直接アップロードできます。アプリはバックエンドの認証サービスからアップロード認証情報を取得し、SDK はその認証情報を使用して、サーバーを経由せずに OSS にファイルをアップロードします。
仕組み
アップロードプロセスには、iOS アプリ、バックエンドサービス、および ApsaraVideo VOD (OSS にファイルを保存) の 3 者が関わります。ワークフローは次のとおりです:
アプリが SDK を呼び出してアップロードを開始すると、SDK は
getAuthコールバックを呼び出します。コールバックでは、お使いのアプリがバックエンドサービスにアップロード認証情報を要求すると、バックエンドサービスは VOD OpenAPI 操作 (
CreateUploadVideoなど) を呼び出してレスポンスを返します。アプリが OpenAPI レスポンスを SDK に渡すと、SDK はそのレスポンスから
UploadAuthとUploadAddressを抽出し、ファイルを直接 OSS にアップロードします。大規模なアップロード中に認証情報の期限が切れると、SDK は refresh 種別で
getAuthコールバックを再度呼び出し、新しい認証情報を取得します。
前提条件
項目 | 要件 |
最小 iOS バージョン | iOS 12.0 |
開発言語 | Objective-C (Swift プロジェクトでは Bridging Header を使用してブリッジします) |
Alibaba Cloud アカウント | ApsaraVideo VOD が有効化されていること |
認証サービス | アップロード認証情報 ( |
SDK の統合
統合方法
方法 1:Pod 統合
お使いの Podfile に以下の内容を追加します:
platform :ios, '12.0'
target 'YourApp' do
pod 'VODUpload', '~> 2.0'
end次のコマンドを実行します:
pod repo update
pod installSDK は、基盤となる AliyunOSSiOS 依存関係を自動的にプルします。
方法 2:Swift Package Manager (SPM) 統合
Xcode のメニューで [File]→[Add Package Dependencies] を選択し、リポジトリアドレス https://github.com/aliyunvideo/VODUpload.git を入力します。
バージョンルールには Up to Next Major Version を選択し、初期バージョンに 2.0.1 を入力します。
プロダクト
VODUploadを App ターゲットに追加します。
または、Package.swift で宣言します:
package(url: "https://github.com/aliyunvideo/VODUpload.git", from: "2.0.1")内部の OSS 依存関係はメインパッケージとともに自動的に解決されます。手動で追加したり設定したりする必要はありません。統合完了後は、import VODUpload を記述するだけで利用できます。API の使用方法は CocoaPods で統合した場合と同じです。
プロジェクト設定
podspec では次のシステムライブラリが宣言されており、CocoaPods で統合すると自動的にリンクされます:
SystemConfiguration.framework
MobileCoreServices.framework
CoreMedia.framework
AVFoundation.framework
CoreTelephony.framework
libresolv.tbdSDK には PrivacyInfo.xcprivacy プライバシーマニフェストが含まれており、Pod 統合時に自動的に VODUpload.bundle/PrivacyInfo.xcprivacy にインジェクトされます。追加の設定は不要です。
必要なヘッダーファイルをインポートします:
#import <VODUpload/VODUploadV2Client.h>
#import <VODUpload/VODUploadConfig.h>
#import <VODUpload/VODAuthContext.h>
#import <VODUpload/VODGetAuthCallback.h>
#import <VODUpload/VODUploadOptions.h>
#import <VODUpload/VODUploadResult.h>
#import <VODUpload/VODUploadError.h>
#import <VODUpload/VODVideoMeta.h>
#import <VODUpload/VODImageMeta.h>
#import <VODUpload/VODUploadTask.h>アップロードのワークフロー
アップロードインスタンスの初期化
VODUploadConfig は、プロパティを使用して直接設定を行います。+uploaderWithConfig: ファクトリメソッドを呼び出してインスタンスを作成します。
VODUploadConfig *config = [[VODUploadConfig alloc] init];
config.getAuth = getAuth; // 必須:認証コールバック。詳細については、「認証コールバックの処理」をご参照ください。
VODUploadV2Client *uploader = [VODUploadV2Client uploaderWithConfig:config];uploader インスタンスはプロパティとして保持する必要があります。ローカル変数にすると、ARC によって解放されてしまい、コールバックが失われる原因となります。同じインスタンスを再利用して、複数のファイルを並行してアップロードできます。ライフサイクルの終了時に [uploader dispose] を呼び出して、リソースを解放してください。
ファイルのアップロード
uploadFile:options:callback: を呼び出してアップロードを開始します。このメソッドは、キャンセルに使用できる VODUploadTask ハンドルを返します:
VODVideoMeta *meta = [[VODVideoMeta alloc] init];
meta.title = @"My Video";
meta.tags = @"demo";
meta.cateId = @(1000);
VODUploadOptions *options = [[VODUploadOptions alloc] init];
options.videoMeta = meta;
options.onProgress = ^(float percent, int64_t uploaded, int64_t total) {
NSLog(@"%.1f%%", percent * 100);
};
VODUploadTask *task = [uploader uploadFile:filePath
options:options
callback:^(VODUploadResult *r, VODUploadError *e) {
if (e) {
NSLog(@"%@: %@", e.errorCode, e.errorMessage);
return;
}
NSLog(@"videoId=%@ uploadTaskId=%@ etag=%@ requestId=%@ durationMs=%lld",
r.videoId, r.uploadTaskId, r.etag, r.requestId, r.durationMs);
}];
// アップロードをキャンセルします。レジュームアップロードはデフォルトで有効なため、同じファイルで次回 uploadFile を呼び出すと、アップロードが自動的に再開されます。
[task cancel];
// task.uploadTaskId はログの関連付けやトラッキング連携に使用できます。画像のアップロード: SDK は、ファイル拡張子 (jpg / jpeg / png / gif / bmp / webp / heic) に基づく場合、または options.imageMeta != nil が明示的に設定されている場合に、自動的に画像のアップロードとして処理します。成功コールバックでは、imageId と imageUrl に値が設定されます。
VODImageMeta *imgMeta = [[VODImageMeta alloc] init];
imgMeta.imageType = @"cover";
imgMeta.title = @"Cover";
VODUploadOptions *opts = [[VODUploadOptions alloc] init];
opts.imageMeta = imgMeta;
[uploader uploadFile:imagePath options:opts callback:cb];VODVideoMeta の説明フィールドは、Objective-C の予約済みメソッドとの競合を避けるため、description ではなく desc です。
認証コールバックの処理
v2 では、VODGetAuthCallback ブロックはアプリケーションからアップロード認証情報を要求します。SDK は特定のタイミングで getAuth を呼び出し、VODAuthContext.kind を使用して必要な認証情報タイプを示します。
Kind | トリガー | 呼び出す OpenAPI |
VODAuthKindCreateVideo | 動画ファイルの初回アップロード | |
VODAuthKindRefreshVideo | レジュームアップロード / 認証情報の更新 | |
VODAuthKindCreateImage | 画像のアップロード |
アプリケーションは、バックエンドの OpenAPI 呼び出しからの raw JSON レスポンスを completion に直接渡します。SDK は、OpenAPI レスポンスからフィールド名で次のキーを読み取ります (大文字と小文字が区別されます):
Kind | 必須フィールド |
VODAuthKindCreateVideo / VODAuthKindRefreshVideo | UploadAuth, UploadAddress, VideoId |
VODAuthKindCreateImage | UploadAuth, UploadAddress, ImageId, ImageURL |
フィールド名では大文字と小文字が区別されます。OpenAPI レスポンスはそのまま渡してください。フィールドを手動で videoId、imageUrl、または image_url に名前変更すると、SDK はそれらを nil として解析します。
VODGetAuthCallback getAuth = ^(VODAuthContext *ctx,
void (^completion)(NSDictionary *result, NSError *error)) {
switch (ctx.kind) {
case VODAuthKindCreateVideo:
[YourBackend createUploadVideo:ctx.fileName
fileSize:ctx.fileSize
completion:^(NSDictionary *json, NSError *err) {
completion(json, err);
}];
break;
case VODAuthKindRefreshVideo:
[YourBackend refreshUploadVideo:ctx.videoId
completion:^(NSDictionary *json, NSError *err) {
completion(json, err);
}];
break;
case VODAuthKindCreateImage:
[YourBackend createUploadImage:ctx.fileName
completion:^(NSDictionary *json, NSError *err) {
completion(json, err);
}];
break;
}
};高度な設定
アップロードアクセラレーション
VODVideoMeta.userData を次の JSON に設定すると、UploadAddress の発行時に VOD サーバーが OSS グローバル転送アクセラレーションエンドポイント (oss-accelerate.aliyuncs.com) を自動的に返します。SDK はそのアクセラレーションエンドポイントに直接アップロードします。
VODVideoMeta *meta = [[VODVideoMeta alloc] init];
meta.title = @"My Video";
meta.userData = @"{\"Type\":\"oss\",\"Domain\":\"oss-accelerate.aliyuncs.com\"}";アップロードアクセラレーションは OSS グローバル転送アクセラレーションに依存します。OSS コンソールでバケットの転送アクセラレーションを有効にする必要があります。詳細については、「転送アクセラレーションを使用した OSS へのアクセス」をご参照ください。
アップロードとトランスコード
VODVideoMeta を使用して、トランスコーディングテンプレートグループまたはワークフローを指定します:
VODVideoMeta *meta = [[VODVideoMeta alloc] init];
meta.title = @"My Video";
meta.desc = @"Video description"; // 注:description ではなく desc を使用します
meta.coverUrl = @"https://example.com/cover.jpg";
meta.cateId = @(1000);
meta.tags = @"tag1,tag2";
meta.storageLocation = @"<Optional: custom storage region>";
meta.templateGroupId = @"<Your template group ID>"; // トランスコードテンプレートグループ
meta.workflowId = @"<Your workflow ID>"; // ワークフロー (オプション)
meta.appId = @"<Optional: application ID>";VODVideoMeta でサポートされているフィールドは、title、desc、coverUrl、cateId、tags、userData、storageLocation、templateGroupId、workflowId、および appId です。すべてのフィールドは任意であり、CreateUploadVideo に渡されます。
アップロードが完了すると、VOD サーバーはテンプレートグループに基づいてソースビデオをトランスコードします。トランスコードを開始したくない場合は、バックエンドから CreateUploadVideo を呼び出す際に、「トランスコードなし」テンプレートグループを渡します。
タイムアウトとリトライ
VODUploadConfig *config = [[VODUploadConfig alloc] init];
config.getAuth = getAuth;
config.timeout = 60; // 単位:秒。デフォルト値:60
config.maxRetryCount = 2; // デフォルト値:2timeout は、単一の OSS リクエストに対する接続および読み書きのタイムアウト (NSTimeInterval、秒単位) を制御します。maxRetryCount は、ネットワークエラー発生時の OSS リクエストの再試行回数を制御します。
timeout の単位は、Android ではミリ秒、iOS では秒です。クロスプラットフォームで実装する際は、この違いにご注意ください。
署名バージョン
config.signature = @"v4"; // デフォルト値:@"v4"。有効な値:@"v1"OSS V4 署名は推奨バージョンです。2025 年 9 月 1 日以降、新規作成バケットには V4 署名が必須となります。既存のお客様も、お早めの移行を推奨します。アプリケーションで使用されるバケットがまだ V1 署名のみをサポートしている場合にのみ、@"v1" を明示的に設定してください。
レジュームアップロード
レジュームアップロードはデフォルトで有効になっています。SDK は (lastModified, fileName, fileSize) の 3つ組をレジュームアップロードキーとして使用し、それをローカルの Caches ディレクトリに自動的に永続化します。
シナリオ | SDK の動作 |
| レジュームアップロードの記録は保持されます。次に同じファイルで |
アプリがクラッシュする、またはバックグラウンドで終了する | レジュームアップロードの記録は保持されます。 次のコールドスタート時に同じファイルで |
ファイルフィンガープリントの変更 | ファイルは新規ファイルとして扱われ、最初からアップロードされます。 |
OSS uploadId の有効期限切れ | SDK は古い記録を自動的にクリアし、 |
レジュームアップロードを無効にするには:
config.checkpoint = NO;マルチパートアップロード
partSize でパートサイズを制御し、parallel で並列数を制御します。
// グローバル設定
config.partSize = 1024 * 1024; // デフォルト値:1 MB
config.parallel = 4; // デフォルト値:4
// タスク単位で上書き
VODUploadOptions *options = [[VODUploadOptions alloc] init];
options.videoMeta = meta;
options.partSize = 2 * 1024 * 1024;
options.parallel = 6;VOD サービスリージョンの設定
config.region = @"cn-shanghai"; // デフォルト値:cn-shanghaiサポートされているリージョンの一覧については、「ApsaraVideo VOD のリージョン ID」をご参照ください。
データレポート
SDK は、製品品質の監視のためにアップロードリンクトラッキングをデフォルトで有効にしています。収集されるのはアップロードプロセスの実行時メトリクスのみで、ファイル内容は含まれません。データレポートを無効にするには:
config.reportEnabled = NO; // デフォルト値:YESエラー処理
VODUploadError は NSError を継承します。エラーコードは UPLOAD.{LAYER}.{TYPE} の 3 セグメント形式です:
LAYER | エラーコード | 説明 |
AUTH | UPLOAD.AUTH.GET_AUTH_FAILED | getAuth コールバックに失敗しました。 |
AUTH | UPLOAD.AUTH.DECODE_FAILED | UploadAuth のデコードに失敗しました。 |
AUTH | UPLOAD.AUTH.EXPIRED | 認証情報の有効期限が切れています。 |
OSS | UPLOAD.OSS.ACCESS_DENIED | OSS へのアクセスが拒否されました (権限/署名の問題)。 |
OSS | UPLOAD.OSS.NO_SUCH_BUCKET | バケットが存在しません。 |
OSS | UPLOAD.OSS.NO_SUCH_UPLOAD | uploadId の有効期限が切れています。SDK は自動的にフォールバックします。 |
OSS | UPLOAD.OSS.UPLOAD_FAILED | OSS のアップロードに失敗しました。 |
OSS | UPLOAD.OSS.MERGE_FAILED | OSS マルチパートのマージに失敗しました。 |
NETWORK | UPLOAD.NETWORK.TIMEOUT | ネットワークタイムアウト。 |
NETWORK | UPLOAD.NETWORK.UNREACHABLE | ネットワークに到達できません。 |
FILE | UPLOAD.FILE.NOT_FOUND | ファイルが存在しません。 |
FILE | UPLOAD.FILE.EMPTY | ファイルが空です。 |
CANCEL | UPLOAD.CANCEL.USER_CANCELLED | ユーザーがアップロードをキャンセルしました。 |
INTERNAL | UPLOAD.INTERNAL.DISPOSED | インスタンスは破棄されています。 |
INTERNAL | UPLOAD.INTERNAL.INVALID_CONFIG | 設定が無効です。 |
パブリックプロパティ:
NSString *errorCode— エラーコードNSString *errorMessage— エラーメッセージNSError *cause— 基になる OSS の例外NSString *uploadTaskId— アップロードタスク IDNSString *suggestion— SDK 組み込みの修正案
if ([error.errorCode hasPrefix:@"UPLOAD.AUTH."]) {
// ユーザーにバックエンドの認証を確認するよう促します
} else if ([error.errorCode isEqualToString:@"UPLOAD.OSS.UPLOAD_FAILED"]) {
// リトライするか、ユーザーにネットワークを確認するよう促します
}
NSLog(@"%@ : %@ (cause=%@, suggestion=%@)",
error.errorCode, error.errorMessage, error.cause, error.suggestion);よくある質問
複数の uploadFile 呼び出しを同時に開始できますか?
はい。各 task は独立しています。parallel との組み合わせによる過度なアップストリーム帯域幅への圧迫を避けるため、ネットワーク状況に応じて同時アップロード数を制御してください。
キャンセル後に再アップロードするとレジュームアップロードが機能しない
次の手順で問題を切り分けてください:
ファイルパスが同一かどうかを確認してください。
ファイルの lastModified またはサイズが変更されていないかを確認してください。
config.checkpointがYESに設定されているかどうかを確認してください。uploadIdが期限切れかどうかを確認します。NoSuchUploadレスポンスを受信すると、SDK は自動的に新規アップロードにフォールバックします。これは想定される動作です。
App Store Connect の審査で "missing privacy manifest" を理由にリジェクトされる
SDK には、Pod の統合時に自動的に組み込まれる PrivacyInfo.xcprivacy ファイルが含まれています。お使いのアプリで使用する Required Reason API も宣言されていることを確認してください。
uploader を作成した後にコールバックがトリガーされない
uploader がローカル変数ではないことを確認してください。 VODUploadV2Client インスタンスは self のプロパティとして保持する必要があります。 そうしないと、ARC によって早期に解放されてしまいます。