使用 R 完成一个小小的时间条可视化

任务背景

在制作了一系列视频的时候,我们在每个视频的片头放置了一个渐显和渐隐的元素。但是不同的视频中,这个元素出现和消失的时间是不同的。我们需要统计一下每个视频中该元素出现和消失的时间点,并且发现在所有视频中共同存在的时间段。

另外,我私心想要小小地把这个共同存在的时间段可视化出来。

进行统计

需要先说明一点,剪映中(包括其他视频剪辑软件)中的这个时间表示方法中,第三个冒号后面的数字并不是毫秒,而是代表帧数。如果一个视频为 30fps,那么代表 1 秒 30 帧。也就是说,在 29 帧的时候,下一帧会到达下一秒:

Snipaste_2023-06-01_15-21-46.png

所有编程语音中,没有任何一个语言可以表示 HH:MM:SS:frame 这样的时间表示法。如果需要表示毫秒(Milliseconds)的话,一般表示方法为 HH:MM:SS.ms

在完成统计并进行记录后,得到这样一张表格:

Snipaste_2023-06-01_15-25-36.png

用 R 语言表示毫秒,以及可视化

如果想要使用传统的 R 语言表示毫秒的话,格式 format 中可以取 %OSn,n 代表显示的秒后面的位数,一般取值为 1-6 之间:

time <- strptime('0:31:02.115', format='%H:%M:%OS4')
format(time, '%H:%M:%OS4')

如果使用 lubridate 包的话,可以正常使用 hms 或者 ymd_hms 进行兼容:

library(lubridate)
time <- hms('0:31:02.115')

Snipaste_2023-06-01_15-30-45.png

接下来是就是如何对时间条进行可视化?其实,直接使用 ggplot 中的 geom_line 就能完成:

library(tidyverse)
library(lubridate)

# 读入统计好的视频数据
video_dat <- read_csv("D:\\video_start_to_end_time.csv")
video_dat

# 将帧数转换为秒,并和对应时间相加
video_dat <- video_dat %>%
  mutate(
    start_time_seconds = period_to_seconds(hms(开始时间)) + 开始帧数/30,
    end_time_seconds = period_to_seconds(hms(截止时间)) + 截止帧数/30
  )

# 转换数据:Wide to Long,方便进行绘图
video_dat2 <- gather(video_dat, attribute, video_time, start_time_seconds:end_time_seconds, factor_key=T)

# 准备共同时间段的起点和终点,方便进行标注
min_line <- max(video_dat$start_time_seconds)
max_line <- min(video_dat$end_time_seconds)

# 进行可视化
ggplot(video_dat2, aes(x=video_time, y=视频编号)) +
  geom_line(color="#f1d600", size=4.5) +
  geom_vline(xintercept = c(min_line, max_line), col="#b55552", size=1) +
  annotate("text", x = min_line+0.2, y = 10.5, label = as.character(round(min_line, digits=1))) +
  annotate("text", x = max_line+0.2, y = 10.5, label = as.character(round(max_line, digits=1))) +
  theme_minimal()

就能得到一个差不多得结果了:

Snipaste_2023-06-01_15-36-46.png

后面的增加单位,更改 x 轴和 y 轴标签之类的,就不再费时间完成了。

当然,还有另一种可以完成类似效果的方法是:geom_dumbbell,具体的实现方案可以参考 r-charts 网站 的介绍。