Go解析Flv数据,统计看视频进度

B站是个好地方,上面有好多视频可以学习,但有时候网络不稳定,于是便使用工具将视频下载了下来。在看视频学习的过程中,想统计一下自己的学习进度,便开发了这个工具

github地址:https://github.com/Andrew201801/calculateProgress

使用教程:

  • 下载release文件,并解压

  • 在放视频的文件夹下,新建一个pass目录,将看过的视频放进去

    • 如下例,数据库文件夹下,有《149什么是函数依赖.flv》等一堆看过的文件,而在数据库文件夹下的pass文件夹内,包含了《 001数据库系统课程简要介绍.flv》等一堆看过的文件
    • 文件示例
  • cd 进release文件的目录,使用命令行调用:

    calculateProgress.exe 目录名称 读取模式
    
    如上例,调用命令为(三者都可):
    calculateProgress E:\\数据库 0
    calculateProgress E:\\数据库 1
    calculateProgress E:\\数据库
    

    目录名称:视频文件的根目录

    读取模式:默认为0,可以为空,0表示直接读取文件,比较快,1表示使用ffmpeg调用,比较慢

    首次使用将生成info.txt文件,记录视频的时长数据。后续使用将直接使用这个文件,可以直接获得数据。

开发过程&代码注释

其实去年考研期间用python写过一个一样的工具,这次怀着练习go的语法的想法,用go重构了一下,并深入学习了mp4和flv的文件格式。

整体流程是这样的:

  • 读取看完和没看完的视频的路径
  • 检查是否首次运行,首次运行就读取解析flv文件,生成info.txt文件
  • 将读取到的视频时长数据和看完,没看完的视频进行匹配,统计各自的时长
  • 将统计结果输出

可以看出来,整体流程来说并没有什么难点,关键在于如何读取flv文件,获取视频的时长数据,我是这么做的(不想看可以直接跳过,看下面的成品):

  • 网上搜索“go 视频 时长”,拿到了这篇文章:纯Golang获取MP4视频时长信息,于是我为了弄懂代码里的含义,去看了MP4文件格式的解析,具体来说就是一堆堆的box,然后时长数据在moov box里,使用timeScale和Duration字段的值,就能计算出来,但我要白嫖代码的时候,发现我的视频都是flv格式的ORZ,于是这条路堵死了。不过这个代码也对我有很大帮助,我从中学习到了如何读取二进制文件
  • 之后我开始查找flv文件的格式,找到了flv格式详解+实例剖析,在博主的帮助下,我知道了时长数据在首个tag,onMetaData里的duration字段里,并需要按照double(Golang是float64)的方式解析,再参考Golang 中的常见字节操作,知道了如何将[]byte转为double

成品:

示例,如下面这个文件:

image-20210706152731875

时长数据为:40 81 BC 0A 3D 70 A3 D7(都是十六进制,需要解析为double)

代码:

file, err := os.Open(filePath)
if err != nil {
    panic(err)
}
keyName:=""
//一个字节一个字节读
var currentByte = make([]byte, 0x01)
var offset int64 = 0
for {
    _, err = file.ReadAt(currentByte, offset)
    if err != nil {
        fmt.Println("读取文件时,发生错误!")
        break
    }
    //遇到小写字母,添加到keyName中
    if currentByte[0]>0x60 && currentByte[0]<0x7B{
        keyName+=string(currentByte[0])
    }else{
        //获取完整的keyName后判断是否拿到了duration
        if keyName=="duration"{
            //fmt.Println("找到了!")
            offset++
            break
        }else{
            keyName=""
        }
    }
    offset++
}
//拿到duration后,将数据按float64的格式读出
var durationBytes=make([]byte,0x08)
_, err = file.ReadAt(durationBytes, offset)
var duration=math.Float64frombits(binary.BigEndian.Uint64(durationBytes))
//方便计算,转成int
return int(duration)

(PS:double的解析也可以自己来,但需要计组基础,IEEE 754浮点数标准详解)

引用:
纯Golang获取MP4视频时长信息
flv格式详解+实例剖析
Golang 中的常见字节操作
IEEE 754浮点数标准详解

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 215,794评论 6 498
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,050评论 3 391
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 161,587评论 0 351
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,861评论 1 290
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,901评论 6 388
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,898评论 1 295
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,832评论 3 416
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,617评论 0 271
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,077评论 1 308
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,349评论 2 331
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,483评论 1 345
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,199评论 5 341
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,824评论 3 325
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,442评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,632评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,474评论 2 368
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,393评论 2 352

推荐阅读更多精彩内容