快速剪辑-助力度咔智能剪辑提效实践

Posted 百度Geek说

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了快速剪辑-助力度咔智能剪辑提效实践相关的知识,希望对你有一定的参考价值。

一、设计背景

度咔剪辑作为百度出品的一款泛知识类视频剪辑工具,承载着创作者的剪辑工作,而快速剪主要解决快速去除无效片段的问题。

  • 修剪片段

    通常我们修剪片段时,需要人工跳转至大致位置,再通过播放视频来定位具体想要修剪的位置。快剪通过NLP识别视频中的字幕,按照视频timeline对齐展示,再通过字幕时长映射视频时间片段,快速修剪。

  • 语气、停顿、重复句

    由于泛知识类视频的特殊性,创作者录制过程中经常会出现语气、停顿、重复句等,假如我们需要修剪类似片段,只能够通过播放视频人工判定,操作繁琐。

    快速剪辑基于视频中提取的音频,借助NLP将含有语气的片段标记出来,再通过字幕之间的时间间隙,直接标记出无声片段区。重复句则可依据计算相邻句式的字符重复度来标记。

二、整体架构

  • Plugin:用于展示快剪控制器。

  • Window:用于渲染与视频控制。

  • Caption:用于字幕展示与操作。

2.1 Window

Window主要包含视频渲染、控制及撤销等功能:

  • Timeline:存储视频的clip数据;TimelineModel:存储贴纸、字幕等数据信息。

  • Streaming:负责渲染Timeline与TimelineModel数据信息,对视频进行预加载,播放控制,进度回调等。

  • LiveWindow:用于展示Streaming渲染好的View,调节尺寸背景,坐标换算等。

  • Restorer:用于保存用户操作,并对操作进行撤销、重做等。

2.2 Caption

Caption包含快剪的主要功能实现:字幕识别、字幕匹配、语气词、重复句等。

  • 当进入快速剪辑页面时,会率先对是否已识别过字幕进行检测,若N,则提取视频音频并上传至后端,进行NLP分析,获取字幕和语气片段数据。

    由于获取到字幕仅包含有效片段,得到后需要字幕与timeline做时间匹配。

    (视频信息是由clip对象存储的,每个clip对象表示一个单独的视频片段。一个clip包含trimIn、trimOut、inPoint、outPoint,通过这些数据来确定一个视频片段展示哪个视频,展示在视频的什么位置。字幕同理,通过字幕的clip数据,把文字放在正确的位置上。)

  • 若已经有字幕文件,则对比距上次识别是否有增添视频,如果有新增,则把未进行字幕识别的视频进行音频提取,传至后端进行NLP分析与识别。

  • 若对比后无新增视频,则直接进入空白句识别阶段。

  • 以上文得到的字幕clip与视频的clip数据,对相邻字幕依据空白句规则增加空白字幕clip。

  • 目前快剪重复句以上下4句、长度大于3且须包含中文为判定条件,综合字符重复度、莱文斯坦距离、余弦相似性三种策略计算重复比率。

/**
* 字符重复度
*/
private func similarity(s1: String, s2: String) -> Float {
    var simiCount: Float = 0
    var string2Array = [String]()
    for i in 0..<s2.count {
        // 从任意位置开始截取到任意位置,闭区间
        let string = subOneString(string: s2, from: i)
        string2Array.append(string)
    }
    for i in 0..<s1.count {
        let string1 = subOneString(string: s1, from: i)
        if string2Array.contains(string1) {
            let index2 = string2Array.firstIndex(of: string1)
            string2Array.remove(at: index2!)
            simiCount = simiCount + 1
        }
    }
    if simiCount == 0 {
        return 0.0
    }
    let rate: Float = simiCount / Float(max(s1.count, s2.count))
    return rate
}
/**
* 莱文斯坦距离,是编辑距离的一种。指两个字串之间,由一个转成另一个所需的最少编辑操作次数。
*/
-(CGFloat)levenshteinDistance:(NSString *)s1 compare:(NSString *)s2 {
    NSInteger n = s1.length;
    NSInteger m = s2.length;
    // 有一个字符串为空串
    if (n * m == 0) {
        return n + m;
    }
    // DP 数组
    int D[n + 1][m + 1];
    // 边界状态初始化
    for (int i = 0; i < n + 1; i++) {
        D[i][0] = i;
    }
    for (int j = 0; j < m + 1; j++) {
        D[0][j] = j;
    }
    // 计算所有 DP 值
    for (int i = 1; i < n + 1; i++) {
        for (int j = 1; j < m + 1; j++) {
            int left = D[i - 1][j] + 1;
            int down = D[i][j - 1] + 1;
            int left_down = D[i - 1][j - 1];
            NSString *i1 = [s1 substringWithRange:NSMakeRange(i - 1, 1)];
            NSString *j1 = [s2 substringWithRange:NSMakeRange(j - 1, 1)];
            if ([i1 isEqualToString:j1] == NO) {
                left_down += 1;
            }
            D[i][j] = MIN(left, MIN(down, left_down));
        }
    }
    NSInteger maxLength = MAX(s1.length, s1.length);
    CGFloat rate = 1.0 - ((CGFloat) D[n][m] / (CGFloat)maxLength);
    returnrate;
}
/**
* 余弦相似性: 首先将字符串向量化,之后在一个平面空间中求出他们向量之间夹角的余弦值。
*/
-(CGFloat)cos:(NSString *)s1 compare:(NSString *)s2 {
    NSMutableSet *setA = [NSMutableSet new];
    for (int i = 0; i < [s1 length]; i++) {
        NSString *string = [s1 substringWithRange:NSMakeRange(i, 1)];
        [setA addObject:string];
    }
    NSMutableSet *setB = [NSMutableSet new];
    for (int i = 0; i < [s2 length]; i++) {
        NSString *string = [s2 substringWithRange:NSMakeRange(i, 1)];
        [setB addObject:string];
    }
    // 统计字频
    NSMutableDictionary *dicA = [NSMutableDictionary new];
    NSMutableDictionary *dicB = [NSMutableDictionary new];
    for (NSString *key in setA) {
        NSNumber *value = dicA[key];
        if (value == nil) {
            value = @(0);
        }
        NSNumber *newValue = @([value integerValue] + 1);
        dicA[key] = newValue;
    }
    for (NSString *key in setB) {
        NSNumber *value = dicB[key];
        if (value == nil) {
            value = @(0);
        }
        NSNumber *newValue = @([value integerValue] + 1);
        dicB[key] = newValue;
    }
    // 向量化,求并集
    NSMutableSet *unionSet = [setA mutableCopy]; //取并集后
    [unionSet unionSet:setB];
    NSArray *unionArray = [unionSet allObjects];
    NSMutableArray *aVec = [[NSMutableArray alloc] initWithCapacity:unionSet.count];
    NSMutableArray *bVec = [[NSMutableArray alloc] initWithCapacity:unionSet.count];
    for (NSInteger i = 0; i < unionArray.count; i++) {
        [aVec addObject:@(0)];
        [bVec addObject:@(0)];
    }
    for (NSInteger i = 0; i < unionArray.count; i++) {
        NSString *object = unionArray[i];

        NSNumber *numA =  dicA[object];
        if (numA == nil) {
            numA = @(0);
        }
        NSNumber *numB =  dicB[object];
        if (numB == nil) {
            numB = @(0);
        }
        aVec[i] = numA;
        bVec[i] = numB;

    }
    // 分别计算三个参数
    NSInteger p1 = 0;
    for (NSInteger i = 0; i < aVec.count; i++) {
        p1 += ([aVec[i] integerValue] * [bVec[i] integerValue]);
    }
    CGFloat p2 = 0.0f;
    for (NSNumber *i in aVec) {
        p2 +=  ([i integerValue] * [i integerValue]);
    }
    p2 = (CGFloat)sqrt(p2);

    CGFloat p3 = 0.0f;
    for (NSNumber *i in bVec) {
        p3 +=  ([i integerValue] * [i integerValue]);
    }
    p3 = (CGFloat)sqrt(p3);
    CGFloat rate = ((CGFloat) p1) / (p2 * p3);
    return rate;
}
  • 由于刷新timeline十分耗费性能,在删除字幕时,可只修改字幕clip数据源,刷新下方tableview展示,在用户退出时再刷新timeline,这样即可避免因实时刷新带来的性能问题。

  • 一键优化后,将字幕数据回传于通用剪辑进行缓存及展示,也便于再次进入快速剪辑。

三、思考与总结

由于字幕识别在远端进行,严重依赖网络,未来度咔将通过飞桨在端中完成音频源数据分析、字幕、重复、语气等片段识别,增强时效性与数据安全性,同时也能节约流量存储成本。以上是整个快速剪辑一键智能剪辑的路径实践,希望通过本篇文章能够让大家有所收获、有所借鉴。

推荐阅读:

|基于etcd实现大规模服务治理应用实战

|短视频个性化Push工程精进之路

|百度爱番番数据分析体系的架构与实践

---------- END ----------

百度 Geek 说

百度官方技术公众号上线啦!

技术干货 · 行业资讯 · 线上沙龙 · 行业大会

招聘信息 · 内推信息 · 技术书籍 · 百度周边

欢迎各位同学关注

以上是关于快速剪辑-助力度咔智能剪辑提效实践的主要内容,如果未能解决你的问题,请参考以下文章

项目实训—基于AI的智能视频剪辑器项目架构搭建

解密体育背后AI黑科技:花样滑冰动作识别多模视频分类和精彩片段剪辑

十大视频场景化应用工具+五大视频领域冠军/顶会算法开源

虎牙直播在AI实时剪辑技术上的创新实践

十大视频场景化应用工具+五大视频领域冠军顶会算法重磅开源!

如何使用事件侦听器来加载动画片段的循环