侧边栏

计算机多媒体技术

发布于 | 分类于 杂项|本文包含AIGC内容

本来是想学习一下WebRTC的,但是发现我好像还得先了解一下多媒体技术的基础知识,先学一下。

多媒体技术是将文字、图形、图像、音频、视频等多种媒体信息进行有效组合,并能够对这些媒体进行获取、编辑、显示、存储和通信等加工处理的综合技术。

多媒体技术的四大主要特征:

  • 集成性: 将各种媒体信息和处理这些信息的设备或工具进行有效集成。
  • 多样性: 处理的媒体信息种类繁多,例如文字、图形图像、声音和视频信息等。
  • 交互性: 用户可以与计算机的多种信息媒体进行交互操作。
  • 实时性: 对处理速度有较高要求,以确保音频、视频、动画等媒体信息的流畅播放。

多媒体计算机系统包括硬件系统和软件系统两大部分。

  • 硬件系统主要包括计算机主要硬件配置、各种外部设备以及相关的多媒体接口。
  • 软件系统包括多媒体操作系统、驱动软件、多媒体应用软件、多媒体创作工具等。

多媒体数据压缩和编码:由于多媒体信息数字化后的数据量非常大,因此需要使用数据压缩技术来减少信息的数据量,以便于存储和传输。

常用的多媒体文件编码格式包括:

  • 图像文件格式:BMP、GIF、JPEG、PNG、PSD 等。
  • 音频文件格式:WAV、MID、MP3、WMA 等。
  • 动画文件格式:GIF、FLIC、SWF 等。
  • 视频文件格式:AVI、MPEG(包括 MPEG-1、MPEG-2 和 MPEG-4)、MOV、WMV、RM/RMVB、FLV、DIVX 等。

图像

图片是如何通过相机拍摄,然后在电脑上展示的?

光学成像

镜头由多片玻璃透镜组成,通过调节光圈大小控制进光量,将外界光线聚焦到传感器上

数字传感器由数百万个光电二极管(像素)组成,每个像素感光并转换光信号为电信号,不同光线强度产生不同电信号强度

图形数据处理

模数转换器将模拟电信号转为数字信号,每个像素被编码为具体的颜色和亮度值,全部的像素点就组成了图像

然后需要进行图像处理,包括

  • 降噪处理,减少图像杂点
  • 色彩校准和白平衡调整
  • 对比度和饱和度优化

在图像存储时,除了保存原本的图像像素数据之外,还会保存拍摄参数(快门速度、光圈等)和拍摄时间、GPS信息等元数据(因此原图可能会存在隐私泄露风险)

分辨率

指组成图片的长宽像素数量,比如1920*1080

分辨率决定了图像画面细节的精细程度,通常情况下,分辨率越高,所包含的像素就越多,画面就越清晰

图像格式与压缩

格式选择在图像创建和导出时决定,由用户或软件选择。不同的格式使用了不同的压缩算法。

图像压缩,主要是为了减少文件大小

有损压缩

图片有损压缩是一种在压缩过程中通过丢弃部分图像数据来减少文件大小的技术。它允许一定程度的质量损失,以换取更高的压缩率。

有损压缩特别适用于自然图像(如照片),因为人眼对图像中的某些细节不敏感,因此这些细节可以被去除,而不会显著影响感知质量。

其原理如下

  • 利用了人眼对细节、颜色和亮度变化的不敏感特性,降低颜色分辨率,忽略不被察觉的细节
  • 数据简化与变换,使用数学变换(如离散余弦变换或小波变换)将图像转换为频域,然后在这个域中丢弃或量化不重要的高频成分。
  • 将图像数据分解为不同的频率成分后,采用量化方法降低数据的精度。例如,将接近的颜色值合并为单一值。
  • 对剩余的低频数据使用熵编码(如霍夫曼编码或算术编码)进一步压缩

JPEG是常见的图片压缩算法,压缩率可达90%,支持多级压缩比,可以显著减少文件大小,便于存储和传输。

无损压缩

无损压缩算法是一类在数据压缩过程中确保数据不丢失的算法。这意味着在对数据进行压缩后,可以完全还原出原始数据,常见无损压缩场景有如gzip、zip等。

常见的无损压缩算法有

  • Run-Length,游程长度编码,专门针对重复数据的压缩。它通过记录重复数据的重复次数来减少数据的存储量,比如AAAAAABBBCCDAA会被压缩为6A3B2C1D2A
  • Lempel-Ziv,改进自 LZ78,动态构建字典并使用编码替代数据流中的模式
  • Huffman,基于字符或符号的出现频率构造二进制编码。频率越高的符号使用的编码越短。

在图像文件的压缩上,无损压缩会保留全部原始图像信息,因此压缩效果比较有限。

PNG是常见的无损压缩图片格式,其使用的是结合了 LZ77 和 Huffman 编码的DEFLATE压缩算法,通过重复模式匹配和频率编码进行压缩

此外的无损压缩图片格式

  • BMP,原始 BMP 通常未压缩,但部分版本使用 RLE 压缩。
  • TIFF,支持多种压缩方法,包括无损(如 LZW、PackBits),常用于医学影像和档案等高分辨率图片
  • GIF,使用 LZW 算法进行压缩,支持256 色调色板和简单透明
  • WebP无损模式,Google 开发的现代图像格式,兼具有损和无损模式,无损模式基于帧预测和熵编码,压缩率高
  • FLIF,次世代无损图像格式,压缩率高于 PNG 和 WebP,支持渐进式显示,目前尚未被广泛使用

图像传输

PTP (Picture Transfer Protocol) 和 MTP (Media Transfer Protocol) 是两种用于数字设备间传输媒体文件的重要协议

PTP:该协议比较老旧了,主要用于数码相机和计算机间的图像传输,传输过程支持元数据传输,直接支持相机拍摄控制

MTP:基于PTP协议扩展,更广泛支持各类媒体文件,支持更复杂的文件管理功能,传输过程更安全、更高效。

HTTP:如果是通过互联网传输图片,那么大概率用到的是HTTP协议。

图像显示

显示器的LCD/LED屏幕由像素矩阵组成,每个像素由红绿蓝三色子像素构成,调节三色亮度产生最终颜色

在接收到图像渲染的任务时,显卡负责解码图像文件,还原图像像素信息,控制每个像素的颜色和亮度,最终在屏幕上将图片展示出来。

不同的显示器对于图片的呈现效果有差异,需要校准显示器色彩配置,确保图像颜色还原度。

音频

我们对着手机说话,声音是如何被远在几千公里外的其他人听到呢?这个过程涉及到硬件、软件和网络的过程,下面介绍一下整个过程的大致流程。

麦克风采集声音

手机的麦克风是将声音信号(声波)转换为电信号的关键硬件。

声音本质上是空气中的振动,当我们说话时,声波振动麦克风中的振膜(通常是电容式或动圈式麦克风)。这种振动会改变麦克风中的电信号,从而捕捉声音。

麦克风生成的是模拟电信号,手机会通过**模数转换器(ADC, Analog-to-Digital Converter)**将这个模拟信号转换成数字信号。

该转换器以一定的采样率(如44.1kHz或48kHz)和量化深度(如16位、24位)来捕获声音的数字化表示。

  • 采样率:每秒采集声音信号的次数,采样率越高,捕捉的声音细节越多。
  • 量化深度:表示每个采样点用多少位数字来描述,量化深度越高,音频的动态范围越大。

音频信号处理

手机内置的音频处理芯片或数字信号处理器(DSP)会对采集到的声音进行处理,这包括:

  • 降噪:移除环境中的背景噪音,确保声音更加清晰。
  • 回声消除:避免麦克风拾取到扬声器的声音,防止通话中的回声问题。
  • 自动增益控制(AGC):根据声音的大小动态调整输入信号的增益,确保声音不会过大或过小。

滤波和傅里叶变换等工作主要是在音频信号被数字化之后的数字信号处理阶段进行,它们通过去除不需要的频率成分、分析音频信号的频率成分等技术来提高音质、减少噪音,并确保更好的音频体验。

  • 滤波的目的是消除不需要的频率成分,比如背景噪音或高频干扰
  • 傅里叶变换的作用是将时间域中的音频信号转换到频率域,以分析和处理不同频率成分

这些处理步骤提高了音质,让我们讲话的声音更加清晰和自然。

音频压缩

为了减少数据量,手机在存储或传输之前会对声音进行压缩

这通常通过使用音频编解码器(如AAC、Opus等)来完成,它们能够在保持较高音质的同时压缩数据,以便节省带宽或存储空间。

音频压缩的原理是通过去除冗余和不可感知的信息,在尽量不影响人耳感知的情况下减少音频数据的体积。音频压缩可以分为两大类:有损压缩和无损压缩。

无损压缩

无损压缩的目标是在不丢失任何音频信息的情况下减少文件大小,压缩后的数据解压缩时可以还原到与原始音频完全相同的数据。工作原理:

  • 预测编码:无损压缩使用算法分析音频信号的冗余,找到相似的样本点,然后记录差异而不是记录每个样本。例如,相邻的样本点在波形上往往非常相近,无损压缩可以记录差值,而不是每个样本的绝对值。
  • 熵编码:像是Huffman编码或算术编码这样的熵编码技术,根据音频信号中样本值出现的频率来进行编码。常见的样本值会使用较短的编码,不常见的样本则使用较长的编码,从而减少整体文件大小。

常见的无损音频压缩格式包括FLAC、ALAC(苹果无损)、WAV(无损未压缩)等。

有损压缩

有损压缩则通过丢弃一些人耳不容易察觉到的信息,实现更高的压缩比。这类压缩通常用于音乐和语音通话,因为它能大幅度减小文件大小,且对音质影响较小。

  • 心理声学模型:有损压缩算法利用了人耳对不同频率声音敏感度的差异。人耳在某些频率上较为敏感,而在其他频率上的感知能力较弱,比如20Hz以下或16kHz以上的声音不易被感知,算法会优先移除这些频率范围内的信息。
  • 掩蔽效应:如果一个强音频信号存在,它会掩盖临近频率的较弱信号。有损压缩算法可以利用这一特性,丢弃被掩蔽的声音。
  • 变换编码(Transform Coding):音频信号首先通过傅里叶变换或离散余弦变换(DCT)转换为频率域。通过这种频率分析,可以识别并压缩不重要或冗余的频率信息。常用的变换编码是MDCT(Modified Discrete Cosine Transform),它能够有效分割音频信号的频谱,并进行压缩。
  • 量化:有损压缩通过降低数据的精度来减少数据量。量化可以减少每个采样点的位数,尤其是那些对音质影响较小的频率成分。
  • 熵编码:与无损压缩类似,使用熵编码(如Huffman编码)对量化后的数据进行编码,进一步减少文件大小。

常见的有损压缩格式包括MP3、AAC、Opus等。

音频实时传输

这种实时传输语音消息,主要用于语音电话、直播等场景

音频数据包

为了能够在网络上传输,音频数据需要被分成小块(数据包),并且添加控制信息,以确保每个包能够正确传递到接收方。通常,音频数据会结合网络协议(如RTP、UDP、TCP)进行打包。

  • RTP(实时传输协议):在实时语音通话中,RTP是常用的协议,它负责管理音频数据包的顺序和时间戳,以保证音频能以正确的顺序和时间间隔播放。
  • UDP vs TCP:
    • UDP(用户数据报协议):实时音频传输中常用的协议,因为它的低延迟特性。尽管UDP不保证数据包的可靠性(可能会丢包或乱序),但它适用于实时应用(如语音通话),因为稍微丢失一些数据对音质影响不大。
    • TCP(传输控制协议):TCP则确保数据包的可靠性和顺序,但在实时性要求高的场景中(如语音通话)延迟会较大,因此通常用于非实时应用(如下载音乐)。

音频数据打包后,通过网络协议栈进行传输。典型的网络传输使用以下协议:

  • IP(Internet Protocol):负责将音频数据包从发送方传递到接收方的网络设备。每个数据包都有源地址和目标地址,IP协议确保数据包通过互联网的路由器和交换机传输到正确的目的地。
  • NAT穿越与STUN/TURN:在点对点通信中,如果双方设备都位于防火墙或NAT后,微信等应用会使用STUN(Session Traversal Utilities for NAT)或TURN(Traversal Using Relays around NAT)服务器来帮助建立连接,或者充当中继服务器。

在实时音频传输(如语音通话)中,系统必须控制传输过程中的延迟,以确保通话的实时性。为此,通常会使用一些技术:

  • 抖动缓冲区(Jitter Buffer):由于网络传输的波动,音频数据包可能会以不同的时间间隔到达,抖动缓冲区会暂时存储并重新调整数据包的播放时间,以确保音频流的平稳播放。
  • 网络自适应技术:当网络质量变差时,音频编解码器会动态调整比特率,减少数据量,以适应带宽的变化。

为了确保语音通话或实时音频传输的质量,网络层面上常用一些**服务质量(QoS)**技术,优先处理音频和视频数据包,减少延迟和丢包率。这在实时通讯应用中尤为重要。

解码音频数据

在接收端,音频数据包通过网络传递到目标设备,并进行逆向的处理:

  • 解包:接收方的设备使用RTP协议或UDP/TCP协议来解包数据。RTP会利用包中的序列号和时间戳来确保数据包按正确的顺序播放,并按照原始时间间隔还原音频。
  • 丢包处理:在UDP传输的情况下,可能会有一些音频包丢失,接收端需要使用插值或其他方法来平滑丢失的数据包,尽可能减少音质的影响。

接收到的数据包中包含压缩的音频数据,接收方需要通过解码器将音频数据解压成原始的音频信号。解码过程通常使用与发送端相同的编码格式,如Opus、AAC等。

例如,在语音通话中,接收方的设备会通过Opus解码器将压缩的音频数据解压成可以播放的语音信号。

音频文件传输

另外一种场景是先采集音频,本地组装成音频文件,再通过网络传输,这种场景常见于发送语音留言消息、录音文件等。

下面的代码演示了通过MediaRecorder进行本地录音和传输文件的过程,整个过程不涉及到复杂的音频数据块传输,而是通过HTTP直接上传文件。

html
<button id="startRecord">开始录音</button>
<button id="stopRecord" disabled>停止录音</button>

<script>
let mediaRecorder;
let audioChunks = [];

navigator.mediaDevices.getUserMedia({ audio: true })
    .then(function(stream) {
    mediaRecorder = new MediaRecorder(stream);

    mediaRecorder.onstart = function() {
        audioChunks = [];
    };

    mediaRecorder.ondataavailable = function(event) {
        audioChunks.push(event.data);
    };

    mediaRecorder.onstop = function() {
        // 可以将audioBlob作为文件上传到服务器
        const audioBlob = new Blob(audioChunks, { type: 'audio/wav' }); 
        const formData = new FormData();
        formData.append('audioFile', audioBlob, 'recording.wav');
        fetch('/upload', {
            method: 'POST',
            body: formData
        })
    };
    })
    .catch(function(err) {
        console.error('无法获取麦克风: ', err);
    });

const startButton = document.getElementById('startRecord');
const stopButton = document.getElementById('stopRecord');

startButton.addEventListener('click', () => {
    mediaRecorder.start();
});

stopButton.addEventListener('click', () => {
    mediaRecorder.stop();
});
</script>

如果需要实时传输数据,在ondataavailable的回调中实时发送数据应该就可以。

播放音频

在播放音频数据时,数据会被送入音频输出设备,如扬声器或耳机。

此时,数字音频信号通过**数模转换器(DAC,Digital-to-Analog Converter)**转化为模拟信号,驱动扬声器发出声音,最终用户能够听到传输过来的音频。

通过这些步骤,语音或音频能够高效地在互联网上传输并还原为可听的声音。

视频

参考: https://help.aliyun.com/zh/vod/product-overview/terms-1,这篇文章介绍了很多概念

视频采集

视频是由连续的图像帧组成,因此视频采集跟图像采集的过程很相似。

为了让视频画面平滑,需要在相邻帧之间保持连续性,人眼具有视觉暂留特性,当帧率超过24fps时,播放的静态图片会感知为连续运动,常见帧率有24fps(电影)、30fps(普通视频)、60fps(高帧率视频)。

视频编码格式

虽然视频确实是由连续帧组成,但它的存储和处理方式与简单的图片序列有很大不同,是一个更复杂和高效的系统。

在实际生产中,视频文件的大小通常远小于同数量图片的总和,这是因为

  • 利用了帧间的相似性

  • 只存储发生变化的部分

  • 使用时间压缩技术

  • 通过预测减少数据冗余

简单来说,视频编码(Codec)就是为了压缩视频数据而做的一类压缩算法,通常这种压缩属于有损数据压缩。

常见的视频编码方式有:

  • H.264/AVC (最广泛使用)

    • 特点:压缩效率高、兼容性最好、硬件解码支持广泛、使用时需要版权费用

    • 应用场景:网络视频平台、高清电视、蓝光光盘、视频会议

  • H.265/HEVC

    • 特点:比H.264提高50%压缩率、支持8K分辨率、需要更多计算资源、使用时需要版权费用

    • 应用场景:超高清视频、流媒体服务、VR视频

  • MPEG系列,

    • 特点:由ISO(国际标准化组织)下属的MPEG(动态图像专家组)主导
    • 应用场景:VCD、DVD和网络传输、广播、媒体存储
  • VP8/VP9 (Google开发)

    • 特点:开源免费、压缩效率接近H.264/H.265、WebM格式的标准编码

    • 应用场景:YouTube、网页视频、Chrome浏览器

  • AV1 (Alliance for Open Media)

    • 特点:完全开源免费、比H.265压缩率提升30%、支持更高分辨率

    • 应用场景:新一代流媒体、Netflix, YouTube等平台、可能是未来的网络视频标准

视频转码(Video Transcoding)是指将已经压缩编码的视频码流转换成另一个视频码流,以适应不同的网络带宽、不同的终端处理能力和不同的用户需求

视频封装格式

播放器在播放视频文件时,除了帧图像之外,还有包括音频、字幕等信息。实际上播放器处理的是多媒体容器(Multimedia Container),也称封装格式(Format)。

封装格式是将已编码压缩好的视频轨道、音频轨道和元数据(视频基本信息如标题、字幕等)按照一定的格式规范,打包放到一个文件中,形成特定文件格式的视频文件,方便播放软件播放。

一般来说,视频文件的后缀名就是它的封装格式,比如将H.264编码的视频和MP3编码的音频按照MP4的标准封装起来,就是我们看到的MP4格式视频。

封装格式并不影响画质,它只负责把内部的视频轨和音频轨集成在一起,并不对内容造成影响。

编码格式封装格式的关系好比酒与酒瓶的关系,编码格式就像酒瓶里的酒,是视频的核心内容,封装格式就像酒瓶,它只是负责把内部的视频轨、音频轨、字幕轨集成在一起。

封装格式主要分为两大类:面向存储的和面向流媒体的。

  • 面向存储的,常见的有AVI、ASF(WMA/WMV)、MP4、MKV、RMVB(RM/RA)等;
  • 面向流媒体的,常见的有FLV、TS(需要配合流媒体网络传输协议,如HLS、RTMP等),MP4也支持流媒体方式(配合HTTP等)。

视频转封装指的是将视频或音频的封装格式进行转换,如将AVI的视频转换为MP4,其间并不会进行音视频的编码和解码工作,而是直接将视频和音频压缩码流从一种封装格式文件中获取出来然后打包成另一种封装格式的文件

流媒体

封装格式只决定了视频文件最终包含的内容格式,如果要将视频文件通过网络进行分发和传输,就需要用到传输协议。传输协议是指在网络上进行音视频传输和播放时使用的一种规则或标准,用于保证音视频数据的有效性、完整性和实时性。

传输协议在传输视音频数据的同时,也会传输一些信令数据,用于控制播放、调节网络状态等。常见的传输协议有HTTP、RTMP、RTSP、HLS等。

现代的浏览器支持****渐进式下载**流媒体播放****,这使得视频可以在未完全下载的情况下开始播放,比如HTML的<video> 元素在播放视频时可以部分加载并播放。

渐进式下载

渐进式下载(Progressive Download)这种模式下,视频文件以文件的形式通过 HTTP 下载,但浏览器会开始预加载文件的一部分内容,并且在下载部分内容后就可以开始播放。视频的后续部分会继续在后台下载。

这种方式并不是真正的流媒体播放,因为它没有按需传输视频内容,也没有根据网络状况动态调整视频质量,但它提供了类似的体验,尤其对于较小的视频文件。

流媒体播放

流媒体技术是通过根据网络带宽动态调整媒体内容的比特率,确保流畅播放的同时提供高质量的体验。

流媒体技术允许根据网络带宽动态调整视频质量,支持实时内容传输(如直播),并减少了用户端的缓存占用。使用这些协议时,浏览器只下载当前播放所需的部分内容,而不是整个文件。

主流的自适应流媒体协议包括HLS(HTTP Live Streaming)或DASH(Dynamic Adaptive Streaming over HTTP)等

**HLS **

HLS (HTTP Live Streaming)是目前最广泛使用的流媒体协议之一,由苹果公司(Apple)开发,特别适合移动设备和跨平台应用,iOS、macOS系统原生支持,很多浏览器和播放器也支持。

它基于HTTP协议工作,通过将视频文件分割成小的、几秒钟的片段,然后根据客户端的网络条件,动态选择合适的片段播放。

  • 优点
    • 支持自适应比特率。
    • 可以与CDN(内容分发网络)无缝集成。
    • 支持加密和DRM(数字版权管理)。
  • 缺点:延迟较高(通常在10秒或更长时间),不太适合低延迟的应用场景。

m3u8和HLS中一个比较重要的概念,是一种文本文件格式,用于描述多媒体播放列表,

  • 提供媒体文件的索引和组织
  • 记录视频/音频分片的位置和顺序

下面是一个典型的m3u8文件内容,其中的segment0.tssegment0.ts等就是切片

#EXTM3U
#EXT-X-PLAYLIST-TYPE:VOD
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-TARGETDURATION:10

#EXTINF:9.009,
segment0.ts
#EXTINF:9.009,
segment1.ts
#EXTINF:9.009,
segment2.ts
#EXT-X-ENDLIST

将一个本地封装格式为mp4的视频,使用HLS协议播放,可以通过ffmpeg来实现

ffmpeg -i input.mp4 -c:v libx264 -crf 21 -preset medium -c:a aac -b:a 128k -hls_time 10 -hls_list_size 0 -hls_segment_filename "output_%03d.ts" output.m3u8

命令解释:

  • -i input.mp4:输入文件
  • -c:v libx264:视频编码器
  • -crf 21:视频质量
  • -preset medium:编码速度和压缩率平衡
  • -c:a aac:音频编码
  • -hls_time 10:每个分片时长10秒
  • -hls_list_size 0:保留所有分片
  • -hls_segment_filename:ts文件命名模式
  • output.m3u8:生成的播放列表文件

**MPEG-DASH **

MPEG-DASH(Dynamic Adaptive Streaming over HTTP) 是由国际标准化组织(ISO)开发的一种开放标准的流媒体协议,不依赖任何特定的平台或设备。与HLS类似,它通过将视频分割为多个片段,并根据网络条件选择合适的比特率流进行播放。

几乎所有现代浏览器都支持,尤其是在HTML5播放器中有良好的兼容性。

  • 优点
    • 开放标准,设备和平台无关。
    • 支持多种DRM方案。
    • 低延迟性能比HLS好。
  • 缺点:不像HLS那样在苹果设备上得到原生支持。

WebRTC

WebRTC (Web Real-Time Communication)由Google(主导开发)虽然不完全属于传统的自适应流媒体技术,但它支持点对点的实时音视频通信,特别适用于视频通话、视频会议和其他实时互动场景。WebRTC通过根据网络状态调整视频和音频质量,实现自适应的实时流传输。

  • 优点
    • 支持低延迟的实时传输。
    • 不需要插件,浏览器原生支持。
    • 点对点传输,不依赖服务器转发,节约带宽。
  • 缺点:对于大规模的直播应用,管理复杂性较高。

SRT (Secure Reliable Transport)

SRT 是基于UDP的视频传输协议,主要用于在不可靠的网络条件下传输高质量的直播视频流,特别是延迟敏感的内容。它通过安全的方式确保视频流传输的可靠性,同时支持自适应比特率调整。

SRT 广泛用于直播平台、云服务和一些高端流媒体系统。

  • 优点
    • 专为低延迟传输设计。
    • 提供安全的传输层,支持加密。
    • 对不稳定的网络有良好适应性。
  • 缺点:相对较新的协议,主流支持还不如HLS和DASH广泛。

总结

  • HLSMPEG-DASH 是当前最常用的自适应流媒体协议。
  • HLS 在苹果设备上有优势,而 MPEG-DASH 是跨平台的开放标准。
  • WebRTC 则更适合实时互动应用,特别是视频通话和会议。
  • SRT 是对低延迟和安全性要求较高场景的首选。

你要请我喝一杯奶茶?

版权声明:自由转载-非商用-保持署名和原文链接。

本站文章均为本人原创,参考文章我都会在文中进行声明,也请您转载时附上署名。