Le SDK de chargement ApsaraVideo VOD pour iOS permet à votre application de charger directement des fichiers vidéo et image vers le stockage VOD. Votre application obtient les identifiants de chargement auprès d'un service d'autorisation backend, et le SDK utilise ces identifiants pour charger les fichiers vers OSS sans faire transiter les médias par votre serveur.
Fonctionnement
Le processus de chargement implique trois parties : votre application iOS, votre service backend et ApsaraVideo VOD (qui stocke les fichiers dans OSS). Le flux de travail est le suivant :
Votre application appelle le SDK pour démarrer un chargement. Le SDK déclenche le rappel
getAuth.Dans le rappel, votre application demande les identifiants de chargement à votre service backend, qui appelle une opération OpenAPI VOD (telle que
CreateUploadVideo) et renvoie la réponse.Votre application transmet la réponse OpenAPI au SDK. Le SDK extrait
UploadAuthetUploadAddressde la réponse et charge le fichier directement vers OSS.Si les identifiants expirent pendant un chargement volumineux, le SDK déclenche à nouveau le rappel
getAuthavec un type d'actualisation pour obtenir de nouveaux identifiants.
Prérequis
Démarrage rapide d'ApsaraVideo VOD
|
Élément |
Exigence |
|
Version minimale d'iOS |
iOS 12.0 |
|
Langage de développement |
Objective-C (les projets Swift utilisent un Bridging Header pour la liaison) |
|
Compte Alibaba Cloud |
ApsaraVideo VOD est activé |
|
Service d'autorisation |
Un service backend capable d'émettre des identifiants de chargement (UploadAuth) est préparé |
Intégrer le SDK
Méthode d'intégration
Méthode 1 : Intégration via Pod
Ajoutez le contenu suivant à votre Podfile :
platform :ios, '12.0'
target 'YourApp' do
pod 'VODUpload', '~> 2.0'
end
Exécutez les commandes suivantes :
pod repo update
pod install
Le SDK récupère automatiquement la dépendance sous-jacente AliyunOSSiOS.
Méthode 2 : Intégration via Swift Package Manager (SPM)
Dans le menu Xcode, sélectionnez File → Add Package Dependencies, puis saisissez l'adresse du dépôt : https://github.com/aliyunvideo/VODUpload.git.
Sélectionnez Up to Next Major Version pour la règle de version et indiquez 2.0.1 comme version initiale.
Ajoutez le produit VODUpload à votre cible App.
Ou déclarez-le dans Package.swift :
1.package(url: "https://github.com/aliyunvideo/VODUpload.git", from: "2.0.1")
Les dépendances OSS sous-jacentes sont analysées automatiquement avec le package principal. Vous n'avez pas besoin de les ajouter ou de les configurer manuellement. Une fois l'intégration terminée, l'instruction import VODUpload suffit. L'utilisation de l'API est identique à celle de l'intégration CocoaPods.
Configuration du projet
Le podspec déclare les bibliothèques système suivantes, qui sont automatiquement liées lorsque vous utilisez CocoaPods pour l'intégration :
SystemConfiguration.framework
MobileCoreServices.framework
CoreMedia.framework
AVFoundation.framework
CoreTelephony.framework
libresolv.tbd
Le SDK inclut un manifeste de confidentialité PrivacyInfo.xcprivacy qui est automatiquement injecté dans VODUpload.bundle/PrivacyInfo.xcprivacy lors de l'intégration via pod. Aucune configuration supplémentaire n'est requise.
Importez les fichiers d'en-tête requis :
#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>
Flux de chargement
Initialiser une instance de chargement
VODUploadConfig utilise des propriétés pour la configuration directe. Appelez la méthode factory +uploaderWithConfig: pour créer une instance :
VODUploadConfig *config = [[VODUploadConfig alloc] init];
config.getAuth = getAuth; // Required: authorization callback. For more information, see "Handle authorization callbacks".
VODUploadV2Client *uploader = [VODUploadV2Client uploaderWithConfig:config];
L'instance uploader doit être conservée en tant que propriété. S'il s'agit d'une variable locale, ARC la libère, ce qui entraîne la perte des rappels. Vous pouvez réutiliser la même instance pour charger plusieurs fichiers simultanément. Appelez [uploader dispose] pour libérer les ressources à la fin du cycle de vie.
Charger des fichiers
Appelez uploadFile:options:callback: pour démarrer un chargement. La méthode renvoie un handle VODUploadTask que vous pouvez utiliser pour annuler l'opération :
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);
}];
// Cancel during upload. Resumable upload is enabled by default. The next uploadFile call with the same file automatically resumes the upload.
[task cancel];
// task.uploadTaskId can be used to correlate logs and integrate with tracking.
Chargement d'image : Le SDK utilise automatiquement le processus de chargement d'image en fonction de l'extension du fichier (jpg / jpeg / png / gif / bmp / webp / heic) ou si options.imageMeta != nil est explicitement défini. Dans le rappel de succès, imageId et imageUrl contiennent des valeurs :
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];
Le champ description de VODVideoMeta est desc (et non description, afin d'éviter les conflits avec la méthode réservée Objective-C).
Gérer les rappels d'autorisation
Dans la version 2, le bloc VODGetAuthCallback demande les identifiants de chargement à votre application. Le SDK appelle getAuth à des moments précis et utilise VODAuthContext.kind pour indiquer le type d'identifiant requis :
|
Kind |
Déclencheur |
OpenAPI à appeler |
|
VODAuthKindCreateVideo |
Premier chargement d'un fichier vidéo |
|
|
VODAuthKindRefreshVideo |
Chargement reprenable / actualisation des identifiants |
|
|
VODAuthKindCreateImage |
Chargement d'image |
Votre application transmet la réponse JSON brute de l'appel OpenAPI backend directement à completion. Le SDK lit les clés suivantes de la réponse OpenAPI par nom de champ (sensible à la casse) :
|
Kind |
Champs requis |
|
VODAuthKindCreateVideo / VODAuthKindRefreshVideo |
UploadAuth, UploadAddress, VideoId |
|
VODAuthKindCreateImage |
UploadAuth, UploadAddress, ImageId, ImageURL (transmis à result.imageUrl) |
Les noms de champs sont sensibles à la casse. Transmettez la réponse OpenAPI telle quelle. Renommer manuellement les champs en videoId, imageUrl ou image_url entraîne leur interprétation comme nil par le SDK.
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;
}
};
Paramètres avancés
Accélération du chargement
Définissez VODVideoMeta.userData sur le JSON suivant. Le serveur VOD renvoie automatiquement l'endpoint d'accélération de transfert global OSS (oss-accelerate.aliyuncs.com) lors de l'émission de UploadAddress. Le SDK charge ensuite directement vers l'endpoint d'accélération :
VODVideoMeta *meta = [[VODVideoMeta alloc] init];
meta.title = @"My Video";
meta.userData = @"{\"Type\":\"oss\",\"Domain\":\"oss-accelerate.aliyuncs.com\"}";
L'accélération du chargement repose sur l'accélération de transfert global OSS. Vous devez activer l'accélération de transfert pour le bucket dans la console OSS. Pour plus d'informations, consultez Accéder à OSS à l'aide de l'accélération de transfert.
Chargement et transcodage
Spécifiez un groupe de modèles de transcodage ou un workflow en utilisant VODVideoMeta :
VODVideoMeta *meta = [[VODVideoMeta alloc] init];
meta.title = @"My Video";
meta.desc = @"Video description"; // Note: use desc, not description
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>"; // Transcoding template group
meta.workflowId = @"<Your workflow ID>"; // Workflow (optional)
meta.appId = @"<Optional: application ID>";
Champs pris en charge de VODVideoMeta : title, desc, coverUrl, cateId, tags, userData, storageLocation, templateGroupId, workflowId et appId. Tous les champs sont facultatifs et sont transmis à CreateUploadVideo.
Une fois le chargement terminé, le serveur VOD transcode la vidéo source en fonction du groupe de modèles. Si vous ne souhaitez pas déclencher le transcodage, transmettez un groupe de modèles « sans transcodage » lors de l'appel à CreateUploadVideo depuis votre backend.
Délai d'attente et nouvelle tentative
VODUploadConfig *config = [[VODUploadConfig alloc] init];
config.getAuth = getAuth;
config.timeout = 60; // Unit: seconds. Default value: 60
config.maxRetryCount = 2; // Default value: 2
timeout contrôle le délai d'attente de connexion et de lecture/écriture (NSTimeInterval, en secondes) pour une seule requête OSS. maxRetryCount contrôle le nombre de nouvelles tentatives pour les requêtes OSS en cas d'erreurs réseau.
L'unité de timeout est la milliseconde sur Android et la seconde sur iOS. Tenez compte de cette différence lors de l'intégration multiplateforme.
Version de signature
config.signature = @"v4"; // Default value: @"v4". Valid values: @"v1"
La signature OSS V4 est la version recommandée. À partir du 1er septembre 2025, la signature V4 est obligatoire pour les buckets nouvellement créés. Il est également recommandé aux clients existants de migrer dès que possible. Définissez explicitement @"v1" uniquement lorsque le bucket utilisé par votre application ne prend en charge que les signatures V1.
Chargement reprenable
Le chargement reprenable est activé par défaut. Le SDK utilise le triplet (lastModified, fileName, fileSize) comme clé de chargement reprenable et le persiste automatiquement dans le répertoire Caches local :
|
Scénario |
Comportement du SDK |
|
|
L'enregistrement de chargement reprenable est conservé. Le prochain appel |
|
L'application plante ou est arrêtée en arrière-plan |
L'enregistrement de chargement reprenable est conservé. Le prochain appel |
|
Toute modification de l'empreinte du fichier |
Le fichier est traité comme un nouveau fichier et chargé depuis le début. |
|
L'uploadId OSS expire |
Le SDK efface automatiquement l'ancien enregistrement et démarre un nouveau chargement via VODAuthKindCreateVideo. |
Pour désactiver le chargement reprenable :
config.checkpoint = NO;
Chargement multipartie
Utilisez partSize pour contrôler la taille des parties et parallel pour contrôler le nombre de parties concurrentes :
// Global configuration
config.partSize = 1024 * 1024; // Default value: 1 MB
config.parallel = 4; // Default value: 4
// Per-task override
VODUploadOptions *options = [[VODUploadOptions alloc] init];
options.videoMeta = meta;
options.partSize = 2 * 1024 * 1024;
options.parallel = 6;
Définir la région du service VOD
config.region = @"cn-shanghai"; // Default value: cn-shanghai
Pour la liste des régions prises en charge, consultez ID de région ApsaraVideo VOD.
Rapport de données
Le SDK active le suivi des liens de chargement par défaut pour la surveillance de la qualité du produit. Seules les métriques d'exécution du processus de chargement sont collectées ; le contenu des fichiers n'est pas inclus. Pour désactiver le rapport de données :
config.reportEnabled = NO; // Default value: YES
Gestion des erreurs
VODUploadError hérite de NSError. Les codes d'erreur utilisent le format à trois segments UPLOAD.{LAYER}.{TYPE} :
|
LAYER |
Code d'erreur |
Description |
|
AUTH |
UPLOAD.AUTH.GET_AUTH_FAILED |
Échec du rappel getAuth. |
|
AUTH |
UPLOAD.AUTH.DECODE_FAILED |
Échec du décodage de UploadAuth. |
|
AUTH |
UPLOAD.AUTH.EXPIRED |
L'identifiant a expiré. |
|
OSS |
UPLOAD.OSS.ACCESS_DENIED |
Accès OSS refusé (problème d'autorisation/de signature). |
|
OSS |
UPLOAD.OSS.NO_SUCH_BUCKET |
Le bucket n'existe pas. |
|
OSS |
UPLOAD.OSS.NO_SUCH_UPLOAD |
L'uploadId a expiré. Le SDK effectue automatiquement un basculement. |
|
OSS |
UPLOAD.OSS.UPLOAD_FAILED |
Échec du chargement OSS. |
|
OSS |
UPLOAD.OSS.MERGE_FAILED |
Échec de la fusion multipartie OSS. |
|
NETWORK |
UPLOAD.NETWORK.TIMEOUT |
Délai d'attente réseau. |
|
NETWORK |
UPLOAD.NETWORK.UNREACHABLE |
Réseau inaccessible. |
|
FILE |
UPLOAD.FILE.NOT_FOUND |
Le fichier n'existe pas. |
|
FILE |
UPLOAD.FILE.EMPTY |
Le fichier est vide. |
|
CANCEL |
UPLOAD.CANCEL.USER_CANCELLED |
L'utilisateur a annulé le chargement. |
|
INTERNAL |
UPLOAD.INTERNAL.DISPOSED |
L'instance a été libérée. |
|
INTERNAL |
UPLOAD.INTERNAL.INVALID_CONFIG |
La configuration n'est pas valide. |
Propriétés publiques :
NSString *errorCode— Code d'erreurNSString *errorMessage— Message d'erreurNSError *cause— Exception OSS sous-jacenteNSString *uploadTaskId— ID de tâche de chargementNSString *suggestion— Suggestion de correction intégrée du SDK
if ([error.errorCode hasPrefix:@"UPLOAD.AUTH."]) {
// Prompt the user to check the backend authorization
} else if ([error.errorCode isEqualToString:VODErrorCodeOssUploadFailed]) {
// Retry or prompt the user to check the network
}
NSLog(@"%@ : %@ (cause=%@, suggestion=%@)",
error.errorCode, error.errorMessage, error.cause, error.suggestion);
FAQ
Puis-je lancer plusieurs appels uploadFile simultanément ?
Oui. Chaque task est indépendante. Contrôlez le nombre de chargements simultanés en fonction des conditions réseau pour éviter une pression excessive sur la bande passante ascendante due à la combinaison avec parallel.
Le chargement reprenable ne fonctionne pas après annulation et rechargement
Résolvez le problème en effectuant les étapes suivantes :
Vérifiez si le chemin du fichier est identique.
Vérifiez si lastModified ou la taille du fichier a changé.
Vérifiez si
config.checkpointest défini surYES.Vérifiez si l'uploadId a expiré. Lorsque la réponse
NoSuchUploadest reçue, le SDK revient automatiquement à un nouveau chargement. Il s'agit d'un comportement attendu.
Rejet de l'examen App Store Connect avec « missing privacy manifest »
Le SDK inclut un fichier PrivacyInfo.xcprivacy qui est automatiquement injecté lors de l'intégration via pod. Assurez-vous que votre application déclare également l'API Required Reason qu'elle utilise.
Les rappels ne sont pas déclenchés après la création de l'uploader
Assurez-vous que uploader n'est pas une variable locale. L'instance VODUploadV2Client doit être conservée en tant que propriété de self. Sinon, ARC la libère prématurément.