视频弹幕时间密度分析与作图

任务描述

给定视频文件和爬取的弹幕(JSON 格式),要求将弹幕在整个视频长度区间内的分布密度计算出来并作图。其中,对于给定的窗口宽度 (Delta)(t) 时刻的密度 ( ho(t)) 定义为 ( ho(t)=displaystyle frac {displaystyle sum_{c.time in [t-Delta/2, t+Delta/2]} 1} {Delta})(t) 取整数即可。假设视频长度不超过 (10) 分钟,弹幕总数不超过 (10^4) 条。

思路分析

由于抽样数很少,我们直接对于每个结果,暴力枚举所有弹幕,检查是否在时间区间内即可。优化可以考虑排序加二分,这里偷懒不做了。

代码实现

绘图采用 matplotlib 进行。

import json
from os import read
import matplotlib.pyplot as plt
import numpy as np
from numpy.lib.stride_tricks import DummyArray
import ffmpeg
import math

import biliDanmu
import biliMedia


def readDanmuList(bid):
    with open("outputdanmu/{bid}.danmu.json".format(bid=bid), "r", encoding="utf-8") as f:
        str_danmu = f.read()
    return json.loads(str_danmu)


def getMediaDuration(bid):
    duration = ffmpeg.probe(
        "output/{bid}.mp4".format(bid=bid))["format"]["duration"]
    return duration


def calcDanmuDensity(danmu_list, duration, Delta=10):
    lim = int(math.ceil(float(duration)))
    ans = [0]*lim
    for i in range(lim):
        for danmu in danmu_list:
            if abs(float(danmu["time"])-i) < Delta/2:
                ans[i] += 1/Delta
    return ans


if __name__ == '__main__':
    bid = "BV16K4y1h7eq"

    biliDanmu.saveDanmuByBid(bid)
    biliMedia.getMP4ByBid(bid)

    danmu_list = readDanmuList(bid)
    duration = getMediaDuration(bid)
    ans = calcDanmuDensity(danmu_list, duration)

    print(ans)
    plt.plot(ans)
    plt.show()

测试结果

References

Bilibili 弹幕爬取初探 - Mollnn - 博客园 (cnblogs.com)

原文地址:https://www.cnblogs.com/mollnn/p/14965716.html