視頻直播技術(shù)干貨(十二):從入門到放棄,快速學(xué)習(xí)Android端直播技術(shù)
Posted on 2024-10-17 11:10 Jack Jiang 閱讀(89) 評論(0) 編輯 收藏本文由陸業(yè)聰分享,原題“一文掌握直播技術(shù):實(shí)時(shí)音視頻采集、編碼、傳輸與播放”,本文進(jìn)行了排版和內(nèi)容優(yōu)化。
1、引言
從游戲、教育、電商到娛樂,直播技術(shù)的應(yīng)用場景無處不在。隨著移動(dòng)端的網(wǎng)速越來越快,直播技術(shù)的普及和發(fā)展將更加迅速。
本文詳細(xì)介紹了Android端直播技術(shù)的全貌,涵蓋了從實(shí)時(shí)音視頻采集、編碼、傳輸?shù)浇獯a與播放的各個(gè)環(huán)節(jié)。文章還探討了直播中音視頻同步、編解碼器選擇、傳輸協(xié)議以及直播延遲優(yōu)化等關(guān)鍵問題。希望本文能為你提供有關(guān)Andriod端直播技術(shù)的深入理解和實(shí)踐指導(dǎo)。

- 移動(dòng)端IM開發(fā)入門文章:《新手入門一篇就夠:從零開發(fā)移動(dòng)端IM》
- 開源IM框架源碼:https://github.com/JackJiang2011/MobileIMSDK(備用地址點(diǎn)此)
2、系列文章
本文是系列文章中的第 11 篇,本系列總目錄如下:
- 《視頻直播技術(shù)干貨(一):揭秘百萬級(jí)粉絲互動(dòng)的Facebook實(shí)時(shí)視頻直播》
- 《視頻直播技術(shù)干貨(二):P2P技術(shù)如何將實(shí)時(shí)視頻直播帶寬降低75%?》
- 《視頻直播技術(shù)干貨(三):實(shí)時(shí)直播答題系統(tǒng)的實(shí)現(xiàn)思路與技術(shù)難點(diǎn)分享》
- 《視頻直播技術(shù)干貨(四):首次披露快手是如何做到百萬觀眾同場看直播仍能秒開且不卡頓的?》
- 《視頻直播技術(shù)干貨(五):七牛云使用QUIC協(xié)議實(shí)現(xiàn)實(shí)時(shí)視頻直播0卡頓》
- 《視頻直播技術(shù)干貨(六):新浪微博實(shí)時(shí)直播答題的百萬高并發(fā)架構(gòu)實(shí)踐》
- 《視頻直播技術(shù)干貨(七):實(shí)時(shí)視頻直播首屏耗時(shí)400ms內(nèi)的優(yōu)化實(shí)踐》
- 《視頻直播技術(shù)干貨(八):淘寶高清、低延時(shí)的實(shí)時(shí)視頻直播技術(shù)解密》
- 《視頻直播技術(shù)干貨(九):千萬級(jí)直播系統(tǒng)后端架構(gòu)設(shè)計(jì)的方方面面》
- 《視頻直播技術(shù)干貨(十):一文讀懂主流視頻直播系統(tǒng)的推拉流架構(gòu)、傳輸協(xié)議等》
- 《視頻直播技術(shù)干貨(十一):超低延時(shí)視頻直播技術(shù)的演進(jìn)之路》
- 《視頻直播技術(shù)干貨(十二):從入門到放棄,快速學(xué)習(xí)Android端直播技術(shù)》(* 本文)
3、知識(shí)準(zhǔn)備
音視頻技術(shù)的門檻一直以來都相對較高,如果你對音視頻相關(guān)技術(shù)的理論知識(shí)了解不多,建議務(wù)必優(yōu)先閱讀這幾篇零基礎(chǔ)音視頻入門文章:
- 《零基礎(chǔ),史上最通俗視頻編碼技術(shù)入門》
- 《愛奇藝技術(shù)分享:輕松詼諧,講解視頻編解碼技術(shù)的過去、現(xiàn)在和將來》
- 《零基礎(chǔ)入門:實(shí)時(shí)音視頻技術(shù)基礎(chǔ)知識(shí)全面盤點(diǎn)》
- 《快速掌握11個(gè)視頻技術(shù)相關(guān)的基礎(chǔ)概念》
另外兩篇入門提納式的文章也可以一并閱讀:
以上資料學(xué)習(xí)完成后,再回頭來閱讀本篇效果會(huì)更好一點(diǎn)。
4、實(shí)時(shí)音視頻采集
4.1音視頻采集設(shè)備與API
在 Android 設(shè)備中,音視頻的采集主要依賴于攝像頭和麥克風(fēng)這兩個(gè)硬件設(shè)備。攝像頭負(fù)責(zé)圖像的采集,麥克風(fēng)則負(fù)責(zé)音頻的采集。
為了調(diào)用這兩個(gè)設(shè)備,Android 提供了 Camera API 和 AudioRecord API。通過這兩個(gè) API,我們可以方便地控制設(shè)備,獲取音視頻數(shù)據(jù)。
以下是具體實(shí)踐步驟。
1)使用 Camera 或 Camera2 API 來調(diào)用攝像頭:
// Camera API
Camera camera = Camera.open();
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(width, height);
camera.setParameters(parameters);
camera.setPreviewCallback(previewCallback);
camera.startPreview();
// Camera2 API
CameraManager cameraManager = (CameraManager) getSystemService(Context.CAMERA_SERVICE);
String cameraId = cameraManager.getCameraIdList()[0];
CameraCharacteristics characteristics = cameraManager.getCameraCharacteristics(cameraId);
StreamConfigurationMap map = characteristics.get(CameraCharacteristics.SCALER_STREAM_CONFIGURATION_MAP);
Size[] previewSizes = map.getOutputSizes(SurfaceTexture.class);
// 選擇合適的預(yù)覽尺寸
cameraManager.openCamera(cameraId, stateCallback, null);
2)使用 AudioRecord API 來調(diào)用麥克風(fēng):
int bufferSize = AudioRecord.getMinBufferSize(sampleRate, channelConfig, audioFormat);
AudioRecord audioRecord = new AudioRecord(MediaRecorder.AudioSource.MIC, sampleRate, channelConfig, audioFormat, bufferSize);
audioRecord.startRecording();
4.2音視頻采集參數(shù)設(shè)置
音視頻采集的質(zhì)量和流暢度,很大程度上取決于采集參數(shù)的設(shè)置。這些參數(shù)包括分辨率、幀率和碼率等。
具體是:
- 1)分辨率:決定了圖像的清晰度。高分辨率可以得到更清晰的圖像,但也會(huì)增加數(shù)據(jù)量,可能導(dǎo)致網(wǎng)絡(luò)傳輸壓力增大;
- 2)幀率:決定了視頻的流暢度。高幀率可以得到更流暢的視頻,但同樣會(huì)增加數(shù)據(jù)量;
- 3)碼率:決定了音視頻數(shù)據(jù)的壓縮程度。高碼率可以得到更高質(zhì)量的音視頻,但也會(huì)增加數(shù)據(jù)量。
在設(shè)置音視頻采集參數(shù)時(shí),需要根據(jù)網(wǎng)絡(luò)狀況和設(shè)備性能,做出合適的折衷。
以下是具體實(shí)踐步驟。
1)設(shè)置攝像頭的分辨率和幀率:
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(width, height);
parameters.setPreviewFrameRate(frameRate);
camera.setParameters(parameters);
2)設(shè)置 AudioRecord 的采樣率、聲道數(shù)和音頻格式:
int sampleRate = 44100;
int channelConfig = AudioFormat.CHANNEL_IN_MONO;
int audioFormat = AudioFormat.ENCODING_PCM_16BIT;
4.3音視頻同步與時(shí)間戳處理
在直播中,音視頻同步是一個(gè)重要的問題。
為了實(shí)現(xiàn)同步,我們需要為每幀音視頻數(shù)據(jù)添加時(shí)間戳。時(shí)間戳記錄了數(shù)據(jù)的采集時(shí)間,可以用來調(diào)整播放順序,保證音視頻的同步。在解碼和播放時(shí),播放器會(huì)根據(jù)時(shí)間戳,正確地排列和播放音視頻數(shù)據(jù)。
為了處理視頻幀數(shù)據(jù)和時(shí)間戳,我們需要將采集到的音視頻幀數(shù)據(jù)和對應(yīng)的時(shí)間戳封裝成一個(gè)數(shù)據(jù)結(jié)構(gòu),然后將這個(gè)結(jié)構(gòu)傳遞給編碼器和傳輸模塊。
以下是一個(gè)簡單的處理方法。
1)首先,定義一個(gè)數(shù)據(jù)結(jié)構(gòu)來保存音視頻幀數(shù)據(jù)和時(shí)間戳:
public class FrameData {
public byte[] data;
public long timestamp;
public FrameData(byte[] data, long timestamp) {
this.data = data;
this.timestamp = timestamp;
}
}
2)在攝像頭的預(yù)覽回調(diào)中添加時(shí)間戳:
camera.setPreviewCallback(new Camera.PreviewCallback() {
@Override
public void onPreviewFrame(byte[] data, Camera camera) {
long timestamp = System.nanoTime();
// 處理視頻幀數(shù)據(jù)和時(shí)間戳
FrameData frameData = new FrameData(data, timestamp);
// 將 frameData 傳遞給編碼器和傳輸模塊
}
});
3)在 AudioRecord 的錄音循環(huán)中添加時(shí)間戳:
while (isRecording) {
long timestamp = System.nanoTime();
int bytesRead = audioRecord.read(buffer, 0, bufferSize);
// 處理音頻幀數(shù)據(jù)和時(shí)間戳
FrameData frameData = new FrameData(Arrays.copyOf(buffer, bytesRead), timestamp);
// 將 frameData 傳遞給編碼器和傳輸模塊
}
4)在編碼器和傳輸模塊中,根據(jù)FrameData對象的時(shí)間戳來處理音視頻幀數(shù)據(jù)。
例如,在編碼時(shí),將時(shí)間戳作為編碼后的音視頻數(shù)據(jù)的顯示時(shí)間;在傳輸時(shí),根據(jù)時(shí)間戳來調(diào)整發(fā)送順序和發(fā)送速度。
這樣,在解碼和播放時(shí),播放器可以根據(jù)時(shí)間戳正確地排列和播放音視頻數(shù)據(jù),實(shí)現(xiàn)同步。
5、音頻編碼
5.1音頻編碼格式對比
常見的音頻編碼格式有 AAC 和 Opus 等。AAC 具有較高的編碼效率,而 Opus 則在實(shí)時(shí)通信中表現(xiàn)更優(yōu)。

具體是:
- 1)AAC編碼格式:適用于非實(shí)時(shí)通信領(lǐng)域,如音樂、廣播、視頻等,具有較高的編碼效率和廣泛的設(shè)備兼容性,但在實(shí)時(shí)通信中的延遲優(yōu)化較弱;
- 2)Opus編碼格式:適用于實(shí)時(shí)通信領(lǐng)域,如VoIP、在線會(huì)議、游戲語音等,具有高音質(zhì)、低延遲和強(qiáng)網(wǎng)絡(luò)適應(yīng)性,但設(shè)備兼容性相對不如AAC。
5.2在Android中實(shí)現(xiàn)音頻編碼
在 Android 中實(shí)現(xiàn)音頻編碼,可以使用 Android 提供的 MediaCodec 類。MediaCodec 支持多種音頻編碼格式,如 AAC 和 Opus 等。要選擇合適的編碼格式,可以參考以下步驟。
1)創(chuàng)建一個(gè) MediaCodec 編碼器實(shí)例:
MediaCodec audioEncoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_AUDIO_AAC);
2)配置編碼器參數(shù):
MediaFormat audioFormat = MediaFormat.createAudioFormat(MediaFormat.MIMETYPE_AUDIO_AAC, sampleRate, channelCount);
audioFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
audioFormat.setInteger(MediaFormat.KEY_AAC_PROFILE, MediaCodecInfo.CodecProfileLevel.AACObjectLC);
audioEncoder.configure(audioFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
3)開始編碼:
audioEncoder.start();
6、視頻編碼
6.1視頻編碼格式對比
常見的視頻編碼格式有 H.264、H.265 和 VP8 等。H.264 是當(dāng)前最常用的編碼格式,而 H.265 和 VP8 則在特定場景下有更好的性能。

具體是:
- 1)H.264編碼格式:適用于視頻會(huì)議、網(wǎng)絡(luò)直播、視頻分享等場景,具有較高的壓縮效率和廣泛的設(shè)備兼容性,但壓縮效率相比H.265較低;
- 2)H.265編碼格式:適用于4K、8K超高清視頻、虛擬現(xiàn)實(shí)等需要高分辨率和高畫質(zhì)的場景,具有極高的壓縮效率,但編解碼復(fù)雜度高,需要更強(qiáng)的計(jì)算能力,且設(shè)備兼容性相對不如H.264;
- 3)VP8編碼格式:適用于網(wǎng)絡(luò)視頻通話、在線視頻服務(wù)等對開源和免費(fèi)有要求的場景,延遲低,適合實(shí)時(shí)通信,但壓縮效率和視頻質(zhì)量不如H.264和H.265,且設(shè)備兼容性較差。
6.2 在Android中實(shí)現(xiàn)視頻編碼
在 Android 中實(shí)現(xiàn)視頻編碼,同樣可以使用 MediaCodec 類。要選擇合適的編碼格式,可以參考以下步驟。
1)創(chuàng)建一個(gè) MediaCodec 編碼器實(shí)例:
MediaCodec videoEncoder = MediaCodec.createEncoderByType(MediaFormat.MIMETYPE_VIDEO_AVC);
2)配置編碼器參數(shù):
MediaFormat videoFormat = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, width, height);
videoFormat.setInteger(MediaFormat.KEY_BIT_RATE, bitRate);
videoFormat.setInteger(MediaFormat.KEY_FRAME_RATE, frameRate);
videoFormat.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, iFrameInterval);
videoEncoder.configure(videoFormat, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
3)開始編碼:
videoEncoder.start();
7、硬件編碼與軟件編碼的選擇與優(yōu)缺點(diǎn)
硬件編碼利用 GPU 進(jìn)行編碼,性能更高,但兼容性較差;軟件編碼則兼容性更好,但性能較低。在實(shí)際應(yīng)用中,需要根據(jù)設(shè)備性能和需求進(jìn)行選擇。
在 Android 中,MediaCodec 類會(huì)根據(jù)設(shè)備性能和需求自動(dòng)選擇硬件編碼器或軟件編碼器。要強(qiáng)制使用硬件編碼器或軟件編碼器,可以在創(chuàng)建 MediaCodec 實(shí)例時(shí),指定編碼器名稱。
例如,要使用硬件 H.264 編碼器,可以使用以下代碼:
MediaCodec videoEncoder = MediaCodec.createByCodecName("OMX.google.h264.encoder");
8、傳輸協(xié)議

9、音視頻解碼與播放
9.1音視頻解碼器的選擇與性能優(yōu)化
解碼器的選擇會(huì)影響播放質(zhì)量和性能。通常,硬件解碼器性能更高,但兼容性較差;軟件解碼器兼容性較好,但性能較低。在實(shí)際應(yīng)用中,需要根據(jù)設(shè)備性能和需求進(jìn)行選擇。
在 Android 中,解碼器的選擇可以通過 MediaCodec 類來實(shí)現(xiàn)。MediaCodec 支持硬件解碼和軟件解碼,通常情況下,它會(huì)根據(jù)設(shè)備性能和需求自動(dòng)選擇解碼器。
9.2音視頻渲染與同步策略
在渲染音視頻時(shí),需要保證音視頻同步。可以通過校準(zhǔn)時(shí)間戳或者調(diào)整播放速度等方法實(shí)現(xiàn)同步。
在 Android 中,音視頻的渲染可以通過 SurfaceView 或 TextureView 來實(shí)現(xiàn)。為了保證音視頻同步,可以在渲染每幀數(shù)據(jù)時(shí),根據(jù)時(shí)間戳來調(diào)整渲染速度。
以下是具體實(shí)踐步驟。
1)創(chuàng)建一個(gè) SurfaceView 或 TextureView:
SurfaceView surfaceView = new SurfaceView(context);
// 或
TextureView textureView = new TextureView(context);
2)在解碼每幀數(shù)據(jù)時(shí),根據(jù)時(shí)間戳來調(diào)整渲染速度:
long presentationTimeUs = bufferInfo.presentationTimeUs;
long delayUs = presentationTimeUs - System.nanoTime() / 1000;
if (delayUs > 0) {
Thread.sleep(delayUs / 1000);
}
decoder.releaseOutputBuffer(outputBufferIndex, true);
9.3播放器的緩沖與自適應(yīng)碼率調(diào)整
為了應(yīng)對網(wǎng)絡(luò)波動(dòng),播放器需要設(shè)置合適的緩沖策略。自適應(yīng)碼率調(diào)整則可以根據(jù)網(wǎng)絡(luò)狀況動(dòng)態(tài)調(diào)整視頻質(zhì)量,以保證流暢度。
在 Android 中,播放器的緩沖策略可以通過 MediaPlayer 或 ExoPlayer 的 API 來設(shè)置。自適應(yīng)碼率調(diào)整則可以通過 ExoPlayer 的 TrackSelection API 來實(shí)現(xiàn)。
以下是具體實(shí)踐步驟。
1)設(shè)置播放器的緩沖策略:
MediaPlayer mediaPlayer = new MediaPlayer();
mediaPlayer.setBufferingUpdateListener(new MediaPlayer.OnBufferingUpdateListener() {
@Override
public void onBufferingUpdate(MediaPlayer mp, int percent) {
// 更新緩沖進(jìn)度
}
});
// 或
ExoPlayer exoPlayer = new SimpleExoPlayer.Builder(context).build();
exoPlayer.setBufferedPositionUpdateListener(new ExoPlayer.BufferedPositionUpdateListener() {
@Override
public void onBufferedPositionUpdate(long bufferedPosition) {
// 更新緩沖進(jìn)度
}
});
2)設(shè)置自適應(yīng)碼率調(diào)整:
TrackSelection.Factory trackSelectionFactory = new AdaptiveTrackSelection.Factory();
DefaultTrackSelector trackSelector = new DefaultTrackSelector(context, trackSelectionFactory);
ExoPlayer exoPlayer = new SimpleExoPlayer.Builder(context).setTrackSelector(trackSelector).build();
10、直播架構(gòu)概述
10.1直播架構(gòu)圖
以下是直播架構(gòu)圖:

解釋一下:
- 1)推流端:需要實(shí)現(xiàn)音視頻采集、編碼、傳輸?shù)裙δ堋jP(guān)鍵組件包括采集模塊、編碼器、傳輸模塊等;
- 2)服務(wù)器端:負(fù)責(zé)接收、轉(zhuǎn)發(fā)和存儲(chǔ)音視頻數(shù)據(jù)。關(guān)鍵組件包括負(fù)載均衡、轉(zhuǎn)碼、錄制等功能模塊;
- 3)拉流端:需要實(shí)現(xiàn)音視頻解碼、渲染和播放等功能。關(guān)鍵組件包括解碼器、渲染模塊、播放器等。
10.2直播延遲與優(yōu)化策略
直播延遲會(huì)影響用戶體驗(yàn)。通過優(yōu)化采集、編碼、傳輸、解碼等環(huán)節(jié),可以降低延遲,提高實(shí)時(shí)性。
直播延遲優(yōu)化策略有:
- 1)優(yōu)化采集模塊:提高采集效率,減少數(shù)據(jù)處理時(shí)間;
- 2)優(yōu)化編碼器:選擇性能更高的編碼器,減少編碼時(shí)間;
- 3)優(yōu)化傳輸模塊:優(yōu)化網(wǎng)絡(luò)傳輸策略,如使用更快的傳輸協(xié)議、提高網(wǎng)絡(luò)帶寬等;
- 4)優(yōu)化解碼器:選擇性能更高的解碼器,減少解碼時(shí)間;
- 5)優(yōu)化渲染模塊和播放器:提高渲染效率,減少播放延遲。
11、本文小結(jié)
本文介紹了直播技術(shù)的全貌,涉及實(shí)時(shí)音視頻采集到播放的各個(gè)環(huán)節(jié)。
以下是一個(gè)簡化的直播流程圖:

直播流程包括以下幾個(gè)關(guān)鍵環(huán)節(jié):
- 1)實(shí)時(shí)音視頻采集:通過攝像頭和麥克風(fēng)采集音視頻數(shù)據(jù),并進(jìn)行參數(shù)設(shè)置和同步處理;
- 2)音視頻編碼:將采集到的音視頻數(shù)據(jù)進(jìn)行編碼,以便進(jìn)行傳輸。選擇合適的編碼器和編碼格式,如AAC、Opus、H.264、H.265和VP8等;
- 3)傳輸協(xié)議:選擇合適的傳輸協(xié)議,如RTMP、HLS和WebRTC等,以保證音視頻數(shù)據(jù)的實(shí)時(shí)傳輸;
- 4)服務(wù)器處理:服務(wù)器接收、轉(zhuǎn)發(fā)和存儲(chǔ)音視頻數(shù)據(jù),進(jìn)行負(fù)載均衡、轉(zhuǎn)碼和錄制等處理;
- 5)音視頻解碼與播放:將接收到的音視頻數(shù)據(jù)進(jìn)行解碼、渲染和播放,實(shí)現(xiàn)音視頻同步和延遲優(yōu)化。
在實(shí)際應(yīng)用中,需要根據(jù)需求和場景選擇合適的技術(shù)和策略,以實(shí)現(xiàn)高質(zhì)量、低延遲的直播體驗(yàn)。
12、參考資料
[1] 詳解音頻編解碼的原理、演進(jìn)和應(yīng)用選型
[2] 零基礎(chǔ),史上最通俗視頻編碼技術(shù)入門
[3] 理解實(shí)時(shí)音視頻聊天中的延時(shí)問題一篇就夠
[4] 淺談開發(fā)實(shí)時(shí)視頻直播平臺(tái)的技術(shù)要點(diǎn)
[5] 福利貼:最全實(shí)時(shí)音視頻開發(fā)要用到的開源工程匯總
[6] 愛奇藝技術(shù)分享:輕松詼諧,講解視頻編解碼技術(shù)的過去、現(xiàn)在和將來
[7] 零基礎(chǔ)入門:實(shí)時(shí)音視頻技術(shù)基礎(chǔ)知識(shí)全面盤點(diǎn)
[8] 實(shí)時(shí)音視頻面視必備:快速掌握11個(gè)視頻技術(shù)相關(guān)的基礎(chǔ)概念
[9] 理論聯(lián)系實(shí)際:實(shí)現(xiàn)一個(gè)簡單地基于html]5的實(shí)時(shí)視頻直播
[10] 實(shí)時(shí)視頻直播客戶端技術(shù)盤點(diǎn):Native、html]5、WebRTC、微信小程序
[11] Android直播入門實(shí)踐:動(dòng)手搭建一套簡單的直播系統(tǒng)
[12] 視頻直播技術(shù)干貨:一文讀懂主流視頻直播系統(tǒng)的推拉流架構(gòu)、傳輸協(xié)議等
[13] 零基礎(chǔ)入門:基于開源WebRTC,從0到1實(shí)現(xiàn)實(shí)時(shí)音視頻聊天功能
[14] 實(shí)時(shí)音視頻入門學(xué)習(xí):開源工程WebRTC的技術(shù)原理和使用淺析
[15] 實(shí)時(shí)音視頻開發(fā)理論必備:如何省流量?視頻高度壓縮背后的預(yù)測技術(shù)
[16] 萬字長文詳解QQ Linux端實(shí)時(shí)音視頻背后的跨平臺(tái)實(shí)踐
(本文已同步發(fā)布于:http://www.52im.net/thread-4714-1-1.html)
作者:Jack Jiang (點(diǎn)擊作者姓名進(jìn)入Github)
出處:http://www.52im.net/space-uid-1.html
交流:歡迎加入即時(shí)通訊開發(fā)交流群 215891622
討論:http://www.52im.net/
Jack Jiang同時(shí)是【原創(chuàng)Java
Swing外觀工程BeautyEye】和【輕量級(jí)移動(dòng)端即時(shí)通訊框架MobileIMSDK】的作者,可前往下載交流。
本博文
歡迎轉(zhuǎn)載,轉(zhuǎn)載請注明出處(也可前往 我的52im.net 找到我)。