FLV 封装格式详解

FLV 封装格式详解

  • FLV 封装格式详解
    • 简介
    • FLV 格式
    • FLV header
    • FLV body
      • back-pointer
      • FLV tag
        • FLV tag header
        • FLV tag data:audio tag
        • FLV tag data:video tag
        • FLV tag data:script tag
    • 总结:FLV 层次结构
    • 实例:flvAnalyser 解析 FLV 文件
    • 解析 FLV 文件的 C 语言代码
    • 参考

FLV 封装格式详解

简介

FLV(Flash Video)是 Adobe 公司设计开发的一种流行的流媒体格式,由于其视频文件体积轻巧、封装简单等特点,使其很适合在互联网上进行应用。此外,FLV可以使用 Flash Player 进行播放,而 Flash Player 插件已经安装在全世界绝大部分浏览器上,这使得通过网页播放 FLV 视频十分容易。目前主流的视频网站如优酷网,土豆网,乐视网等网站无一例外地使用了 FLV 格式。FLV 封装格式的文件后缀通常为“.flv”。直播场景下拉流比较常见的是 http-flv 直播流,具有延时低,易传输等特点。

FLV 格式

总体上看,FLV 由文件头(file header)和(file body)组成,其中 FLV body 由一对对的 Tag 和 Previous Tag Size 组成。

在这里插入图片描述

其中,Previous Tag Size 占用4个字节,记录前一个 Tag 的大小,用于逆向读取处理。

FLV header 后的第一个 Previous Tag Size 为 0。

Tag 由 Tag Header 和 Tag Body 组成。Tag Header 占 11 字节。

而 Tag Body 一般分为三种类型:脚本(Script)数据、视频数据、音频数据。其中 Video Tag 和 Audio Tag 由 Tag header 和 Tag Data 组成;Script Tag 只有 Tag Data。

FLV 数据以大端序进行存储,在解析时需要注意。

FLV 文件的详细内容结构如下:

在这里插入图片描述

FLV header

从上图中可以看到,FLV 头占用 9 个字节,用来标识文件类型为 FLV 类型,以及后续的音视频标识。一个 FLV 文件,每种类型的 tag 都属于一个流,也就是一个 flv 文件最多只有一个音频流,一个视频流,不存在多个独立的音视频流在一个文件的情况。FLV 头的结构如下:

在这里插入图片描述

上面的 UI 表示无符号整型,后面跟着的数字代表其长度是多少位;UB 表示位域,表示一个字节的多少位。可以参考C语言中的结构体位域。

所有 FLV 格式文件都以 FLV Header 开头。FLV Header 类型是 FLVHEADER,FLVHEADER 定义如下:

typedef struct {
    UI8 Signature; // 'F' (0x46)
    UI8 Signature; // 'L' (0x4C)
    UI8 Signature; // 'V' (0x56)
    UI8 Version; // FLV 版本。例如,0x01 表示 FLV 版本 1
    UI8 TypeFlags; // b0 是否存在视频流,b2 是否存在音频流,其他字段保留,值为 0
    UI32 DataOffset; // FLV Header 长度,单位:字节
} FLVHEADER;

在 FLV 版本 1 中,“数据偏移”字段值为 9。在 FLV 未来版本中,此字段可兼容更大尺寸的 FLV Header。

FLV body

FLV Header之后,就是 FLV File Body。FLV File Body 是由一连串的 back-pointers + tags 构成。

在这里插入图片描述

FLV Body 类型是 FLVBODY,FLVBODY 定义如下:

typedef struct {
    UI32 PreviousTagSize0;
    FLVTAG Tag1;
    UI32 PreviousTagSize1;
    FLVTAG Tag2;
    ...
    UI32 PreviousTagSizeN-1;
    FLVTAG TagN;
    UI32 PreviousTagSizeN;
} FLVBODY;

back-pointer

back-pointer 表示 Previous Tag Size(前一个 tag 的字节数据长度),占4个字节,第一个 back-pointer 数据为 0。

FLV tag

tag 表示音视频数据,每一个 tag 由两部分组成:tag header 和 tag data。

FLV Tag 类型是 FLVTAG,FLVTAG 定义如下:

typedef struct {
    UB[2] Reserved; // 用于 FMS 的保留字段, 值为 0
    UB[1] Filter; // 指示 packet 是否需要预处理。0 = 不需要预处理。1 = packet 在渲染前需要预处理。未加密文件中此值为0,加密文件中此值为1。
    UB[5] TagType; // 8 = 音频,9 = 视频,18 = 脚本数据
    UI24 DataSize; // tag data 的长度。等于 tag 总长度 – 11
    UI24 Timestamp; // 当前tag的解码时间戳 (DTS),单位是ms。第一个tag的DTS总是0
    UI8 TimestampExtended; // 和Timestamp字段一起构成一个32位值, 此字段为高8位。单位是ms
    UI24 StreamID; // 总为 0
  IF TagType == 8
    AudioTagHeader Header;
  IF TagType == 9
    VideoTagHeader Header;
  IF TagType == 8
    AUDIODATA Data;
  IF TagType == 9
    VIDEODATA Data;
  IF TagType == 18
    SCRIPTDATA Data;
} FLVTAG;

上面 Timestamp 和 TimestampExtended 两个字段拼成一个 32 位的时间戳,是当前 Tag 的解码时间戳 (DTS)。对于音频帧来说,PTS 和 DTS 相同。对于视频帧来说,若含 B 帧,则 PTS 和 DTS 不同,H264 视频帧 PTS = DTS + CTS,CTS 就是 CompositionTime 字段,表示 PTS 与 DTS 的时间偏移值,单位 ms。

FLV tag header

存放当前 tag 的类型、数据区长度、时间戳等信息。tag header 一般占 11 个字节。

在这里插入图片描述

FLV tag 的类型可以是视频、音频和 Script(脚本类型)。

FLV tag data:audio tag

audio tag 包含 audio tag header 和 audio tag body 两部分。

其中,audio tag header 占 1 字节,包含了音频数据的参数信息,从第 2 个字节开始为音频流数据。

在这里插入图片描述

前 4bit 表示音频格式;第 5、6bit 表示采样率;第 7bit 表示采样精度;第 8bit 表示音频声道。

在这里插入图片描述

这里着重强调一下格式10格式:AAC。声音类型应为 1 (立体声) 且采样率应为 3 (44 kHz)。这并不表示 FLV 中的 AAC 音频总是立体声、44 kHz的数据。实际上,Flash 播放器会忽略这两个值,而从已编码的 AAC 位流中提取出声道数和采样率信息。

第二个字节开始为音频数据:

在这里插入图片描述

如果音频格式为 10,即是 AAC 格式。AudioTagHeader 中会多出一个字节 AACPacketType,这个字段来表示 AACAUDIODATA 的类型:0 = AAC sequence header,1 = AAC raw。

  • AAC sequence header 也就是包含了 AudioSpecificConfig,里面有一些更加详细音频的信息。
  • AAC raw 这种包含的就是音频 ES 流了,也就是音频负载(audio payload)。

AudioTagHeader 定义如下:

typedef struct {
    UB [4] SoundFormat;
    UB [2] SoundRate;
    UB [1] SoundSize;
    UB [1] SoundType;
  IF SoundFormat == 10
    UI8 AACPacketType;
} AudioTagHeader;

AudioTagBody/AUDIODATA 定义如下:

typedef struct {
  IF Encrypted
    EncryptedBody Body
  else
    AudioTagBody Body;
} AudioTagBody;

AUDIODATA 包含 Body 字段。如果采用了加密,Body 的类型是 EncryptedBody,可参考规范文档“附件 F. FLV 加密”章节获得详细信息,此处略。如果未采用加密,则 Body 的类型是 AudioTagBody,下面详述。

AudioTagBody 定义如下:

typedef struct {
  IF SoundFormat == 10
    AACAUDIODATA SoundData;
  ELSE
    Varies by format
} AudioTagBody;

Flash 播放器 9.0.115.0 及以上版本支持 AAC 格式。AACAUDIODATA 定义如下:

typedef struct {
  IF AACPacketType == 0
    AudioSpecificConfig;
  ELSE IF AACPacketType == 1
    Raw AAC frame data in UI8;
} AACAUDIODATA;

在这里插入图片描述

FLV tag data:video tag

video tag 包含 video tag header 和 video tag body 两部分。video tag data 开始的第一个字节包含视频数据的参数信息,从第二个字节开始为视频流数据。结构如下:

在这里插入图片描述

第一个字节包含视频信息:前4位表示帧类型;后4位表示编码类型。

在这里插入图片描述

第 2 个字节开始为视频数据。

在这里插入图片描述

如果 CodecID = 7,视频的格式是 AVC(H.264)的话,VideoTagHeader 会多出 4 个字节的信息,AVCPacketType(1 字节) 和 CompositionTime(3 字节),所以是 H.264 编码的情况下 VideoHeader 长度是 5 个字节。

AVC VIDEO PACKET 结构如下:

在这里插入图片描述

VideoTagBody/VIDEODATA 定义如下:

typedef struct {
  IF Encrypted
    EncryptedBody Body
  else
    VideoTagBody Body;
} VIDEODATA;

VIDEODATA 包含 Body 字段。如果采用了加密,Body 的类型是 EncryptedBody,可参考规范文档“附件 F. FLV 加密”章节获得详细信息,此处略。如果未采用加密,则 Body 的类型是 VideoTagBody,下面详述。

VideoTagBody 包含视频帧净荷数据。VideoTagBody 定义如下:

typedef struct {
  IF FrameType == 5
    UI8 VideoData;
  ELSE (
  IF CodecID == 2
    H263VIDEOPACKET VideoData;
  IF CodecID == 3
    SCREENVIDEOPACKET VideoData;
  IF CodecID == 4
    VP6FLVVIDEOPACKET VideoData;
  IF CodecID == 5
    VP6FLVALPHAVIDEOPACKET VideoData;
  IF CodecID == 6
    SCREENV2VIDEOPACKET VideoData;
  IF CodecID == 7
    AVCVIDEOPACKET VideoData;
  )  
} VideoTagBody;

AVCVIDEOPACKET 包含 AVC(H264)视频净荷数据。AVCVIDEOPACKET 定义如下:

typedef struct {
  IF AVCPacketType == 0
    AVCDecoderConfigurationRecord Data;
  IF AVCPacketType == 1
    One or more NALUs
} AVCVIDEOPACKET;

AVCDecoderConfigurationRecord 包含着 H.264 解码相关比较重要的 sps 和 pps 信息,再给 AVC 解码器送数据流之前一定要把 sps 和 pps 信息送出,否则的话解码器不能正常解码。而且在解码器 stop 之后再次 start 之前,如 seek、快进快退状态切换等,都需要重新送一遍 sps 和 pps 的信息。

AVCDecoderConfigurationRecord 在 FLV 文件中一般情况也是出现 1 次,也就是第一个 video tag。

FLV tag data:script tag

script tag 又通常被称为 metadata tag,会放一些关于FLV视频和音频的元数据信息如:duration、width、height等。通常该类型 tag 会跟在 FLV header 后面作为第一个 tag 出现,而且只有一个。

script tag 没有 script tag header,只有script tag body。一般来说,script tag 包含两个 AMF 包。结构如下所示:

在这里插入图片描述
第一个 AMF 包(封装字符串类型数据):

  • 第 1 个字节表示 AMF 包类型,一般总是 0x02,表示字符串;
  • 第 2-3 个字节为 UI16 类型值,表示字符串的长度,一般总是 0x000A(“onMetaData”长度);
  • 后面字节为字符串数据,一般总为 “onMetaData”(6F,6E,4D,65,74,61,44,61,74,61)。

第二个 AMF 包(封装一个数组类型,这个数组中包含了音视频信息项的名称和值):

  • 第 1 个字节表示 AMF 包类型,一般总是 0x08,表示数组。
  • 第 2-5 个字节为 UI32 类型值,表示数组元素的个数。
    后面即为各数组元素的封装,数组元素为元素名称和值组成的对。表示方法如下:第 1-2 个字节表示元素名称的长度,假设为 L。后面跟着为长度为 L 的字符串。第 L+3 个字节表示元素值的类型。后面跟着为对应值,占用字节数取决于值的类型。

常见的数组元素表示如下表:

在这里插入图片描述

AMF:Action Message Format,是 Adobe 设计的一种通用数据封装格式,在 Adobe 的很多产品中应用,简单来说,AMF 将不同类型的数据用统一的格式来描述。

👇下面是有关 script data 更详细的解释👇。

ScriptTagBody/SCRIPTDATA 定义如下:

typedef struct {
  IF Encrypted
    EncryptedBody Body
  else
    ScriptTagBody Body;
} SCRIPTDATA;

ScriptTagBody 包含以 AMF 编码的 SCRIPTDATA。AMF 是一种紧凑二进制格式,用于序列化 ActionScript 对象图。ScriptTagBody 定义如下:

typedef struct {
    SCRIPTDATAVALUE Name;
    SCRIPTDATAVALUE Value;
} ScriptTagBody;

这里的 Name 就是上面提到的 script tag 中的方法名,Value 是此方法的一组参数。

一个 SCRIPTDATAVALUE 记录包含一个特定类型的 ActionScript 值。

SCRIPTDATAVALUE 定义如下:

typedef struct {
    UI8 Type;
  IF Type == 0
    DOUBLE ScriptDataValue;
  IF Type == 1
    UI8 ScriptDataValue;
  IF Type == 2
    SCRIPTDATASTRING ScriptDataValue;
  IF Type == 3
    SCRIPTDATAOBJECT ScriptDataValue;
  IF Type == 7
    UI16 ScriptDataValue;
  IF Type == 8
    SCRIPTDATAECMAARRAY ScriptDataValue;
  IF Type == 10
    SCRIPTDATASTRICTARRAY ScriptDataValue;
  IF Type == 11
    SCRIPTDATADATE ScriptDataValue;
  IF Type == 12
    SCRIPTDATALONGSTRING ScriptDataValue;
} SCRIPTDATAVALUE;

SCRIPTDATAVALUE 的两个字段,Type 是类型,ScriptDataValue 是值。Type 的值确定 ScriptDataValue 的类型。

在这里插入图片描述

因为 ScriptDataValue 的类型是动态的,由运行时解析得到的 Type 的值确定,所以这里类型和值用了两个字段。如果是静态类型,显然只用一个字段就可以了。

第一个 AMF(Name) 的 Type = 2,类型为 SCRIPTDATASTRING,定义如下:

typedef struct {
    UI16 StringLength; // StringData 字段的长度,单位字节
    STRING StringData; // 字符串实际数据,注意不带结束符 NUL
} SCRIPTDATASTRING;

第二个 AMF(Value) 的 Type = 8,类型为 SCRIPTDATAECMAARRAY,定义如下:

typedef struct {
    UI32 ECMAArrayLength; // ECMA 数组元素数量
    SCRIPTDATAOBJECTPROPERTY[] Variables; // 变量名和变量值的列表,即 ECMA 数组
    SCRIPTDATAOBJECTEND ListTerminator; // 列表终止符
} SCRIPTDATAECMAARRAY;

其中,SCRIPTDATAOBJECTPROPERTY 类型定义了 ActionScript 对象或关联数组变量的对象属性。

SCRIPTDATAOBJECTPROPERTY 定义如下:

typedef struct {
    SCRIPTDATASTRING PropertyName;
    SCRIPTDATAVALUE PropertyData;
} SCRIPTDATAOBJECTPROPERTY;

常见的数组元素表示如下表:

在这里插入图片描述

实例:onMetaData 对象

FLV 元数据对象应在名为 onMetadata 的 SCRIPTDATA 标签中携带。各种属性对通过 NetStream.onMetaData 属性运行的 ActionScript 程序有效。可用的属性根据创建 FLV 文件的软件而有所不同。

onMetaData 标签通常会成为 FLV Body 中的第一个标签,紧跟在 FLV Header 之后。onMetaData 标签中存储的是一些视频、音频及文件相关的元数据信息:如视频帧率,音频采样率、文件长度等。

onMetaData 标签的 Name 字段主要就是存储 “onMetaData” 字符串。具体为:第 1 个字节值是 0x02,表示 Name 字段是字符串类型。第 2-3 个字节为 UI16 类型值,标识字符串的长度,值为 0x000A (“onMetaData” 这个字符串的长度)。后面跟着的数据为具体的字符串,值为 “onMetaData”。

onMetaData 标签的 Value 字段存储上表所示的各属性键值对。具体为:第 1 个字节值是 0x08,表示 Value 字段是数组类型。第 2-5 个字节为UI32类型值,表示数组元素个数。后面紧跟着数组,数组元素为属性名称和值组成的对(键值对)。最后是数组的结束符。

ScriptTagBody onMetaData;

onMetaData.Name.Type == 0x02
onMetaData.Name.ScriptDataValue.StringLength == 0x000A
onMetaData.Name.ScriptDataValue.StringData == "onMetaData"

onMetaData.Value.Type == 0x08
onMetaData.Value.ScriptDataValue.ECMAArrayLength == 
onMetaData.Value.ScriptDataValue.Variables[0].PropertyName == {0x0005, "width"}   // SCRIPTDATASTRING 类型
onMetaData.Value.ScriptDataValue.Variables[0].PropertyData == {0x00, 1280.0}      // SCRIPTDATAVALUE 类型
onMetaData.Value.ScriptDataValue.Variables[1].PropertyName == {0x0005, "height"}  // SCRIPTDATASTRING 类型
onMetaData.Value.ScriptDataValue.Variables[1].PropertyData == {0x00, 720.0}       // SCRIPTDATAVALUE 类型
...

PropertyName 的类型是 SCRIPTDATASTRING,第一个参数是字符串长度,第二个参数是字符串。
PropertyData 的类型是 SCRIPTDATAVALUE,第一个参数是 Type,为 0 时,第二个参数是一个 Double 类型的变量。

总结:FLV 层次结构

在这里插入图片描述

在 C 语言中定义 FLV 文件结构,一目了然:

/*
 * @brief flv file header 9 bytes
 */
typedef struct flv_header {
    uint8_t signature[3];
    uint8_t version;
    uint8_t type_flags;
    uint32_t data_offset; // header size, always 9
} __attribute__((__packed__)) flv_header_t;

/*
 * @brief flv tag general header 11 bytes
 */
typedef struct flv_tag {
    uint8_t tag_type;
    uint32_t data_size;
    uint32_t timestamp;
    uint8_t timestamp_ext;
    uint32_t stream_id;
    void *data; // will point to an audio_tag or video_tag
}   flv_tag_t;

typedef struct audio_tag {
    uint8_t sound_format; // 0 - raw, 1 - ADPCM, 2 - MP3, 4 - Nellymoser 16 KHz mono, 5 - Nellymoser 8 KHz mono, 10 - AAC, 11 - Speex
    uint8_t sound_rate; // 0 - 5.5 KHz, 1 - 11 KHz, 2 - 22 KHz, 3 - 44 KHz
    uint8_t sound_size; // 0 - 8 bit, 1 - 16 bit
    uint8_t sound_type; // 0 - mono, 1 - stereo
    void *data;
}   audio_tag_t;

typedef struct video_tag {
    uint8_t frame_type;
    uint8_t codec_id;
    void *data;
}   video_tag_t;

typedef struct avc_video_tag {
    uint8_t avc_packet_type; // 0x00 - AVC sequence header, 0x01 - AVC NALU
    uint32_t composition_time;
    uint32_t nalu_len;
    void *data;
}   avc_video_tag_t;

实例:flvAnalyser 解析 FLV 文件

flvAnalyser是一款FLV分析工具。

下载地址:https://github.com/zymill/flvAnalyser

打开一个 FLV 文件,概述如下所示:

在这里插入图片描述

文件结构如下所示:

在这里插入图片描述

先来看看 FLV header:

在这里插入图片描述

这里可以看到,flag中,第0位与第2位都是1,表示既有视频也有音频。

紧跟着flv header之后的是Script Data Tag,一般来讲Script Data Tag只会出现一次,用来提供音视频数据的属性和配置信息,如分辨率、帧率、码率等。这些信息在音视频数据传输过程中通常保持不变,因此通常只需要在开始时发送一次。然而,在某些特殊情况下,Script Data Tag 可能会发送多次。例如,当音视频数据的属性或配置信息发生变化时(如动态调整分辨率、帧率等),发送端可能会发送新的 Script Data Tag 来更新元数据信息。接收端在收到新的 Script Data Tag 后,可以根据其中的信息进行相应的调整。

在这里插入图片描述

Video tag 的 tag header中也包括负载类型和负载长度,此外还有Time stamp和Time stamp ext时间戳,tag body中则是具体的媒体信息,下图展示了一个负载类型为H.264编码的Video Tag:

在这里插入图片描述

Audio tag 中的信息与Video tag中几乎没有差别,下图是下图展示了一个负载类型为ADPCM编码的Audio Tag:

在这里插入图片描述

解析 FLV 文件的 C 语言代码

详见于:最简单的 FLV 封装格式解析程序

参考

  1. https://blog.csdn.net/leixiaohua1020/article/details/17934487
  2. https://blog.csdn.net/leixiaohua1020/article/details/50535082
  3. https://www.jianshu.com/p/651deb57a6b4
  4. https://cloud.tencent.com/developer/article/1415235
  5. https://zhuanlan.zhihu.com/p/654246696
  6. https://cloud.tencent.com/developer/article/2344723

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/527611.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

pytorch演示pipeline并行

pytorch演示pipeline并行 1.单卡内存不够时,可以将网络切分成几段(stage),每个GPU负责一个stage。比如GPU0计算完之后将数据发送给GPU1算后续的stage 2.以上的方式,会导致GPU的利用率不高,可以将输入的batch切分成多份更小的batch,陆续送给GPU0,这样GPU0处理完micro batch0之后…

Anthropic 的 Claude 3 现能从数百个选项中可靠地挑选出合适的工具来完成任务

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗?订阅我们的简报,深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同,从行业内部的深度分析和实用指南中受益。不要错过这个机会,成为AI领…

flood_fill 算法|图形渲染

flood fill 算法常常用来找极大连通子图,这是必须掌握的基本算法之一! 图形渲染 算法原理 我们可以利用DFS遍历数组把首个数组的值记为color,然后上下左右四个方向遍历二维数组数组如果其他方块的值不等于color 或者越界就剪枝 return 代码…

浮点数在计算机中的存储

这一段代码的输出是什么? int main() {int n 9;float *pFloat (float *)&n;printf("n的值为:%d\n",n);printf("*pFloat的值为:%f\n",*pFloat);*pFloat 9.0;printf("num的值为:%d\n",n);pri…

企业网络安全运营能力的多维度评价及优化策略

网络安全是企业面临的一个日益重要的问题,安全运营能力的强弱直接关系到企业的健康可持续发展和综合竞争力的提升。为推动企业网络安全工作的标准化建设,提升企业的网络安全运营能力,本文从安全建设、安全应对和安全效果三个角度出发&#xf…

如何给MySQL数据库的所有表统一加上字段

在开发过程中,有时候慢慢的建了很多数据库表,但是后来发现需要统一增加某些字段的时候,可以通过alter语句 ALTER TABLE 表名 ADD 列名 数据类型;比如我要给t_user表增加gmt_create与gmt_modified字段,用作记录新增记录时间与更新…

达梦关键字(如:XML,EXCHANGE,DOMAIN,link等)配置忽略

背景:在使用达梦数据库时,查询SQL中涉及XML,EXCHANGE,DOMAIN,link字段,在达梦中是关键字,SQL报关键词不能使用的错误。 解决办法: 配置达梦安装文件E:\MyJava\dmdbms\data\DAMENG\dm.ini 忽略这些关键词,…

CGAL的交叉编译-androidlinux-arm64

由于项目算法需要从Linux移植到android,原先的CGAL库也需要进行移植,先现对CGAL的移植过程做下记录,主要是其交叉编译的过程.。 前提条件: 1、主机已安装NDK编译器,版本大于19 2、主机已安装cmake 和 make 3、主机…

政安晨:【Keras机器学习实践要点】(二十二)—— 基于 TPU 的肺炎分类

目录 简述 介绍 / 布置 加载数据 可视化数据集 建立 CNN 纠正数据失衡 训练模型 拟合模型 可视化模型性能 ​编辑预测和评估结果 政安晨的个人主页:政安晨 欢迎 👍点赞✍评论⭐收藏 收录专栏: TensorFlow与Keras机器学习实战 希望政安晨的博客…

达梦(DM)报错[-3209]: 无效的存储参数

[TOC](达梦(DM)报错[-3209]: 无效的存储参数) 最近有一个项目,一直使用的是达梦数据库,今天遇到了一个问题,就是将测试环境新增加的表导入线上时报错 [-3209]: 无效的存储参数,这里我用我本地的达梦数据库复现一下这个问题&#…

【HTML】简单制作一个动态变色光束花

目录 前言 开始 HTML部分 效果图 ​编辑​编辑​编辑​编辑总结 前言 无需多言,本文将详细介绍一段代码,具体内容如下: 开始 首先新建文件夹,创建一个文本文档,其中HTML的文件名改为[index.html]&a…

python-flask后端知识点

anki 简单介绍: 在当今信息爆炸的时代,学习已经不再仅仅是获取知识,更是一项关于有效性和持续性的挑战。幸运的是,我们有幸生活在一个科技日新月异的时代,而ANKI(Anki)正是一款旗舰级的学习工具…

【深度学习】环境搭建ubuntu22.04

清华官网的conda源 https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/ 安装torch conda install pytorch torchvision torchaudio pytorch-cuda12.1 -c pytorch -c nvidia 2.2.2 conda install 指引看这里: ref:https://docs.nvidia.com/cuda/cuda-installatio…

高创新 | Matlab实现OOA-CNN-GRU-Attention鱼鹰算法优化卷积门控循环单元注意力机制多变量回归预测

高创新 | Matlab实现OOA-CNN-GRU-Attention鱼鹰算法优化卷积门控循环单元注意力机制多变量回归预测 目录 高创新 | Matlab实现OOA-CNN-GRU-Attention鱼鹰算法优化卷积门控循环单元注意力机制多变量回归预测预测效果基本介绍程序设计参考资料 预测效果 基本介绍 1.Matlab实现OOA…

css实现各级标题自动编号

本文在博客同步发布,您也可以在这里看到最新的文章 Markdown编辑器大多不会提供分级标题的自动编号功能,但我们可以通过简单的css样式设置实现。 本文介绍了使用css实现各级标题自动编号的方法,本方法同样适用于typora编辑器和wordpress主题…

Qt案例 通过调用Setupapi.h库实现对设备管理器中设备默认驱动的备份

参考腾讯电脑管家-软件市场中的驱动备份专家写的一个驱动备份软件案例,学习Setupapi.h库中的函数使用.通过Setupapi.h库读取设备管理器中安装的设备获取安装的驱动列表,通过bit7z库备份驱动目录下的所有文件. 目录导读 实现效果相关内容示例获取SP_DRVIN…

计算机网络-运输层

运输层 湖科大计算机网络 参考笔记,如有侵权联系删除 概述 运输层的任务:如何为运行在不同主机上的应用进程提供直接的通信服务 运输层协议又称端到端协议 运输层使应用进程看见的好像是在两个运输层实体之间有一条端到端的逻辑通信信道 运输层为应…

Github上传大文件(>25MB)教程

0.在github中创建新的项目(已创建可忽略这一步) 如上图所示,点击New repository 进入如下页面: 1.下载Git LFS 下载git 2.打开gitbash 3.上传文件,代码如下: cd upload #进入名为upload的文件夹,提前…

k8s集群node节点状态为Not Ready

目录 一、Node节点Not Ready状态的可能原因 二、排查node节点状态为Not Ready的原因 一、Node节点Not Ready状态的可能原因 node节点状态为Not Ready可能的原因有: 1.网络插件出问题 有过安装经验的小伙伴应该很熟悉未安装网络插件的情况下node节点在集群中的状…

【MacOs】proxychains配置使用

一、开始 1. 安装proxychains 使用brew进行安装 brew install proxychains-ng没有homebrew的,可以使用该命令安装 /usr/bin/ruby -e "$(curl -fsSL https://cdn.jsdelivr.net/gh/ineo6/homebrew-install/install)"2. 配置代理配置文件 cd /opt/homeb…