ショートビデオSDKは、ビデオ編集機能を提供します。 ビデオ、画像、マテリアルをインポートし、フィルター、ダブ、タイムエフェクト、ピクチャーインピクチャー (PiP) エフェクトなどのエフェクトをビデオに追加できます。 このトピックでは、iOS用のショートビデオSDKを使用してビデオを編集する方法について説明します。

サポートされているエディション

エディション 説明
Professional すべての機能がサポートされています。
標準モード 字幕、アニメーションステッカー、ミュージックビデオ (MV) を除く機能がサポートされています。
基本 サポートされません。

関連クラス

機能 分類 説明
初期化 AliyunEditor ビデオ編集を定義するコアクラス。
編集 AliyunIClipConstructor ビデオソースを管理するために使用されるクラス。
AliyunClip メディアクリップを定義するクラス。
AEPVideoTrack プロジェクト構成のメインストリームのトラックを定義するクラス。
AEPVideoTrackClip プロジェクト構成のメインストリームのクリップを定義するクラス。
プレビュー制御 AliyunIPlayer 再生プロトコルを定義するクラス。
AliyunIPlayerCallback 再生ステータスコールバックプロトコルを定義するクラス。
ビデオ効果の設定 AliyunEffectFilter フィルターのモデルを定義するクラス。
AliyunEffectTimeFilter 時間効果のモデルを定義するクラス。
AliyunTransitionEffect トランジションを定義する基本クラス。
AliyunEffectMV MVのモデルを定義するクラス。
AliyunFilterManager ルックアップテーブル (LUT) フィルタと静的フィルタを管理するために使用できるフィルタマネージャを定義するクラス。
AliyunLutFilterController LUTフィルタコントローラを定義するクラス。
AliyunLutFilter LUTフィルタのモデルを定義するクラス。
AliyunShaderFilterController 静的フィルターコントローラーを定義するクラス。
AliyunShaderFilter 静的フィルターのモデルを定義するクラス。
音楽と効果音の設定 AliyunEffectMusic 音楽を定義するクラス。
AliyunEffectDub ダブを定義するクラス。
AEPAudioTrack プロジェクト構成でオーディオトラックを定義するクラス。
AEPAudioTrackClip プロジェクト構成でオーディオトラッククリップを定義するクラス。
PiPの設定 AliyunPipManager PiPマネージャを定義するクラス。
AliyunPipTrackController PiPトラックコントローラを定義するクラス。
AliyunPipClipController PiPクリップコントローラを定義するクラス。
AliyunPipClip PiPデータモデルを定義するクラス。
AEPPipVideoTrackClip プロジェクト構成でPiPクリップを定義するクラス。
AEPPipVideoTrack プロジェクト構成でPiPトラックを定義するクラス。
AliyunClipAugmentationInfo SEI (image supplemental enhancement information) を定義するクラス。
AliyunClipAudioInfo オーディオ情報を定義するクラス。
AliyunPureColorBorderInfo ボーダー情報を定義するクラス。
字幕とステッカーの設定 AliyunStickerManager ステッカーと字幕マネージャーを定義するクラス。
AliyunCaptionStickerController 字幕コントローラを定義するクラス。
AliyunGifStickerController アニメーションGIFコントローラーを定義するクラス。
AliyunImageStickerController 静的イメージコントローラを定義するクラス。
AliyunCaptionSticker 字幕データモデルを定義するクラス。
AliyunGifSticker アニメーションGIFデータモデルを定義するクラス。
AliyunImageSticker 静的イメージデータモデルを定義するクラス。
AEPGifStickerTrack プロジェクト構成でアニメーションGIFトラックを定義するクラス。
AEPImageStickerTrack プロジェクト構成で静的イメージトラックを定義するクラス。
AEPCaptionTrack プロジェクト構成で字幕トラックを定義するクラス。
ドラフトボックス AliyunEditorProject プロジェクトの構成を定義するクラス。
AliyunDraft ドラフトオブジェクトを定義するクラス。
AliyunDraftManager ローカルドラフトマネージャーを定義するクラス。
AliyunDraftLoadTask ドラフトリソースの読み込みタスクを定義するクラス。
AliyunDraftProjectUploadTask ドラフトアップロードタスクを定義するクラス。
AEPSource リソースオブジェクトを定義するクラス。
AEPResourceModel ロードタスクで特定のリソースモデルを定義するクラス。
その他の設定 AliyunICanvasView doodleおよびcanvasビューを定義するクラス。
AliyunIPaint ペイントブラシを定義するクラス。

ビデオ编集プロセス

設定 手順 説明 サンプルコード
基本設定 1 エディターを作成して初期化します。 エディターの初期化Initialize an editor
2 ビデオをトリミングし、ビデオソースを動的に変更し、ビデオ編集中にトランジション時間とエフェクトを動的に変更します。 ビデオの管理
3 プレビューを設定します。 プレビューの設定
詳細構成 4 フィルター、トランジション、MVなどのエフェクトを設定します。 ビデオエフェクトの設定
5 BGM、ダブ、サウンドエフェクトを設定します。 音楽と効果音を設定する
6 PiPを設定します。 PiPの設定
7 字幕、ワードアート、バブル、ステッカーを設定します。 字幕とアニメーションステッカーを設定する
8 ドラフトボックスに保存されているビデオを編集するか、編集したビデオをドラフトボックスに保存します。 ドラフトボックス
9 doodlesを設定します。 その他の設定

エディターの初期化Initialize an editor

エディターを作成して初期化します。 コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。

// 1. タスクパス: 編集するメディアファイルごとにタスクが生成されます。 編集初期化時にタスクパスを指定する必要があります。 最初にタスクを初期化する必要があります。
NSString * taskPath = @ "xxx"; // taskPathは、インポートするビデオのURLです。 ほとんどの場合、ビデオはローカルソースまたはドラフトボックスからインポートされます。

// 2. プレビュービュー: プレビュービューを設定すると、編集中に各操作がプレビュービューにリアルタイムで反映されます。
UIView * preview = xxx;

// 3。 エディタをインスタンス化します。
AliyunEditor * editor = [[AliyunEditor alloc] initWithPath:taskPathプレビュー: プレビュー];
            
プレビュービューに表示される内容が出力ビデオに表示される内容と一致するように、プレビュービューのアスペクト比を出力ビデオのアスペクト比と同じに設定することをお勧めします。

ビデオの管理

AliyunIClipConstructorクラスを使用して、ビデオエディターでビデオまたは画像を管理できます。 AliyunIClipConstructorを呼び出してエディターでビデオまたは画像を変更した後、次回エディターを使用するときに [editor startEdit] を呼び出して変更を有効にする必要があります。

コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。

// 1. ビデオソースマネージャーを取得します。
id<AliyunIClipConstructor> contructor = [editor getClipConstructor];

// 2。 ビデオクリップを追加します。
// 2.1編集を停止します。
[エディタstopEdit];
// 2.2ビデオクリップを作成します。
AliyunClip * clip = [[AliyunClip alloc] initWithVideoPath:videoPath startTime:2 duration:6 animDuration:0];
// 2.3.1ビデオクリップを最後に追加します。
[contructor addMediaClip: クリップ];
// 2.3.2または、ビデオクリップを指定した位置に追加します。
[contructor addMediaClip:clip atIndex:1];
// 2.4編集を開始します。
[エディタstartEdit];

// 3。 ビデオクリップを更新または置き換えます。
[contructor updateMediaClip: クリップatIndex:1];

// 4。 ビデオクリップを削除します。
// 4.1最後のビデオクリップを削除します。
[contructor deleteLastMediaClip];
// 4.2指定したビデオクリップを削除します。
[contructor deleteMediaClipAtIndex:1];
// 4.3すべてのビデオクリップを削除します。
[contructor deleteAllMediaClips];

// 5。 すべてのビデオクリップを取得します。
NSArray<AliyunClip *> * mediaClips = contructor.mediaClips;

プレビューの設定

ビデオ編集中に、ビデオに対してさまざまな操作を実行できます。 たとえば、ビデオを再生したり、ビデオを一時停止したり、再生タイムラインの期間を取得したりできます。 コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。

再生コントロール

// プレビュープレーヤーを取得します。
id<AliyunIPlayer> player = [editor getPlayer];

// 再生を開始します。    
[プレイヤープレイ];

// 再生を再開します。
[プレイヤーの履歴書];

// 再生を一時停止します。
[プレイヤーの一時停止];

// 指定した位置にスキップします。
[プレイヤーシーク: timeInSecond];

// ビデオをミュートします。
[エディタsetMute:YES];

// ボリュームを設定します。
[editor setVolume:50];

// 時間効果の影響を受けないストリームの現在位置を取得します。
double currentTime = [player getCurrentStreamTime];

// タイムエフェクトの影響を受けない再生タイムライン上の現在の位置を取得します。
double currentTime = [player getCurrentTime];

// 時間効果の影響を受けないストリームの継続時間を取得します。
double duration = [player getStreamDuration];

// タイムエフェクトの影響を受ける再生時間の合計を取得します。
double duration = [player getDuration];

再生コールバック

// 再生ステータスをリッスンします。
editor.playerCallback = self;

// プロトコル。
- (void)playerDidEnd {
    // 再生終了時に返されるコールバック。
}

- (void)playProgress :( double)playSec streamProgress :( double)streamSec {
    // 再生の進行状況のコールバック。
}

- (void)playError :( int)errorCode {
    // 再生中にエラーが発生したときに返されるコールバック。
}
            

ビデオエフェクトの設定

フィルター、トランジション、MV、タイムエフェクトなどのビデオエフェクトを設定できます。 コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。

フィルター
  • フィルタには、LUTフィルタ、静的フィルタ、およびアニメーションフィルタが含まれる。
    • LUTフィルター: Lookup Tableを使用してピクセルを置き換えます。
    • 静的フィルター: シェーディング言語で記述してピクセルを計算します。 アニメーション効果はサポートされていません。
    • アニメーションフィルター: シェーディング言語で記述してピクセルを計算します。 アニメーション効果が使用されます。
  • カスタムフィルターを作成できます。 詳細については、「フィルターとトランジション」をご参照ください。
LUTフィルター
// 1. LUTフィルターを追加します。
AliyunLutFilterController * controller = [[エディターgetFilterManager] applyLutFilterWithPath: パス強度: 強度];
if (! コントローラ) {
    // LUTフィルターの追加に失敗しました。
}

// 2。 強度を更新します。
controller.model.int ensity = 0.5;

// 3。 LUTフィルターを削除します。
[[エディタgetFilterManager] removeFilter:controller];
静的フィルター
// 1. 静的フィルターを追加します。
AliyunShaderFilterController * controller = [[editor getFilterManager] applyShadeFilterWithPath:path];
if (! コントローラ) {
    // 静的フィルターの追加に失敗しました。
}

// 2。 静的フィルターを削除します。
[[エディタgetFilterManager] removeFilter:controller];
アニメーションフィルター
// 1. アニメーションフィルターを追加します。
AliyunEffectFilter * animationFilter = [[AliyunEffectFilter alloc] initWithFile:filterFolder];
animationFilter.startTime = 2;
animationFilter.endTime = 10;
//... その他のパラメーターについては、APIのドキュメントを参照してください。
[エディターapplyAnimationFilter:animationFilter];

// 2。 アニメーションフィルターを変更します。
animationFilter.startTime = 4;
animationFilter.endTime = 12;
//... その他のパラメーターについては、APIのドキュメントを参照してください。
[エディターupdateAnimationFilter:animationFilter];

// 3。 アニメーションフィルターを削除します。
[エディターremoveAnimationFilter:animationFilter];
遷移
  • カスタム遷移を作成できます。 詳細については、「フィルターとトランジション」をご参照ください。
  • ショートビデオSDKは、AliyunTransitionEffectTypeCircle (円) 、AliyunTransitionEffectTypeFade (フェードインおよびフェードアウト) 、AliyunTransitionEffectTypePolygon (ポリゴン) 、AliyunTransitionEffectTypeShuffer (ブラインド) 、およびAliyunTransitionEffectTypeTranslate (translate) を提供します。 AliyunTransitionEffectType

トランジションの位置

トランジションは、2つのビデオクリップ間でのみ適用できます。 ビデオクリップが1つしかない場合、トランジションはサポートされません。 遷移は0秒の位置から始まる。 次の例を参照してください。

[---- ビデオクリップA ----] [---- ビデオクリップB ----] [---- ビデオクリップC ----]...[---- ビデオクリップN -----]
                ^                ^                 ^
 位置: 0 1 N-1->

トランジションの設定

// トランジションを追加します。
// 注: 次の操作を呼び出す前に、まず [editor stopEdit] を呼び出す必要があります。 次の操作を呼び出した後、[editor startEdit] を呼び出します。 
AliyunTransitionEffect * transition = [[AliyunTransitionEffect alloc] initWithPath:transitionFolder];
[エディターapplyTransition:transition atIndex:0];

// トランジションを更新します。
// 注: トランジションの期間は、トランジションの前後のビデオの期間より長くすることはできません。
transition.overlapDuration = 1;
//... その他のパラメーターについては、APIのドキュメントを参照してください。
[エディターupdateTransition:transition atIndex:0];

// トランジションを削除します。
[エディターremoveTransitionAtIndex:0];

MV

カスタムMVを作成できます。 詳細については、「MV」をご参照ください。

// MVを追加します。
AliyunEffectMV * mv = [[AliyunEffectMV alloc] initWithFile:mvFolder];
[エディターapplyMV:mv];

// MVをミュートします。
[エディターremoveMVMusic];

// MVを削除します。
[エディターremoveMV];

タイムエフェクト

ショートビデオSDKは、TimeFilterTypeSpeed (スピードランピング) 、TimeFilterTypeRepeat (ループ) 、およびTimeFilterTypeInvert (逆再生) のタイムエフェクトを提供します。 TimeFilterType

ビデオの逆再生を設定する場合、ビデオのGOP (group of pictures) サイズが35より大きい場合、逆再生効果を使用する前にビデオをトランスコードする必要があります。 AliyunNativeParserを呼び出して、GOPサイズを取得できます。 ビデオクロッピング機能を使用して、ビデオをトランスコードできます。
// 1. タイムエフェクトを追加します。
// 1.1速度ランピングを設定します。
AliyunEffectTimeFilter * timeFilter = [[AliyunEffectTimeFilter alloc] init];
timeFilter.type = TimeFilterTypeSpeed;
timeFilter.param = 0.67;
timeFilter.startTime = 2;
timeFilter.endTime = 10;
//... その他のパラメーターについては、APIのドキュメントを参照してください。
[エディターapplyTimeFilter:timeFilter];

// 1.2ループを設定します。
AliyunEffectTimeFilter * timeFilter = [[AliyunEffectTimeFilter alloc] init];
timeFilter.type = TimeFilterTypeRepeat;
timeFilter.param = 3; // たとえば、ビデオを3回ループするように設定します。
timeFilter.startTime = 2;
timeFilter.endTime = 10;
//... その他のパラメーターについては、APIのドキュメントを参照してください。
[エディターapplyTimeFilter:timeFilter];

// 1.3逆再生を設定します。
AliyunEffectTimeFilter * timeFilter = [[AliyunEffectTimeFilter alloc] init];
timeFilter.type = TimeFilterTypeInvert;
//... その他のパラメーターについては、APIのドキュメントを参照してください。
[エディターapplyTimeFilter:timeFilter];


// 2。 タイムエフェクトを削除します。
[エディターremoveTimeFilter:timeFilter];

音楽と効果音を設定する

音楽やダブを追加したり、フェードイン、フェードアウト、音声の変更などのサウンドエフェクトをオーディオに追加したりできます。 コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。

音楽

音楽には、バックグラウンドミュージックとダブが含まれます。 バックグラウンドミュージックは、速度ランピング、ループ、および逆再生などの時間効果の影響を受けません。 ダブは時間の影響を受けます。

バックグラウンドミュージック
// 1. バックグラウンドミュージックを追加します。
AliyunEffectMusic * music =[[AliyunEffectMusic alloc] initWithFile:musicFilePath];
music.duration = 3;
music.audioMixWeight = 50; // バックグラウンドミュージックの重み付け音量を示します。
// ... その他のパラメーターについては、APIのドキュメントを参照してください。
[エディターapplyMusic:music];

// 2。 バックグラウンドミュージックを削除します。
[エディターremoveMusic: 音楽];
ダブ
// 1. ダブを追加します。
AliyunEffectDub * dub =[[AliyunEffectDub alloc] initWithFile:dubFilePath];
dub.startTime = 2;
dub.audioMixWeight = 50; // ダブの重み付き音量を示します。
dub.audioDenoiseWeight = 50; // ノイズ低減の程度を示します。
// ... その他のパラメーターについては、APIのドキュメントを参照してください。
[エディターapplyDub:dub];

// 2。 ダブを削除します。
[エディターremoveDub:dub];
サウンドエフェクト
  • フェードインとフェードアウト: AliyunAudioFadeShapeLinear (線形曲線) とAliyunAudioFadeShapeSin (正弦曲線) がサポートされています。 AliyunAudioFadeShape
  • 次の音声変更効果がサポートされています。 AliyunAudioEffectType
    • AliyunAudioEffectLolita (活発な女性の声)
    • AliyunAudioEffectUncle (ハスキー男性の声)
    • AliyunAudioEffectReverb (残響)
    • AliyunAudioEffectEcho (エコー)
    • AliyunAudioEffectRobot (ロボット音声)
    • AliyunAudioEffectBigDevil (不吉な声)
    • AliyunAudioEffectMinions (minion voice)
    • AliyunAudioEffectDialect (方言)
フェードインとフェードアウト
// 1. オーディオを追加する前にフェードイン効果を設定します。 フェードアウト効果を設定する操作も同様ですが、fadeInパラメーターがfadeOutパラメーターに置き換えられています。
AliyunAudioFade * fadeIn = [[AliyunAudioFade alloc] init];
fadeIn.shape = AliyunAudioFadeShapeLinear;
fadeIn.duration = 2;
music.fadeIn = fadeIn; // ダブを設定する手順は似ています。

// 2. オーディオを追加した後、フェードイン効果を変更します。 フェードアウト効果を変更する操作は同様であり、機能はsetAudioFadeOutShape: 、duration: 、streamId: に変更されています。
[エディタsetAudioFadeInShape:AliyunAudioFadeShapeLinear期間: 2 streamId:music.effectVid];

// 3。 オーディオを追加した後、フェードイン効果を削除します。 フェードアウト効果を除去する操作は同様であり、関数がremoveAudioFadeOutWithStreamId: に変更されている。
[editor removeAudioFadeInWithStreamId:music.effectVid]; // ダブを削除する手順は似ています。
音声変更
// 1. オーディオを追加する前に音声変更を設定します。
AliyunAudioEffect * audioEffect = [[AliyunAudioEffect alloc] init];
audioEffect.type = AliyunAudioEffectLolita;
audioEffect.weight = 50;
[dub.audioEffects addObject:audioEffect]; // 注: 1つの音声変更エフェクトのみを設定できます。

// 2. オーディオを追加した後に音声変更を設定します。
[エディタsetAudioEffect:AliyunAudioEffectLolita重み: 50 streamId:dub.effectVid];

// 3。 オーディオを追加した後、音声変更効果を削除します。
[エディターremoveAudioEffect:AliyunAudioEffectLolita streamId:dub.effectVid];

PiPの設定

PiP機能を使用すると、既存のメイントラックに1つ以上のPiPエフェクトを追加できます。
  • メイントラック: 編集ページのデフォルトトラック。 1つのメイントラックのみが許可されます。 メイントラックは、複数のビデオストリームを含むことができる。
  • PiP: 複数のPiPエフェクトを追加し、位置、スケーリング、回転などのPiPエフェクトの設定を行うことができます。 デフォルトでは、PiPエフェクトを作成すると、PiPトラックが自動的に作成されます。 PiP効果は、異なるPiPトラック間で移動することができる。

コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。

// PiPマネージャを取得します。 PiPマネージャを使用して、PiPエフェクトを追加、削除、変更、およびチェックできます。
AliyunPipManager * pipManager = [エディターgetPipManager];


// PiP効果を追加します。
// 1. 最上位レイヤーにPiPトラックを追加し、そのトラックにPiPクリップを追加します。
// 1.1ビデオクリップを追加します。
NSError * error = nil;
AliyunPipClipController * pipClipController = [pipManager addClipWithType:AliyunPipClipTypeVideoパス: xxVideoPathエラー:&エラー];
// 1.2イメージを追加します。
NSError * error = nil;
AliyunPipClipController * pipClipController = [pipManager addClipWithType:AliyunPipClipTypeImageパス: xxImagePathエラー:&エラー];

// 2。 指定したPiPトラックにPiPクリップを挿入します。
// PiPクリップを作成する2.1。
AliyunPipClip * pipClip = [[AliyunPipClip alloc] initWithClipType:AliyunPipClipTypeVideo clipPath:xxxVideoPath];
//... PiPのその他のパラメーター設定については、「https://alivc-demo-cms.alicdn.com/versionProduct/doc/shortVideo/iOS_cn/Classes/AliyunPipClip.html」をご参照ください。// 指定したトラックにPiPクリップを挿入する2.2。
NSError * error = nil;
AliyunPipClipController * pipClipController = [pipManager addClipWithModel:pipClip toTrack:pipManager.trackControllers.firstObjectエラー:&error]; // たとえば、最初のトラックにPiPクリップを追加します。


// PiP効果を削除します。
NSError * error = nil;
[pipManager removePipClipController:pipClipControllerエラー:&エラー];


// PIPトラックを切り替えます。
[pipManager movePipClipController:pipController toTrack:pipManager.trackControllers.firstObject withStartTime:0]; // たとえば、PiPクリップを最初のトラックの開始位置に移動します。


// PiPクリップを変更します。
// たとえば、PiPクリップの位置を変更します。
pipController.clip.center = CGPointMake(100、100);

// たとえば、PiPクリップの位置、サイズ、回転を変更します。
[pipController begin Edit];
pipController.clip.center = CGPointMake(100、100);
pipController.clip.scale = 0.7;
pipController.clip.rotation = M_PI_2;
[pipController endEdit];

// テストを実行します。
// たとえば、現在の時刻のタッチポイントの最上位レイヤーでPiPクリップを取得します。
double currentTime = [[エディターgetPlayer] getCurrentTime];
AliyunPipClipController * pipClipController = [pipManager hitTest:touchPoint withTime:currentTime];

字幕とアニメーションステッカーを設定する

  • AliyunStickerManagerを使用して、字幕とステッカーを管理できます。 さらに、AliyunCaptionStickerControllerAliyunStickerControllerを使用して、字幕とステッカーのステータスを管理できます。 字幕コントローラーとレンダリングコントローラーはどちらもAliyunRenderBaseControllerから派生しています。 したがって、字幕およびステッカーを修正するための論理は、基礎となる要素の属性を修正するための論理と同じである。
  • 短いビデオSDKを使用すると、ワードアートやバブルを字幕に適用できます。 カスタムのワードアート効果とバブルを作成できます。 詳細については、「ワードアートアニメーション」をご参照ください。
  • ステッカーには、静的ステッカーとアニメーションステッカーが含まれます。 アニメーションステッカーは泡に似ていますが、テキストはありません。 カスタムアニメーションステッカーを作成できます。 詳細については、「アニメーション」をご参照ください。
  • コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。
マネージャー
  • マネージャーを使用して、字幕とステッカーを追加、削除、変更、および確認できます。 AliyunStickerManager
  • 字幕とステッカーは、レンダリングモデルAliyunRenderModelから派生し、基になるレンダリング要素の属性を持ちます。 字幕またはステッカーコントローラーは、ある時点で一番上のレイヤーの字幕またはステッカーの座標をプレビューするためにクリックした位置にあります。
// マネージャーを取得します。
AliyunStickerManager * stickerManager = [エディターgetStickerManager];

// 字幕またはステッカーを追加します。
// たとえば、字幕を追加します。
AliyunCaptionStickerController * captionController = [stickerManager addCaptionText:@ "Hello" bubblePath:nil startTime:0 duration:5];

// 字幕またはステッカーを削除します。
[stickerManager削除: gifController];

// 字幕またはステッカーを見つけます。
// たとえば、現在の時刻のタッチポイントの最上位レイヤーで字幕またはステッカーを取得します。
double currentTime = [[エディターgetPlayer] getCurrentTime];
AliyunRenderBaseController * controller = [stickerManager findControllerAtPoint:touchPoint atTime:currentTime];
字幕
// 字幕を追加します。
AliyunCaptionStickerController * captionController = [stickerManager addCaptionText:@ "Hello" bubblePath:nil startTime:0 duration:5];

// 字幕を変更します。
[captionController begin Edit];
captionController.mo del.text = xxx;
captionController.mo del.outlineWidth = 3;
captionController.mo del.outlineColor = UIColor.redColor;
//... その他のパラメーターについては、APIドキュメントのAliyunCaptionStickerに関するページを参照してください。
[captionController endEdit];
ワードアート
// ワードアート効果を適用します。
captionController.mo del.fontEffectTemplatePath = fontEffectFolder; // ワードアートリソースパッケージフォルダを示します。
// ワードアート効果を削除します。
captionController.mo del.fontEffectTemplatePath = nil;
バブル
// バブルを適用します。
captionController.mo del.resourePath=bubbleEffectFolder; // バブルリソースパッケージフォルダーを示します。
// バブルを削除します。
captionController.mo del.resourePath = nil;
アニメーションステッカー
// アニメーションステッカーを追加します。
AliyunGifStickerController * gifController = [stickerManager addGif:gifFilePath startTime:0 duration:5];


// アニメーションステッカーを変更します。
[gifController begin Edit];
gifController.gif.center = xxx;
//... その他のパラメーターについては、APIドキュメントのAliyunGifStickerに関するページを参照してください。
[gifController endEdit];
静的ステッカー
// 静的ステッカーを追加します。
AliyunImageStickerController * imageController = [stickerManager addImage:imageFilePath startTime:0 duration:5];

// 静的ステッカーを変更します。
[imageController begin Edit];
imageController.image.center = xxx;
//... その他のパラメーターについては、APIドキュメントのAliyunImageStickerに関するページを参照してください。
[imageController endEdit];

ドラフトボックス

編集ごとに、編集タスクが生成され、プロジェクト構成の変更として記録されます。 編集結果をすぐにエクスポートしたくない場合は、編集をドラフトとして保存できます。 次回ドラフトをロードするときに、前の編集を復元して編集を続けることができます。 コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。

プロジェクト設定

編集はドラフトオブジェクトとして特徴付けられ、タイムライン構造で記述される。 各編集アクションは、プロジェクト構成の変更に反映されます。 プロジェクト構成を編集インターフェイスに関連付けることをお勧めします。 ドラフトを読み込むと、プロジェクト構成を使用して、対応する編集と一致する編集インターフェイスが復元されます。
// 編集中にプロジェクト構成を取得します。
AliyunEditorProject * project = [editor getEditorProject];

ドラフトオブジェクト

編集は、AliyunDraftという名前のドラフトオブジェクトとして保存できます。 次の方法を使用して編集を保存できます。

// 0。 編集をドラフトとして保存する前に、ドラフトを保存する場所を指定する必要があります。 ショートビデオSDKは、ドラフトコンテナとして使用できるドラフト管理オブジェクトを提供します。
AliyunDraftManager * draftManager; // ドラフト管理の詳細については、このトピックの次のセクションを参照してください。

// 1. ドラフトタイトルを指定して、ドラフトを保存します。 ドラフトの保存場所も指定する必要があります。 draftオブジェクトが返されます。
AliyunDraft * draft = [editor saveToDraft:draftManager withTitle:@ "あなたのドラフトタイトル"];

// 2.1ドラフトタイトルを指定しません。 この場合、最後のドラフトタイトルが使用されます。
AliyunDraft * draft = [editor saveToDraft:draftManager];

// 下書きオブジェクトを取得した後、下書きタイトルを2.2変更します。
[draft renameTitle:@ "あなたのドラフトタイトル"];
ドラフトをより適切に識別し、ユーザーがオンプレミスまたはクラウドドラフトビジネスを開発できるようにするために、短いビデオSDKはユーザーのIDを予約します。 次のAPIを呼び出して、ビジネスのIDを設定できます。
[ドラフトchangeProjectId:@ "カスタムプロジェクトid"];

下書きサムネイル

編集中に、サムネイルが自動的に生成される。 ほとんどの場合、ビデオの最初のフレームがサムネイルとして使用されます。 次のAPI操作を呼び出して、カスタムサムネイルを使用することもできます。

[エディターupdateCover:yourCoverImage];

// パラメータを空白のままにすると、デフォルトで生成されたサムネイルが使用されます。
[editor updateCover:nil];

下書きオブジェクトを取得した後、サムネイルを変更できます。

[draft updateCover:yourCoverImage];
カスタムサムネイルを使用する場合は、できるだけ早くカスタムサムネイルを設定することをお勧めします。 カスタムサムネイルがドラフトに使用されると、ドラフトはサムネイルを更新しなくなります。 これにより、編集効率を向上させることができます。

ドラフト管理

重要 ドラフト管理オブジェクトは、初期化中にすべての管理されたドラフトオブジェクトを解析します。 したがって、一定の性能損失が生じる。 オブジェクトを頻繁に作成および破棄するのではなく、ドラフト管理オブジェクトをグローバルオブジェクトとして使用することをお勧めします。
// ドラフト管理オブジェクトを初期化します。
// ユーザー間の分離を改善するために、ドラフト管理オブジェクトにIDを使用することをお勧めします。
NSString * draftManagerId;
// ドラフト管理オブジェクトをインスタンス化します。
AliyunDraftManager * draftManager = [[AliyunDraftManager alloc] initWithId:draftManagerId];


// ドラフトリストを管理します。

// ドラフトリストを取得します。
NSArray<AliyunDraft *> * draftList = draftManager.draftList;
// ドラフトリストの変更を聞くことができます。
draftManager.de legate = yourListener;
// ドラフトリストの変更をリッスンするには、AliyunDraftManagerDelegateプロトコルを実装します。
// - (void) onAliyunDraftManager :( AliyunDraftManager *)mgr listDidChange :( NSArray<AliyunDraft *> *) リスト;


// ドラフトを削除します。
[draftManager deleteDraft:targetDraft];


// 下書きをコピーします。
[draftManager copyDraft:fromDraft toPath:newDraftTaskPath withTitle:@ "あなたの新しいドラフトタイトル"];

ドラフトの読み込み

編集中に様々なリソースを使用することができる。 パフォーマンスを向上させ、ストレージ容量を節約するために、使用されるリソースはすべてタスクディレクトリにコピーされません。 編集をドラフトから復元する前に、いくつかのリソース読み込みタスクを処理して、編集用のすべてのリソースの準備ができていることを確認する必要があります。 次のタイプのリソースに特に注意することをお勧めします。
  • アルバム内のメディアリソース: 編集を開始する前に、これらのリソースに対する読み取り権限があることを確認してください。
  • 動的にカスタマイズされたフォントリソース: 編集を開始する前に、対応するフォントがシステムまたは少なくとも現在のアプリケーションセッションに登録されていることを確認してください。
[ドラフトロード: ^(NSArray<AliyunDraftLoadTask *> * tasks) {
    for (AliyunDraftLoadTask * task in tasks) {
        // リソースの読み込みタスクを処理します。
        // 1. タスクのリソースモデルを取得します。
        AEPResourceModel * resource = task.resource;

        // 2. タスクを処理します。
        // 他のリソースタイプのタスクを処理する方法については、デモのAliyunDraftLoader.mを参照してください。

        // 3. 処理結果をマークします。
        // 3.1.1成功: 結果を無視します。
        [タスクonIgnore];
        // 3.1.2成功: リソースモデルの属性を変更する必要があります。
        AEPSource * resultSoruce = [resource.source createWithPath:@ "result path"]; // たとえば、ロード後にリソースパスが変更された場合。
        [タスクonSuccess:resultSoruce];

        // 3.2.1失敗: 対応するノードを削除し、読み込みを続行します。
        [task onFailToRemove]; // たとえば、字幕のフォントをロードできない場合は、字幕を削除してロードを続行します。
        // 3.2.2失敗: 全体的な読み込み失敗をマークします。 次のエラーメッセージが表示されます。
        NSError * error = xxxx; // ロードエラーの理由を指定する必要があります。
        [task onFailToStopWithError:error]; // この失敗が発生した場合は、他のロードタスクを停止することを推奨します。
    }
} completion:^(NSString * taskPath, AliyunEditorBaseProject * project, NSError * error) {
    if (!taskPath !project error) {
        // 読み込みの失敗を処理します。
        // ほとんどの場合、error.localizedDescriptionには失敗の詳細な理由が含まれています。
        return;
    }

    // ロードが成功しました。
    // taskPathパラメーターを使用してエディターを作成し、編集を復元できます。 このトピックの「エディタの初期化」セクションを参照してください。
}];

ドラフトアップロード

編集は主にプロジェクト構成とリソースで構成されます。 プロジェクトの構成とリソースがクラウドに同期されると、クラウドドラフトが生成されます。 AliyunDraftProjectUploadTaskをします。

パフォーマンスを向上させ、ストレージ容量を節約するために、編集に使用されるリソースはデフォルトですべてコピーされません。 ただし、ドラフトには使用されているすべてのリソースの説明が記録されます。 リソースのインデックスを改善するには、AEPSource.path (ローカルパス) とAEPSource.sourceId (リソースID) を使用してリソースを記述します。 詳細については、「AEPSource」をご参照ください。 ドラフトリソースのロード、アップロード、およびダウンロードのプロセスでは、リソースの説明が送信されます。 さらに、現在ロードされているリソースが属するノードオブジェクト、タイムラインが属するモジュールなどの情報も送信される。 詳細については、「AEPResourceModel」をご参照ください。

ドラフトのアップロードには2つの手順が必要です。
  1. 編集に使用するすべてのリソースをアップロードします。 このプロセス中に、プロジェクト構成のリソースの説明が変更されます。
  2. 変更したリソースの説明を含むプロジェクト構成ファイルをアップロードします。
[draft uploadWithResourceUploader:^(NSArray<AliyunDraftLoadTask *> * tasks) {
    for (AliyunDraftLoadTask * task in tasks) {
        // アップロードタスクの処理。
        // 1. タスクのリソースモデルを取得します。
        AEPResourceModel * resource = task.resource;

        // 2. タスクを処理します。
        // 他のリソースタイプのタスクを処理する方法については、デモのAliyunDraftLoader.mを参照してください。

        // 3. 処理結果をマークします。
        // 3.1.1成功: 結果を無視します。
        [task onIgnore]; // たとえば、組み込みリソースをアップロードする必要はありません。
        // 3.1.2成功: リソースモデルの属性を変更する必要があります。
        AEPSource * resultSoruce = [resource.source createWithURL:@ "resource URL"]; // たとえば、リソースをアップロードした後にネットワーク接続を取得した場合。
        [タスクonSuccess:resultSoruce];

        // 3.2.1失敗: 対応するノードを削除し、アップロードを続行します。
        [task onFailToRemove]; // たとえば、字幕のフォントのアップロードに失敗した場合は、字幕を削除してアップロードを続行します。
        // 3.2.2失敗: 全体的な読み込み失敗をマークします。 次のエラーメッセージが表示されます。
        NSError * error = xxx; // アップロード失敗の理由を指定する必要があります。
        [task onFailToStopWithError:error]; // この失敗が発生した場合は、他のアップロードタスクを停止することを推奨します。
    }
} projectUploader:^(AliyunDraftProjectUploadTask * projTask) {
    // 処理用のクラウドドラフトを追加します。
    // 1.1ドラフトのプロジェクト構成ファイルのパスを取得します。
    NSString * projectFilePath = projTask.projectFilePath;
    // 1.2プロジェクト設定ファイルを処理します。
    NSString * projectUrl = [yourUploader upload:projectFilePath]; // たとえば、構成ファイルをアップロードした後にネットワークパスが返されます。

    // 2.1ドラフトを同期します。
    NSString * projectId = [yourApi addCloudDraft:projectUrl]; // たとえば、サービスを呼び出した後にIDが返されます。
    // 2.2ドラフトのプロジェクトIDを更新します。
    [projTask.draft changeProjectId:projectId];
    
    // 3. 処理結果をマークします。
    // 3.1成功。
    [projTask onSuccess];
    // 3.2失敗。
    NSError * error = xxx; // 失敗の理由を指定する必要があります。
    [projTask onFailWithError: エラー];
} completion:^(NSError * error) {
    if (error) {
        // アップロードの失敗を処理します。
        return;
    }
        
    // アップロードの成功を処理します。
}];

Draftダウンロード、

ドラフトのプロジェクト構成には、使用されているすべてのリソースの説明が記録されます。 したがって、プロジェクト構成ファイルはすべてのリソースを列挙できます。 リソースがローカルシステムに同期されると、ドラフトがダウンロードされます。

ドラフトをダウンロードするときに、ドラフトを保存する場所を指定する必要があります。 したがって、ドラフトダウンロードAPI操作はAliyunDraftManagerで定義されています。

// 0。 ビジネスに基づいて、クラウドドラフトに対応するプロジェクト構成ファイルとプロジェクトIDを取得します。
NSString * projectFilePath = xxx;
NSString * projectId = xxx;

// 1。 下書きをダウンロードします。
[draftManager downloadDraftWithProjectFile:projectFilePath resourceDownloader:^(NSArray<AliyunDraftLoadTask *> * tasks) {
    for (AliyunDraftLoadTask * task in tasks) {
        // ダウンロードタスクを処理します。
        // 1. リソースを取得します。
        AEPResourceModel * resource = task.resource;

        // 2. タスクを処理します。
        NSString * localPath = [yourDownloader download:resource.source.URL]; // たとえば、ネットワークダウンロードを実行する場合。

        // 3. 処理結果をマークします。
        AEPSource * localSource = [resource.source createWithPath:localPath]; // たとえば、リソースがローカルシステムにダウンロードされた場合。
        [task onSuccess:localSource];
        // その他の結果のマーキングについては、「ドラフトの読み込み」セクションを参照してください。
    }
} completion:^(AliyunDraft * draft, NSError * error) {
    if (エラー! ドラフト) {
        // ダウンロードの失敗を処理します。
        return;
    }

    // ダウンロードの成功を処理します。
    [draft changeProjectId:projectId]; // クラウドでIDを確認することを推奨します。
    // 残りの処理を完了します。
}];

その他の設定

落書き

ショートビデオSDKは、キャンバスとペイントブラシを設定するための操作を含む一連のdoodle操作を提供します。 AliyunICanvasViewを使用して、doodle設定を管理できます。 コードで使用されるパラメーターの詳細については、「関連クラス」をご参照ください。

// 1. ペイントブラシを作成します。
AliyunIPaint * paint = [[AliyunIPaint alloc]initWithLineWidth:5.0 lineColor:UIColor.whiteColor];
// 2。 doodleビューを追加します。
AliyunICanvasView * paintView = [[AliyunICanvasView alloc]initWithFrame:CGRectMake(0、0、100、100) paint:paint];
[yourView addSubview:paintView];

// 3。 落書きだ
// doodleにビューをタッチします。

// 4. その他の操作を実行します。
// 4.1アクションを元に戻す。
[paintView undo];
// アクションをやり直して4.2。
[paintView redo];
// すべてのdoodle操作を元に4.3ます。
[paintView undoAllChanges];
// 4.4すべての行をクリアします。 この操作は元に戻すことができません。
[paintView削除];

// 5。 完全な落書き。
UIImage * image = [paintView complete];
NSString * paintPath = xxx;
[UIImagePNGRepresentation (画像) writeToFile:paintPath atomically:YES];

// 6。 編集に追加します。
AliyunEffectImage * paintImage = [[AliyunEffectImage alloc] initWithFile:paintPath];
[エディターapplyPaint:paintImage linesData:paintView.lines];

// 7。 落書きを削除します。
[エディターremovePaint:paintImage];