You can replace the video, image, and text in a video template to generate a new video. The video template feature of short videos allows you to crop a large number of videos that have the same style as an existing video at a time.

Supported editions

Edition Supported
Professional Yes
Note Only the short video SDK V3.27 or later support the video template feature.
Standard No
Basic No

Related classes

Class Description
AliyunTemplate The class that defines the template.
AliyunTemplateParam The class that defines template parameters.
AliyunTemplateNode The class that defines the node for applying the template.
AliyunTemplateClipNode The class that defines the clip node for applying the template.
AliyunTemplateCaptionNode The class that defines the subtitle node for applying the template.
AliyunTemplateEditor The class that defines the editor for applying the template.
AliyunTemplateModifyContent The class that defines what you want to modify in the template builder.
AliyunTemplateBuilder The class that defines the template generator.
AliyunTemplateExporter The class that defines the template exporter.
AliyunTemplateLoader The class that defines the template loader.
AliyunTemplateImporter The class that defines the template importer.
ATResourceModel The class that defines the template resource model.
AliyunTemplateResourceExport The class that defines the template resource export manager.
AliyunTemplateResourceImport The class that defines the template resource import manager.

Generate a template

You can generate a template file in the editor or draft directory and store the file in the specified directory. You can also open and edit the generated template file. You can obtain the AliyunTemplate object and provide API operations to update thumbnails, preview videos, preview titles, preview templates, and lock nodes. For more information about the parameters that are used in the code, see Related classes.
// Generate a template file and update it.
NSString *taskPath = [[AlivcTemplateResourceManager builtTemplatePath] stringByAppendingPathComponent:[NSUUID UUID].UUIDString];
AliyunTemplateBuilder *builder = [AliyunTemplateBuilder build:taskPath editorTaskPath:_taskPath];
if (builder) {
    // update title
    [builder updateTitle:_titleView.text];

    // update cover url
    NSString *coverPath = [_taskPath stringByAppendingPathComponent:@"template_cover.png"];
    NSData *data = UIImagePNGRepresentation(_coverImage);
    [data writeToFile:coverPath atomically:YES];
    [builder updateCover:coverPath];

    // update preview with remote url
    [builder updatePreviewVideo:_outputPath];

    // save all
    [builder save];

    AlivcTemplateBuilderViewController *vc = [[AlivcTemplateBuilderViewController alloc] initWithEditorTaskPath:taskPath isOpen:YES];
    [self.navigationController pushViewController:vc animated:YES];

    return;
}

Export the template

The generated template and its associated custom resources (including template resources and project resources, except built-in app resources or platform resources) all exist in the configuration file as an absolute path (Source.Path). If the template needs to be used on different devices or platforms, you need to export the template. When you export the template, the local associated resources are copied to the relative directory or uploaded and the specified address (Source.URL) is returned for cross-device use. For more information about the parameters that are used in the code, see Related classes.
NSString *taskPath = @"Storage directory";
NSString *templateTaskPath = @"Template directory";

AliyunTemplateResourceExport *resourceExport = [AliyunTemplateResourceExport new];

// Export template resources. The purpose is to convert the path of local custom resources to http (local resources need to be uploaded) or a custom protocol address, for example, "alivc_resource://relation?path=". For more information, see the demo code example.
resourceExport.selfResourceExport = [AlivcTemplateResourceManager templateResourceExport:taskPath];

// Export project resources. The purpose is to convert the path of local custom resources to http (local resources need to be uploaded) or a custom protocol address, for example, "alivc_resource://relation?path=". For more information, see the demo code example.
resourceExport.projectResourceExport = [AlivcTemplateResourceManager projectResourceExport:taskPath];

// Start the export.
[AliyunTemplateExporter export:taskPath templateTaskPath:templateTaskPath resourceExport:resourceExport completed:^(NSError *error) {

    if (error) {
        // Failed
    }
    else {
        // Successful
    }
}];

Import the template

Templates to be used in an app are often built-in or downloaded over the Internet. These templates usually can be used across devices. If you need to use templates on the current device, you must import the templates to process associated resources. When you import a template, non-locally associated resources are downloaded if necessary. The resources with custom protocol addresses are processed and the specified absolute path (Source.Path) is returned. This way, the corresponding resources can be accessed when the template is loaded. For more information about the parameters that are used in the code, see Related classes.
NSString *tempTaskPath = @"Template directory";
NSString *taskPath = @"Storage directory";
// Import template resources. The purpose is to convert the custom protocol address (for example, "alivc_resource://relation?path=") to a local full path. For more information, see the demo code example.
AliyunResourceImport *resourceImport = [AlivcTemplateResourceManager templateResourceImport:tempTaskPath reset:YES];
[AliyunTemplateImporter import:taskPath templateTaskPath:tempTaskPath resourceImport:resourceImport completed:^(NSError *error) {
    if (error) {
        // If an error occurs, delete the local template file. You can try the import again next time.
        [[NSFileManager defaultManager] removeItemAtPath:taskPath error:nil];
    }
    else {
        // Successful
    }
}];

Load the template

The imported template can be used only after it is loaded. The template can be applied only after project resources are imported. For more information about the parameters that are used in the code, see Related classes.
// Load the loader.
NSString *taskPath = @"Template directory";
AliyunTemplateLoader *loader = [[AliyunTemplateLoader alloc] initWithTaskPath:taskPath];
if (loader) {
    self.loader = loader;
}
else {
    // Failed
}

// After project resources are imported, apply the template.
NSString *templateTaskPath = @"Template directory";
__weak typeof(self) weakSelf = self;
[self.loader loadProject:[AlivcTemplateResourceManager projectResourceImport:templateTaskPath reset:NO shouldDownload:YES] completed:^(NSError *error) {
    if (error) {
        // Failed to load resources.
    }
    else {
        // Successful. The template is applied.
        AlivcTemplateEditorViewController *tevc = [[AlivcTemplateEditorViewController alloc] initWithTemplateTaskPath:templateTaskPath];
        [weakSelf.navigationController pushViewController:tevc animated:YES];
    }
}];

Apply the template

You can edit a specified template or a draft to which the template has been applied. You can preview or replace nodes such as videos, images, and subtitles, and export videos. For more information about the parameters that are used in the code, see Related classes.
// Create an application template editor.
if (self.templateTaskPath) {
    // Create
    NSString *taskPath = [[AlivcTemplateResourceManager projectTemplatePath] stringByAppendingPathComponent:[NSUUID UUID].UUIDString];
    self.aliyunEditor = [AliyunTemplateEditor createTemplateEditor:self.templateTaskPath onTaskPath:taskPath];
}
else if (self.taskPath) {
    // Open
    self.aliyunEditor = [AliyunTemplateEditor openTemplateEditor:self.taskPath];
}

// Set the preview view.
self.aliyunEditor.preview = self.videoDisplayView;

// Load the editor. Subsequent operations can only be performed after the editor is loaded.
int ret = [self.aliyunEditor loadEditor];
if (ret != ALIVC_COMMON_RETURN_SUCCESS) {
    NSLog(@"Loading failed due to an authorization issue: %d", ret);
}

// Start editing.
[self.aliyunEditor startEdit];

// Play
[self.aliyunEditor..getPlayer play];

// Obtain the node list for change and sort them by lock and start time.
NSArray<AliyunTemplateClipNode *> *sortNodes = [[self.aliyunEditor clipNodes] sortedArrayUsingComparator:^NSComparisonResult(AliyunTemplateClipNode *obj1, AliyunTemplateClipNode *obj2) {
    if (obj1.lock && !obj2.lock) {
        return NSOrderedAscending;
    }
    else if (!obj1.lock && obj2.lock) {
        return NSOrderedDescending;
    }
    else if (obj1.timelineIn < obj2.timelineIn) {
        return NSOrderedAscending;
    }
    return NSOrderedDescending;
}];


// Change the video or image clip.
int ret = [self.aliyunEditor updateClipNode:node clipPath:sourcePath clipType:AliyunClipVideo];
if (ret == ALIVC_COMMON_RETURN_SUCCESS) {
    // Successful
}
else {
    NSLog(@"Change failed: %d", ret);
}

// Export
AlivcExportViewController *controller = [[AlivcExportViewController alloc] init];
controller.taskPath = self.aliyunEditor.taskPath;
controller.outputPath = [[AlivcTemplateResourceManager applyTemplatePath] stringByAppendingPathComponent:fileName];
controller.outputSize = self.aliyunEditor.getEditorProject.config.outputResolution;
controller.backgroundImage = [UIImage imageWithContentsOfFile:self.aliyunEditor.getCurrentTemplate.cover.path];
controller.coverImage = controller.backgroundImage;
controller.draft = draft;
[self.navigationController pushViewController:controller animated:YES];