python解析flv协议(AMF数据)

本文介绍如何使用Python解析FLV格式,包括FLV文件头、文件体和Tag的详细解析,以及AMF0数据处理,提供了一个简单的Python实现。此外,文章还提及了FLV在直播中的应用和数据结构。
摘要由CSDN通过智能技术生成

学习python也有1周了,因为之前学习了golang,所以觉得python和golang有很多类似的地方,比如切片和语法,python的确是一门很好的语言,至少你了解了之后才会发现其实它很强大,编写效率很高,至少目前为止我觉得运行效率也很高,之前没学过python2,所以跳过直接python3,既然是学习总得练练手吧,因为前段时间打算做一个抓直播地址的工具,截取网卡数据包的时候,接触过rtmp协议和flv协议,所以打算做一个flv文件解析库,其实也谈不上库,也就是对python如何解析flv协议做一个封装而已,因为这个类Flv在AMF数据的处理上也只处理了AMF0的常用数据,amf元数据在rtmp直播中也常用到,其他的元数据,没有demo我也没法测试

 

flv协议相信做过直播的童鞋都很清楚,本文也就大概的提一下,因为网上介绍的文章很多,就不详细的介绍了

FLV(Flash Video)是现在非常流行的流媒体格式,由于其视频文件体积轻巧、封装播放简单等特点,使其很适合在网络上进行应用,目前主流的视频网站无一例外地使用了FLV格式。另外由于当前浏览器与Flash Player紧密的结合,使得网页播放FLV视频轻而易举,也是FLV流行的原因之一。

FLV是流媒体封装格式,我们可以将其数据看为二进制字节流。总体上看,FLV包括文件头(File Header)和文件体(File Body)两部分,其中文件体由一系列的Tag及Tag Size对组成。

FLV格式解析

header

头部分由一下几部分组成
Signature(3 Byte)+Version(1 Byte)+Flags(1 Bypte)+DataOffset(4 Byte)

  • signature 占3个字节
    固定FLV三个字符作为标示。一般发现前三个字符为FLV时就认为他是flv文件。
  • Version 占1个字节
    标示FLV的版本号。这里我们看到是1
  • Flags 占1个字节
    内容标示。第0位和第2位,分别表示 video 与 audio 存在的情况.(1表示存在,0表示不存在)。截图看到是0x05,也就是00000101,代表既有视频,也有音频。
  • DataOffset 4个字节
    表示FLV的header长度。这里可以看到固定是9

body

FLV的body部分是由一系列的back-pointers + tag构成

  • back-pointers 固定4个字节,表示前一个tag的size。
  • tag 分三种类型,video、audio、scripts。

tag组成

tag type+tag data size+Timestamp+TimestampExtended+stream id+ tag data

  • type 1个字节。8为Audio,9为Video,18为scripts
  • tag data size 3个字节。表示tag data的长度。从streamd id 后算起。
  • Timestreamp 3个字节。时间戳
  • TimestampExtended 1个字节。时间戳扩展字段
  • stream id 3个字节。总是0
  • tag data 数据部分

其实重点还是是数据部分,flv文件其实是有很多tag组合,常见的tag包含音频,视频,和脚本(元数据),脚本tag就是描述视频或音频的信息的数据,如宽度、高度、时间等等,一个文件中通常只有一个元数据, 音频tag和视频tag就是音视频信息了,采样、声道、频率,编码等信息,这都是基础的知识,关于协议网上很多介绍,下面直接上干货,之后打算学习下python通过ctypes封装调用c方面的知识,谁不想代码跑得快点了

flv.py

#!/usr/bin/env python3
# -*- coding: utf-8 -*-
__author__ = "mengdj@outlook.com"
import struct
import traceback
from enum import Enum, unique


"""flv文件解析,元数据解析采用amf0格式"""


@unique
class TagType(Enum):
    """标签类型"""
    FLV_TAG_AUDIO = 0x08
    FLV_TAG_VIDEO = 0x09
    FLV_TAG_SCRIPT = 0x12


@unique
class Amf0DataType(Enum):
    """脚本中的变量类型(本程序支持的元数据类型)"""
    FLV_AMF0_NUMBER = 0x00
    FLV_AMF0_BOOLEAN = 0x01
    FLV_AMF0_STRING = 0x02
    FLV_AMF0_OBJECT = 0X03
    FLV_AMF0_NULL = 0x05
    FLV_AMF0_ARRAY = 0x08
    FLV_AMF0_END_OF_OBJECT = 0x09
    FLV_AMF0_STRICT_ARRAY = 0X0a
    FLV_AMF0_DATE = 0X0b
    FLV_AMF0_LONG_STRING = 0X0c


class UnSupportFileFormat(Exception):
    pass


class UnSupportAmfValFormat(Exception):
    pass


class Tag(object):
    """flv文件头"""
    previousTagsSize = 0
    type = 0
    length = 0
    timestamp = 0
    exTimestamp = 0
    streamsId = 0
    # 原始数据
    data = []

    def parse(self):
        """请子类实现此方法来解析原始数据"""
        pass

    def __str__(self):
        """like tostring"""
        return "%s previousTagsSize:%d type:%d length:%d timestamp:%d exTimestamp:%d streamsId:%d" % (
            self.__class__, self.previousTagsSize, self.type, self.length, self.timestamp, self.exTimestamp,
            self.streamsId)

    def getBytes(self):
        """获取原始字节数据"""
        return self.data


# end of class Tag

class AudioTag(Tag):
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值