任务描述
给定视频文件和爬取的弹幕(JSON 格式),要求将弹幕在整个视频长度区间内的分布密度计算出来并作图。其中,对于给定的窗口宽度 \(\Delta\),\(t\) 时刻的密度 \(\rho(t)\) 定义为 \(\rho(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)