本文还有配套的精品资源,点击获取
简介:FLV是一种用于网络流媒体的视频格式。本文介绍了一种名为“flvparse”的小工具,用于解析FLV文件的二进制数据。工具展示了FLV文件的标签结构,包括音频、视频和脚本数据,以及如何通过命令行运行解析,从而帮助开发者更直观地理解FLV文件内容。介绍了flvparse在视频播放故障排查、内容分析、格式转换和流媒体研究等场景的应用。
1. FLV视频格式解析
FLV(Flash Video)格式是互联网上广泛使用的流媒体视频格式之一。它的高效性和较好的兼容性使其成为视频分享网站的标准格式。要深入理解FLV,我们必须从它的结构和原理开始。本章将介绍FLV格式的基础知识,包括它的起源、特点以及为什么它在流媒体领域中备受青睐。
1.1 FLV的诞生背景
FLV视频格式最初由Adobe Systems公司开发,是其Flash播放器的一部分。它允许视频内容通过HTTP协议进行流式传输,并且兼容几乎所有的现代浏览器。因此,FLV很快成为YouTube等视频分享网站首选的视频格式。
1.2 FLV的核心优势
FLV格式之所以能在早期互联网视频市场中占据一席之地,主要得益于以下几个优势:
压缩效率高 :FLV通过使用Sorenson Spark编解码器(H.263)和MP3音频压缩技术,使得视频文件相对较小,便于在线播放。 兼容性好 :几乎所有的浏览器都集成了Flash Player插件,使得FLV格式的视频可以跨平台、跨浏览器播放。 流式传输支持 :支持通过HTTP进行流式传输,用户在视频缓冲的同时可以开始观看视频内容。
1.3 FLV的使用现状
尽管FLV格式曾一度主导网络视频市场,但由于HTML5的兴起以及新的视频编码标准(如H.264)的发展,FLV格式的使用率有所下降。然而,它在某些特定场景下仍有其独特的价值,特别是在需要兼容老式系统的环境中。
随着技术的发展,我们可能需要对FLV文件进行解析和处理,而这就需要我们深入理解FLV的内部结构。第二章将带领我们走进FLV的文件结构和Tag介绍,为后续的分析和操作奠定基础。
2. FLV文件结构与Tag介绍
2.1 FLV文件的基本构成
2.1.1 文件头结构解析
FLV(Flash Video)文件格式是Adobe公司设计用于在网络上传输视频流的一种文件格式。它广泛应用于网络视频播放和分享平台,例如YouTube和Facebook在它们早期的版本中就使用了FLV格式。
文件头(File Header)是FLV文件的第一部分,包含了用于标识FLV文件类型的元数据。一个FLV文件头的长度通常是9个字节,包含了以下关键信息:
Signature(签名) :占3个字节,固定值为 FLV ,用于快速识别文件格式。 Version(版本) :占1个字节,FLV文件格式的版本号,目前普遍为 0x01 。 Flag(标志) :占5个字节,其中: 最后一个字节为0,用于指示文件头的结束。 前面四个字节表示该FLV文件是否包含音频和视频数据流。
一个典型的FLV文件头示例如下:
46 4C 56 01 01 00 00 00 09
这个文件头表明该FLV文件包含音频和视频流,并且支持脚本数据流。
2.1.2 数据块(Chunk)和Tag的概念
FLV文件的数据被组织成一系列的数据块(Chunk),每个数据块包含了特定类型的信息。数据块分为三种类型,分别对应FLV中的不同数据流:
音频块(Audio chunk) :包含音频信息。 视频块(Video chunk) :包含视频帧数据。 脚本块(Script chunk) :包含元数据和脚本信息。
每个数据块包含一个或多个Tag(标签),这些Tag是FLV文件中携带实际数据的基本单位。FLV Tag的类型主要有以下几种:
脚本数据Tag :如AMF0或AMF3格式的数据包,用于传输元数据和脚本信息。 音频Tag :包含音频流数据。 视频Tag :包含视频流数据。
一个数据块(Chunk)可能包含多个连续的Tag,这些Tag按照它们的类型和时间戳的顺序排列。时间戳记录了该Tag相对于前一个视频或音频Tag的延迟时长,以毫秒为单位。
2.2 FLV Tag的种类与结构
2.2.1 不同类型的Tag及作用
FLV Tag根据数据类型和用途的不同,可以分为以下几种:
音频Tag :用于传输音频流数据。FLV支持多种音频编解码格式,包括但不限于MP3和AAC。 视频Tag :用于传输视频帧数据。FLV支持多种视频编解码格式,如Sorenson Spark(H.263)和VP6。 脚本数据Tag :用于传输FLV文件的元数据(metadata),如视频的宽度、高度、持续时间等,以及播放器需要执行的脚本信息。
每种Tag都遵循相同的结构:一个Tag头部和随后的数据有效载荷(payload)。Tag头部提供了对数据有效载荷大小、类型以及时间戳等信息的描述。
2.2.2 Tag头和数据部分的详细分析
FLV Tag头部具有固定的11个字节的长度,包含了以下关键信息:
Tag类型(Tag Type) :占1个字节,用于标识Tag的类型,如音频Tag、视频Tag或脚本数据Tag。 数据长度(Data Length) :占3个字节,表示Tag数据部分的长度。 时间戳(Timestamp) :占3个字节,表示Tag的播放时间戳。 时间戳扩展(Timestamp Extended) :占1个字节,用于表示时间戳的扩展值,允许4个额外字节的使用。 流ID(Stream ID) :占3个字节,通常设为0x000001。
Tag的头部之后是Tag的数据部分,它的内容和长度取决于Tag的类型和FLV文件中的数据流。
下面是一个视频Tag的头部示例:
09 00 00 00 00 00 00 00 00 01 00 00
这个头部表示一个视频Tag,其数据长度为0,时间戳为0,并且流ID为1。由于数据长度为0,这表明该视频Tag实际上并没有携带任何数据。
综上所述,FLV文件的结构由文件头、数据块(Chunk)和Tag组成,每部分都具有特定的格式和作用。通过理解这些组成部分,我们可以更深入地分析和处理FLV文件,为后续的视频处理和分析工作打下基础。
3. flvparse工具功能与用法
3.1 flvparse工具的安装与配置
3.1.1 安装环境与依赖
flvparse 是一个广泛使用的命令行工具,用于分析和操作FLV文件。它支持多种操作系统,包括Windows、Linux和macOS。在开始使用flvparse之前,确保你的系统满足以下基础要求:
一台现代的计算机。 足够的磁盘空间用于安装和存储FLV文件。 适合你操作系统的flvparse版本。
安装flvparse通常很直接,因为它不需要复杂的安装程序。对于大多数Linux发行版和macOS,你可以通过包管理器(如apt-get、brew等)安装预编译的二进制文件。对于Windows,你可以下载预编译的可执行文件或使用包管理器,如chocolatey。
安装依赖通常包括:
Python版本2.7或更高版本。对于某些特定功能,可能需要Python 3。 FLV文件解析库(如FFmpeg)。
安装完成后,你可以通过在命令行中运行 flvparse --help 来检查flvparse是否正确安装。
3.1.2 配置flvparse工具的步骤
尽管flvparse的默认配置可以满足大部分需求,但有时你可能需要对工具进行个性化的设置。以下是一些常见的配置步骤:
设置环境变量 :如果你使用的是Linux或macOS,可能需要设置环境变量以确保flvparse能够找到FFmpeg和其他依赖。
bash export PATH=/path/to/ffmpeg:$PATH
在Windows上,你可以在系统的环境变量设置中添加FFmpeg的路径。
创建配置文件 :flvparse允许用户通过配置文件来定制输出。你可以通过运行 flvparse --init-config 来创建一个基本配置文件,并根据需要进行修改。
测试配置 :配置完成后,使用 flvparse --config /path/to/config 命令测试配置文件是否生效。
bash flvparse --config /path/to/config /path/to/flvfile.flv
3.2 flvparse工具的主要功能
3.2.1 对FLV文件的分析
flvparse工具的主要功能之一是对FLV文件进行详尽的分析。它支持解析FLV文件头,提取视频、音频流信息,以及识别和解读不同的Tag类型。flvparse提供了一个简单易用的接口来查看FLV文件的内部结构,这可以帮助开发者更好地理解文件内容和格式。
3.2.2 提取和显示FLV数据信息
flvparse不仅能分析FLV文件,还能提取其中的数据信息,如视频分辨率、帧率、音频格式和持续时间等。这为媒体处理人员提供了一个便利的工具,无需使用复杂的视频编辑软件即可获得关键信息。flvparse通过控制台输出这些信息,用户还可以通过配置输出格式,将其重定向到日志文件中。
3.3 flvparse命令行操作指南
3.3.1 基本命令使用方法
flvparse的基本使用方法非常直观。下面是一个简单的命令行示例,展示如何使用flvparse来分析一个FLV文件:
flvparse --info example.flv
上述命令将输出 example.flv 文件的详细信息。 --info 选项指示flvparse仅显示文件信息,并不进行深入分析。
3.3.2 高级选项与输出控制
flvparse也支持许多高级选项,例如过滤特定类型的Tags或限制输出的信息量。例如,如果你想仅查看FLV文件中的视频信息,可以使用以下命令:
flvparse --video example.flv
通过使用不同的参数和选项,flvparse可以灵活地适应不同的使用场景。输出控制允许用户指定输出格式,例如JSON或XML,以方便进一步的处理和自动化。
flvparse --json example.flv > output.json
以上命令将FLV文件的信息输出为JSON格式。
以上内容仅为第三章“flvparse工具功能与用法”的概述性描述。在后续章节中,我们将深入探讨flvparse的安装与配置、主要功能、命令行操作指南、二进制数据到人类可读格式的转换、应用场景分析、进阶功能与定制,以及性能优化与问题解决。
4. 二进制数据到人类可读格式的转换
4.1 二进制数据的结构和解读
4.1.1 二进制数据的基本概念
二进制数据是由0和1组成的数据形式,它是计算机内部最基础的数据表示方式。在处理FLV视频文件时,我们遇到的大部分数据都是二进制形式的,它们代表着音频、视频、元数据等信息。理解二进制数据的基本概念是解析和分析FLV文件的重要一步,也是开发和使用flvparse工具前必备的基础知识。
4.1.2 从二进制到可读数据的转换过程
将二进制数据转换为人类可读的格式是一个涉及编码和解码的过程。首先需要了解二进制数据的结构,包括它所遵循的协议和规范。对于FLV文件来说,这涉及到分析每个FLV Tag的结构,理解每个字节所代表的意义。例如,FLV文件头中的第一个字节表示文件的版本,而接下来的三个字节则表示文件的流类型。通过这样的映射和解读,我们可以将二进制数据转换为更高级的表示形式,如时间戳、视频编码信息、音频采样率等。
4.2 flvparse工具的数据格式化输出
4.2.1 输出格式的定制
flvparse工具提供了丰富的选项来自定义输出格式。用户可以根据自己的需求选择输出哪些信息,以及以何种形式展现。例如,如果你只想查看FLV文件中视频流的帧率信息,可以通过命令行参数来实现这一目标。下面是一个示例代码块,展示了如何使用flvparse来获取特定数据:
flvparse --show=video帧率 文件名.flv
4.2.2 通过flvparse实现数据可视化
flvparse不仅能够输出文本信息,还支持将解析的数据以图形化的方式展现。这对于理解FLV文件结构和分析视频流属性非常有帮助。可视化功能可以以图表的形式直观地展示数据流的变化,如音频和视频轨道的同步,或者帧率的波动。下面是一个mermaid流程图的示例,它描述了flvparse工具如何将音频和视频数据流进行同步的过程:
graph LR
A[开始] --> B[读取FLV文件]
B --> C[解析Tag]
C --> D[分离音频和视频数据流]
D --> E[计算时间戳]
E --> F[进行数据同步]
F --> G[生成可视化图表]
4.2.3 代码解读
上述代码块中的命令行参数 --show=视频帧率 是一种特定的用法,它告知flvparse工具输出视频帧率的详细信息。这里,“视频帧率”是指视频数据中记录的每秒显示的帧数,它是评估视频播放质量的一个重要指标。flvparse通过内部解析算法读取FLV文件的视频Tag,并提取出相应的帧率信息。这个过程对于视频编辑者来说非常实用,因为它可以帮助他们判断视频素材是否满足他们的编辑需求。
通过这种方式,flvparse工具能够将复杂的二进制数据结构转化为更加直观和人类可读的格式。这种高级的数据转换功能极大地提高了FLV文件分析的效率和易用性。
5. flvparse应用场景分析
5.1 媒体处理与分析
5.1.1 FLV视频编辑的前期准备
在进行FLV视频编辑前,通常需要对原始视频文件进行分析,以便了解其结构和内容。FLV视频编辑的前期准备工作包括视频信息的提取、关键帧的定位、元数据的解析等。flvparse工具在这一阶段扮演着关键角色,提供了一套强大的分析命令,可以轻松完成以下任务:
提取视频元数据 :如视频时长、宽高、帧率等。 列出所有关键帧 :这对于视频剪辑尤为重要,能够确定视频的可编辑点。 查找特定Tag :例如脚本数据或元数据,帮助编辑者了解视频内容的层次结构。
flvparse通过提供JSON或XML格式的输出选项,使得这些信息可以被自动化脚本处理,进一步集成到视频编辑流程中。
5.1.2 媒体信息的提取与分析
flvparse工具的媒体信息提取功能对于内容创作者而言,能够快速获取FLV文件的详细属性。例如,通过以下命令可以提取FLV文件的详细结构信息:
flvparse --format json input.flv
此命令将输出一个JSON格式的文件,其中包含了FLV文件中每个Tag的信息,如时间戳、Tag类型等。这样,编辑者可以基于这些信息,决定哪些部分的视频需要被保留、删除或修改。
5.2 故障诊断与数据恢复
5.2.1 常见FLV视频文件损坏问题的诊断
FLV视频文件损坏可能会导致视频播放不完整、图像和音频不同步等问题。通过flvparse工具,可以检查FLV文件是否完整,以及是否含有损坏的Tag或丢失的数据块。具体步骤包括:
完整性校验 :通过分析FLV文件头和Tag信息,确认是否所有必要的数据块都存在。 损坏Tag检测 :flvparse可以识别出损坏的Tag,并且报告它们的出现位置。
graph TD
A[开始诊断] --> B[读取FLV文件头]
B --> C[检查Tag信息]
C --> D{是否存在损坏Tag?}
D -- 是 --> E[记录损坏Tag位置]
D -- 否 --> F[输出完整检查报告]
E --> G[尝试修复或恢复]
F --> H[结束诊断]
G --> H
5.2.2 使用flvparse进行数据恢复尝试
数据恢复的过程一般包括以下步骤:
定位损坏区域 :根据flvparse的输出,找到损坏的Tag或数据块。 分析损坏原因 :确定损坏是由于文件传输错误、存储介质问题还是其他原因造成的。 数据恢复尝试 :如果损坏是由数据覆盖引起的,可以尝试使用未损坏的部分进行恢复。
flvparse --repair input.flv output.flv
此命令尝试对损坏的FLV文件进行修复,并输出一个新的FLV文件。请注意,并非所有损坏都可以被完全修复,flvparse在某些情况下仅能最大限度地减少数据丢失。
5.3 开发者工具与学习资源
5.3.1 flvparse作为开发者工具的集成
flvparse不仅是一个强大的命令行工具,也可以被集成到其他软件中作为开发者工具。开发者可以利用flvparse的API进行二次开发,创建更专业化的视频处理应用。例如:
视频处理库集成 :将flvparse集成到视频编辑软件中,提供FLV文件分析和预处理功能。 自定义脚本扩展 :基于flvparse提供的脚本接口,开发者可以根据具体需求编写特定的分析和处理脚本。
5.3.2 学习资源和文档的推荐
为了更好地使用flvparse工具,用户需要对相关的学习资源有所了解。以下是一些推荐资源:
官方文档 :flvparse的官方文档提供了详细的命令行参数说明和使用指南。 在线教程 :有许多在线平台提供flvparse的使用教程,包括视频和文本两种形式。 开发者社区 :加入flvparse的开发者社区,可以帮助用户更快地解决问题,并与其他用户交流经验。
为了深入理解flvparse的用法,用户应该从基本命令开始实践,逐步掌握高级选项和定制化功能。实践中遇到的任何问题,都可以在开发者社区中提出来寻求帮助。
6. flvparse进阶功能与定制
6.1 编写自定义脚本与插件
6.1.1 flvparse的脚本编写基础
flvparse作为一个强大的FLV文件分析工具,其能力不限于内置的功能。用户可以利用Python编写自定义脚本来扩展工具的功能,满足特定的需求。自定义脚本的编写通常需要对Python语法有一定的了解,同时也要熟悉flvparse提供的API接口。
编写脚本的第一步是了解flvparse提供的脚本接口。flvparse通常会提供一系列用于文件分析、数据提取的函数,这些函数可以被自定义脚本调用来实现更复杂的数据处理逻辑。例如,可以编写脚本来遍历FLV文件的所有帧,提取特定的数据信息,并将其保存或处理。
import flvparse
def analyze_flv(file_path):
# 使用flvparse打开FLV文件
with flvparse.open(file_path) as flv:
for frame in flv:
# 对每一帧进行处理
frame_data = frame.get_data()
# 这里可以添加代码以进行帧数据的分析或提取特定的信息
# 打印帧的类型
print(frame.header.frame_type)
上面的代码段是flvparse自定义脚本的一个非常基础的例子。它通过打开一个FLV文件,遍历每一帧,并打印出每一帧的类型。 flvparse.open 函数用于打开文件, frame.get_data() 方法用于获取帧数据。
6.1.2 插件系统的介绍和开发
除了直接使用脚本来扩展flvparse的功能,flvparse还可能支持插件系统。插件是一种可以被flvparse在运行时动态加载并使用的独立模块,它能够提供额外的功能或改变flvparse的行为。
在开发插件时,需要注意flvparse对插件的接口规范。通常插件需要定义一个入口函数,该函数会在插件加载时被调用。此外,插件需要按照flvparse指定的目录结构放置,以便flvparse能够正确加载和卸载插件。
# 插件目录结构
# /path/to/flvparse/plugins/
# -- myplugin/
# |-- __init__.py
# |-- myplugin.py
# myplugin.py
from flvparse import PluginInterface
def my_plugin_entry():
def my_custom_function(flv):
# 自定义处理FLV文件的逻辑
pass
return my_custom_function
# 在 __init__.py 中注册插件
from .myplugin import my_plugin_entry
# 插件入口点注册
PluginInterface.register_plugin(my_plugin_entry)
在这个示例中,我们创建了一个名为 myplugin 的插件。 my_custom_function 函数是我们提供的自定义逻辑,它可以被flvparse调用。 PluginInterface.register_plugin 方法用于注册这个插件的入口函数。
6.2 flvparse的高级数据处理
6.2.1 数据过滤与提取的高级技巧
在处理大型FLV文件时,往往需要对数据进行过滤和提取,以得到所需的信息。flvparse提供了一些高级的数据处理技巧,这些技巧可以让用户更加精确地获取数据。
例如,flvparse可能支持通过时间戳、帧类型或者数据的特定内容来进行过滤。高级过滤可能需要一些正则表达式或特定的数据处理函数,这取决于flvparse的设计。
import flvparse
import re
def extract_metadata(file_path):
metadata_pattern = re.compile(b'metadata:')
extracted_metadata = []
with flvparse.open(file_path) as flv:
for frame in flv:
# 查看帧数据是否匹配metadata模式
if metadata_pattern.search(frame.get_data()):
extracted_metadata.append(frame.get_data())
return extracted_metadata
在这个示例中,我们尝试提取与“metadata”相关的帧数据。我们定义了一个正则表达式 metadata_pattern 来匹配与“metadata”相关的数据,然后遍历FLV文件中的每一帧,将匹配到的帧数据保存到列表中。
6.2.2 集成外部库以扩展功能
flvparse的设计可能允许集成外部库以实现更复杂的功能。这包括对视频帧的分析、图像处理、音频处理等。例如,可以集成像OpenCV这样的图像处理库,或者像Pillow这样的图像处理库,来对FLV中的视频帧进行分析和处理。
在集成外部库之前,需要先确保外部库已经安装在系统中,并且与flvparse兼容。之后,就可以在脚本中导入外部库,并调用相应的函数来处理数据。
import flvparse
from PIL import Image
def process_video_frames(file_path):
with flvparse.open(file_path) as flv:
for frame in flv:
if frame.header.frame_type == 'video':
frame_data = frame.get_data()
# 使用Pillow处理视频帧
img = Image.open(frame_data)
# 这里可以添加代码处理图像,例如转换格式、尺寸调整等
img.save('processed_frame.jpg')
在这个示例中,我们尝试处理FLV文件中的视频帧。当遇到视频帧时,我们使用Pillow库打开帧数据作为图像,并对其进行了简单的保存操作。如果需要进行更复杂的图像处理,Pillow库提供了广泛的API来进行操作。
通过这些高级技巧和外部库的集成,flvparse的自定义功能能够大幅度地扩展,满足从数据分析到视频处理的各种专业需求。
7. flvparse的性能优化与问题解决
7.1 flvparse的性能调优
7.1.1 性能分析与瓶颈定位
当我们处理大规模的FLV文件或者需要对大量的FLV数据进行分析时,flvparse的性能就显得尤为重要。性能分析和瓶颈定位是优化的第一步。使用flvparse时,可以利用系统的性能分析工具,例如Linux系统中的 perf 或者 top 命令,来监控flvparse的CPU和内存使用情况。
在分析过程中,我们需要注意以下几点: - 查找flvparse在解析文件时是否存在内存泄漏现象。 - 监控flvparse在处理某些特定类型的FLV Tag时是否出现了长时间的延迟。 - 观察flvparse在处理大型文件时的IO操作,判断是否影响了整体性能。
定位瓶颈之后,我们可以通过以下方式对性能进行调优:
# 使用 perf 分析 flvparse 的性能
perf stat flvparse [options] input.flv
7.1.2 针对不同场景的性能优化方法
针对不同处理场景,我们可以通过以下几种方式优化flvparse的性能:
多线程处理 :如果flvparse支持多线程,可以利用这一特性同时处理多个FLV文件或文件内的多个数据块。 减少不必要的数据处理 :分析是否所有输出的数据都是必须的,如果只是需要部分信息,则可以调整flvparse的配置以减少不必要的数据处理。 使用缓存机制 :对于需要反复读取的FLV文件,可以采用缓存机制,减少对磁盘的重复读取,提升数据处理速度。
# 在flvparse的配置文件中启用多线程处理
flvparse --threads=4 [options] input.flv
7.2 常见问题诊断与解决
7.2.1 遇到的问题分类与案例分析
在使用flvparse时可能会遇到各种各样的问题。这些问题可以大致分类为以下几类:
解析错误 :由于FLV文件损坏或flvparse版本与FLV文件格式不兼容导致的解析错误。 运行时错误 :如内存溢出、文件未找到等。 性能问题 :如处理时间过长、系统资源占用高等。
下面是一个解析错误的案例分析:
Error: Invalid FLV header encountered.
这个错误通常表示flvparse在尝试解析一个FLV文件时遇到了无效的文件头。处理此类问题通常需要确认FLV文件是否完整且未损坏。
7.2.2 解决方案与预防措施
针对解析错误,我们可以采取以下预防措施和解决方案:
验证FLV文件完整性 :确保FLV文件没有损坏,可以使用flvparse本身或其它工具进行验证。 更新flvparse :如果是由于flvparse版本过旧,导致无法处理新格式的FLV文件,那么升级到最新版本可能会解决该问题。 检查FLV文件格式 :确认FLV文件的格式与flvparse兼容,例如某些特定的编码或数据格式。
对于运行时错误,解决方案通常包括:
确保足够的权限 :检查是否有足够的权限去读取FLV文件或写入输出文件。 检查命令行参数 :确保所有命令行参数都正确无误,符合flvparse的使用要求。
对于性能问题,通常的预防措施和解决方案包括:
优化输入数据 :如前所述,优化输入FLV文件或调整flvparse的配置以提升性能。 硬件升级 :如果优化操作依然无法满足性能需求,可能需要考虑升级硬件设备。
通过上述章节的深入探讨,我们可以看到flvparse作为一款强大的FLV分析工具,其功能不仅仅局限于基础的数据解析。通过对性能优化与问题解决的深入分析,flvparse的使用者可以更加高效地处理FLV数据,并在遇到问题时迅速定位并解决。
本文还有配套的精品资源,点击获取
简介:FLV是一种用于网络流媒体的视频格式。本文介绍了一种名为“flvparse”的小工具,用于解析FLV文件的二进制数据。工具展示了FLV文件的标签结构,包括音频、视频和脚本数据,以及如何通过命令行运行解析,从而帮助开发者更直观地理解FLV文件内容。介绍了flvparse在视频播放故障排查、内容分析、格式转换和流媒体研究等场景的应用。
本文还有配套的精品资源,点击获取