iOS 直播 —— 推流

*推流束世,就是將采集到的音頻,視頻數(shù)據(jù)通過(guò)流媒體協(xié)議發(fā)送到流媒體服務(wù)器床玻。
*推流前的工作:采集毁涉,處理,編碼壓縮
*推流中做的工作: 封裝锈死,上傳

推流前的工作.png

推流——采集到的音頻贫堰,視頻數(shù)據(jù)通過(guò)流媒體協(xié)議發(fā)送到流媒體服務(wù)器.png

話說(shuō)回來(lái), 其實(shí)有一個(gè)庫(kù) LFLiveKit 已經(jīng)實(shí)現(xiàn)了 后臺(tái)錄制待牵、美顏功能严嗜、支持h264、AAC硬編碼洲敢,動(dòng)態(tài)改變速率,RTMP傳輸?shù)惹羊牵覀冋嬲_(kāi)發(fā)的時(shí)候直接使用就很方便啦压彭。
另外也有:
LiveVideoCoreSDK : 實(shí)現(xiàn)了美顏直播和濾鏡功能,我們只要填寫(xiě)RTMP服務(wù)地址渗常,直接就可以進(jìn)行推流啦壮不。
PLCameraStreamingKit: 也是一個(gè)不錯(cuò)的 RTMP 直播推流 SDK。

但還是推薦用 LFLiveKit皱碘,而為了進(jìn)一步了解推流這個(gè)過(guò)程询一,先按自己的步子試著走走,了解下癌椿。

一健蕊、采集視頻
采集硬件(攝像頭)視頻圖像

#import "MovieViewController.h"
#import <AVFoundation/AVFoundation.h>

@interface MovieViewController ()<AVCaptureVideoDataOutputSampleBufferDelegate,AVCaptureAudioDataOutputSampleBufferDelegate>

@property (nonatomic, strong) AVCaptureSession *session;
@property (nonatomic, strong) AVCaptureVideoDataOutput *videoOutput;
@property (nonatomic, strong) AVCaptureAudioDataOutput *audioOutput;

@property (nonatomic, strong) dispatch_queue_t videoQueue;
@property (nonatomic, strong) dispatch_queue_t audioQueue;

@property (nonatomic, strong) AVCaptureConnection *videoConnection;
@property (nonatomic, strong) AVCaptureConnection *audioConnection;

@property (nonatomic, strong) AVCaptureVideoPreviewLayer *previewLayer;

@end

@implementation MovieViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self initSession];
    [self showPlayer];
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.session startRunning];
}

- (void)viewDidDisappear:(BOOL)animated {
    [self.session stopRunning];
}

- (void)initSession {
    // 初始化 session
    _session = [[AVCaptureSession alloc] init];

    // 配置采集輸入源(攝像頭)
    NSError *error = nil;
    // 獲得一個(gè)采集設(shè)備, 默認(rèn)后置攝像頭
    AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
    // 用設(shè)備初始化一個(gè)采集的輸入對(duì)象
    AVCaptureDeviceInput *videoInput = [AVCaptureDeviceInput deviceInputWithDevice:videoDevice error:&error];
    AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioDevice error:&error];
    if (error) {
        NSLog(@"Error getting  input device: %@", error.description);
        return;
    }

    if ([_session canAddInput:videoInput]) {
        [_session addInput:videoInput]; // 添加到Session
    }
    if ([_session canAddInput:audioInput]) {
        [_session addInput:audioInput]; // 添加到Session
    }
    // 配置采集輸出,即我們?nèi)〉靡曨l圖像的接口
    _videoQueue = dispatch_queue_create("Video Capture Queue", DISPATCH_QUEUE_SERIAL);
    _audioQueue = dispatch_queue_create("Audio Capture Queue", DISPATCH_QUEUE_SERIAL);

    _videoOutput = [[AVCaptureVideoDataOutput alloc] init];
    _audioOutput = [[AVCaptureAudioDataOutput alloc] init];

    [_videoOutput setSampleBufferDelegate:self queue:_videoQueue];
    [_audioOutput setSampleBufferDelegate:self queue:_audioQueue];

    // 配置輸出視頻圖像格式
    NSDictionary *captureSettings = @{(NSString*)kCVPixelBufferPixelFormatTypeKey: @(kCVPixelFormatType_32BGRA)};
    _videoOutput.videoSettings = captureSettings;
    _videoOutput.alwaysDiscardsLateVideoFrames = YES;
    if ([_session canAddOutput:_videoOutput]) {
       [_session addOutput:_videoOutput];  // 添加到Session
    }

    if ([_session canAddOutput:_audioOutput]) {
        [_session addOutput:_audioOutput]; // 添加到Session
    }
    // 保存Connection踢俄,用于在SampleBufferDelegate中判斷數(shù)據(jù)來(lái)源(Video/Audio)
    _videoConnection = [_videoOutput connectionWithMediaType:AVMediaTypeVideo];
    _audioConnection = [_audioOutput connectionWithMediaType:AVMediaTypeAudio];

}

- (void)showPlayer {
    _previewLayer = [AVCaptureVideoPreviewLayer layerWithSession:_session];
    _previewLayer.videoGravity = AVLayerVideoGravityResizeAspectFill; // 設(shè)置預(yù)覽時(shí)的視頻縮放方式
    [[_previewLayer connection] setVideoOrientation:AVCaptureVideoOrientationPortrait]; // 設(shè)置視頻的朝向
    _previewLayer.frame = self.view.layer.bounds;
    [self.view.layer addSublayer:_previewLayer];
}

#pragma mark 獲取 AVCapture Delegate
- (void)captureOutput:(AVCaptureOutput *)captureOutput didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer fromConnection:(AVCaptureConnection *)connection {

    // 這里的sampleBuffer就是采集到的數(shù)據(jù)了,根據(jù)connection來(lái)判斷缩功,是Video還是Audio的數(shù)據(jù)
    if (connection == self.videoConnection) {  // Video
        NSLog(@"這里獲的 video sampleBuffer,做進(jìn)一步處理(編碼H.264)");
    } else if (connection == self.audioConnection) {  // Audio
        NSLog(@"這里獲得 audio sampleBuffer都办,做進(jìn)一步處理(編碼AAC)");
    }
}

@end

上述是大致實(shí)現(xiàn)獲取最基本數(shù)據(jù)的情況嫡锌,一些細(xì)節(jié)(尺寸、方向)暫時(shí)沒(méi)有深入琳钉,真正做直播的時(shí)候势木,一般是視頻和音頻是分開(kāi)處理的,只有重點(diǎn)注意那個(gè)代理方法歌懒。
二啦桌、GPUImage 處理

在進(jìn)行編碼 H.264 之前,一般來(lái)說(shuō)肯定會(huì)做一些美顏處理的歼培,否則那播出的感覺(jué)太真實(shí)震蒋,就有點(diǎn)丑啦茸塞,在此以磨皮和美白為例簡(jiǎn)單了解。(具體參考的是:琨君 基于 GPUImage 的實(shí)時(shí)美顏濾鏡
直接用 BeautifyFaceDemo 中的類GPUImageBeautifyFilter
, 可以對(duì)的圖片直接進(jìn)行處理:

GPUImageBeautifyFilter *filter = [[GPUImageBeautifyFilter alloc] init];
UIImage *image = [UIImage imageNamed:@"testMan"];
UIImage *resultImage = [filter imageByFilteringImage:image];
self.backgroundView.image = resultImage;

備注下 CMSampleBufferRef 與 UIImage 的轉(zhuǎn)換

- (UIImage *)sampleBufferToImage:(CMSampleBufferRef)sampleBuffer {
    //制作 CVImageBufferRef
    CVImageBufferRef buffer;
    buffer = CMSampleBufferGetImageBuffer(sampleBuffer);

    CVPixelBufferLockBaseAddress(buffer, 0);

    //從 CVImageBufferRef 取得影像的細(xì)部信息
    uint8_t *base;
    size_t width, height, bytesPerRow;
    base = CVPixelBufferGetBaseAddress(buffer);
    width = CVPixelBufferGetWidth(buffer);
    height = CVPixelBufferGetHeight(buffer);
    bytesPerRow = CVPixelBufferGetBytesPerRow(buffer);

    //利用取得影像細(xì)部信息格式化 CGContextRef
    CGColorSpaceRef colorSpace;
    CGContextRef cgContext;
    colorSpace = CGColorSpaceCreateDeviceRGB();
    cgContext = CGBitmapContextCreate(base, width, height, 8, bytesPerRow, colorSpace, kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
    CGColorSpaceRelease(colorSpace);

    //透過(guò) CGImageRef 將 CGContextRef 轉(zhuǎn)換成 UIImage
    CGImageRef cgImage;
    UIImage *image;
    cgImage = CGBitmapContextCreateImage(cgContext);
    image = [UIImage imageWithCGImage:cgImage];
    CGImageRelease(cgImage);
    CGContextRelease(cgContext);
    CVPixelBufferUnlockBaseAddress(buffer, 0);
    return image;
}

但是視頻中是怎樣進(jìn)行美容處理呢查剖?怎樣將其轉(zhuǎn)換的呢钾虐?平常我們這樣直接使用:

GPUImageBeautifyFilter *beautifyFilter = [[GPUImageBeautifyFilter alloc] init];
[self.videoCamera addTarget:beautifyFilter];
[beautifyFilter addTarget:self.gpuImageView];

此處用到了 GPUImageVideoCamera,可以大致了解下 GPUImage詳細(xì)解析(三)- 實(shí)時(shí)美顏濾鏡
GPUImageVideoCamera: GPUImageOutput的子類笋庄,提供來(lái)自攝像頭的圖像數(shù)據(jù)作為源數(shù)據(jù)效扫,一般是響應(yīng)鏈的源頭。
GPUImageView:響應(yīng)鏈的終點(diǎn)直砂,一般用于顯示GPUImage的圖像菌仁。
GPUImageFilter:用來(lái)接收源圖像,通過(guò)自定義的頂點(diǎn)静暂、片元著色器來(lái)渲染新的圖像济丘,并在繪制完成后通知響應(yīng)鏈的下一個(gè)對(duì)象。
GPUImageFilterGroup:多個(gè)GPUImageFilter的集合洽蛀。
** GPUImageBeautifyFilter**:

@interface GPUImageBeautifyFilter : GPUImageFilterGroup {
  GPUImageBilateralFilter *bilateralFilter;
  GPUImageCannyEdgeDetectionFilter *cannyEdgeFilter;
  GPUImageCombinationFilter *combinationFilter;
  GPUImageHSBFilter *hsbFilter;
}
簡(jiǎn)單理解這個(gè)美顏的流程.png

不得不說(shuō)GPUImage 是相當(dāng)強(qiáng)大的摹迷,此處的功能也只是顯現(xiàn)了一小部分,其中 filter 那塊的處理個(gè)人目前還有好多不理解郊供,需要去深入了解啃源碼峡碉,暫時(shí)不過(guò)多引入。通過(guò)這個(gè)過(guò)程將 sampleBuffer 美容處理后驮审,自然是進(jìn)行編碼啦鲫寄。
三、視頻疯淫、音頻壓縮編碼

而編碼是用 硬編碼呢 還是軟編碼呢地来? 相同碼率,軟編圖像質(zhì)量更清晰熙掺,但是耗電更高靠抑,而且會(huì)導(dǎo)致CPU過(guò)熱燙到攝像頭。不過(guò)硬編碼會(huì)涉及到其他平臺(tái)的解碼适掰,有很多坑颂碧。綜合來(lái)說(shuō),iOS 端硬件兼容性較好类浪,iOS 8.0占有率也已經(jīng)很高了载城,可以直接采用硬編。
硬編碼:下面幾個(gè)DEMO 可以對(duì)比下费就,當(dāng)然看 LFLiveKit 更直接诉瓦。
VideoToolboxPlus
iOSHardwareDecoder
-VideoToolboxDemo
iOS-h264Hw-Toolbox

軟編碼: 利用FFmpeg+x264將iOS攝像頭實(shí)時(shí)視頻流編碼為h264文件 ,備忘下: FFmpeg-X264-Encode-for-iOS
我直接使用了 LFLiveKit ,里面已經(jīng)封裝的很好啦睬澡,此處對(duì) Audiotoolbox && VideoToolbox 簡(jiǎn)單了解下:

AudioToolbox
iOS使用AudioToolbox中的AudioConverter API 把源格式轉(zhuǎn)換成目標(biāo)格式, 詳細(xì)可以看 使用iOS自帶AAC編碼器固额。

// 1、根據(jù)輸入樣本初始化一個(gè)編碼轉(zhuǎn)換器
AudioStreamBasicDescription 根據(jù)指定的源格式和目標(biāo)格式創(chuàng)建 audio converter
// 2煞聪、初始化一個(gè)輸出緩沖列表 outBufferList 
// 3斗躏、獲取 AudioCallBack
OSStatus inputDataProc(AudioConverterRef inConverter, UInt32 *ioNumberDataPackets, AudioBufferList *ioData,AudioStreamPacketDescription **outDataPacketDescription, void *inUserData) 
// 4、音頻格式完成轉(zhuǎn)換
AudioConverterFillComplexBuffer 實(shí)現(xiàn)inBufferList 和 outBufferList昔脯、inputDataProc音頻格式之間的轉(zhuǎn)換啄糙。

VideoToolbox
iOS8之后的硬解碼、硬編碼API云稚,此處只做編碼用隧饼。

// 1、初始化 VTCompressionSessionRef  
- (void)initCompressionSession;
// 2静陈、傳入  解碼一個(gè)frame
VTCompressionSessionEncodeFrame(compressionSession, pixelBuffer, presentationTimeStamp, duration, (__bridge CFDictionaryRef)properties, (__bridge_retained void *)timeNumber, &flags);
// 3燕雁、回調(diào),處理 取得PPS和SPS
static void VideoCompressonOutputCallback(void *VTref, void *VTFrameRef, OSStatus status, VTEncodeInfoFlags infoFlags, CMSampleBufferRef sampleBuffer)
// 4鲸拥、完成編碼贵白,然后銷毀session
VTCompressionSessionCompleteFrames(compressionSession, kCMTimeInvalid);
VTCompressionSessionInvalidate(compressionSession);
CFRelease(compressionSession);
compressionSession = NULL;

四、推流

封裝數(shù)據(jù)成 FLV崩泡,通過(guò) RTMP 協(xié)議打包上傳,從主播端到服務(wù)端即基本完成推流猬膨。
4-1角撞、封裝數(shù)據(jù)通常是封裝成 FLV
FLV流媒體格式是一種新的視頻格式,全稱為FlashVideo勃痴。由于它形成的文件極小谒所、加載速度極快,使得網(wǎng)絡(luò)觀看視頻文件成為可能沛申,它的出現(xiàn)有效地解決了視頻文件導(dǎo)入Flash后劣领,使導(dǎo)出的SWF文件體積龐大,不能在網(wǎng)絡(luò)上很好的使用等缺點(diǎn)铁材。(What)

格式: 源自(封包 FLV

一般FLV 文件結(jié)構(gòu)里是這樣存放的:
[[Flv Header]
[Metainfo Tag]
[Video Tag]
[Audio Tag]
[Video Tag]
[Audio Tag]
[Other Tag]…]
其中 AudioTag 和 VideoTag 出現(xiàn)的順序隨機(jī)的尖淘,沒(méi)有嚴(yán)格的定義。
Flv Header 是文件的頭部著觉,用FLV字符串標(biāo)明了文件的類型村生,以及是否有音頻、視頻等信息饼丘。之后會(huì)有幾個(gè)字節(jié)告訴接下來(lái)的包字節(jié)數(shù)趁桃。
Metainfo 中用來(lái)描述Flv中的各種參數(shù)信息,例如視頻的編碼格式、分辨率卫病、采樣率等等油啤。如果是本地文件(非實(shí)時(shí)直播流),還會(huì)有偏移時(shí)間戳之類的信息用于支持快進(jìn)等操作蟀苛。
VideoTag 存放視頻數(shù)據(jù)益咬。對(duì)于H.264來(lái)說(shuō),第一幀發(fā)送的NALU應(yīng)為 SPS和PPS屹逛,這個(gè)相當(dāng)于H.264的文件頭部础废,播放器解碼流必須先要找到這個(gè)才能進(jìn)行播放。之后的數(shù)據(jù)為I幀或P幀罕模。
AudioTag 存放音頻數(shù)據(jù)评腺。對(duì)于AAC來(lái)說(shuō),我們只需要在每次硬編碼完成后給數(shù)據(jù)加上adts頭部信息即可淑掌。

iOS 中的使用:詳細(xì)看看 LFLiveKit 中的 LFStreamRTMPSocket 類蒿讥。
4-2、RTMP
從推流端到服務(wù)端抛腕,數(shù)據(jù)經(jīng)過(guò)處理后芋绸,最常用的協(xié)議是RTMP(Real Time Messaging Protocol,實(shí)時(shí)消息傳送協(xié)議)担敌。

RTMP的傳輸延遲通常在1-3秒摔敛,符合手機(jī)直播對(duì)性能的要求,因此RTMP是手機(jī)直播中最常見(jiàn)的傳輸協(xié)議全封。

但是網(wǎng)絡(luò)延遲和阻塞等問(wèn)題的一直存在的马昙,所以通過(guò)Quality of Servic一種網(wǎng)絡(luò)機(jī)制將流數(shù)據(jù)推送到網(wǎng)絡(luò)端,通過(guò)CDN分發(fā)是必要的刹悴。

另外行楞,服務(wù)端還需要對(duì)數(shù)據(jù)流一定的處理,轉(zhuǎn)碼土匀,使得數(shù)據(jù)流支持HLS子房,HTTP-FLV,RTMP等格式的拉流就轧,支持一轉(zhuǎn)多证杭,適配不同網(wǎng)絡(luò)、分辨率的終端妒御。(當(dāng)然這就是服務(wù)端要做的事情啦)

可以用 LFLiveKit 直接嘗試躯砰,或者也可以看看 LMLiveStreaming,當(dāng)然此處先用一個(gè)本地視頻推送嘗試一下携丁。
4-3琢歇、本地模擬推流
此處是跟著 快速集成iOS基于RTMP的視頻推流 來(lái)實(shí)現(xiàn)的兰怠,否則就連基本的展示都不能啦啊。此處也可以配合著Mac搭建nginx+rtmp服務(wù)器 來(lái)安裝李茫,安裝好 nginx 之后揭保,安裝ffmpeg、下載 VLC 就可以直接開(kāi)始啦
起初在用 ffmpeg 的時(shí)候魄宏,遇到下面那個(gè)錯(cuò):

一個(gè)輸入的錯(cuò).png

后來(lái)發(fā)現(xiàn)是自己輸入錯(cuò)了秸侣,還是要仔細(xì):
視頻文件地址:/Users/pipixia/Desktop/kobe.mp4(自己的一個(gè)測(cè)試視頻)
推流拉流地址:rtmp://localhost:1935/rtmplive/room

~ ffmpeg -re -i /Users/qiu/Desktop/kobe -vcodec libx264 -acodec aac -strict -2 -f flv rtmp://localhost:1935/rtmplive/room

那個(gè)-vcodec libx264 -acodec aac -strict -2 -f flv命令也不要寫(xiě)錯(cuò)了,ffmpeg 命令可參考 FFmpeg常用基本命令宠互。

784630-5263fc0c51731bef.gif

4-4味榛、手機(jī)直播 - VLC上 顯示
為了更好的感受下,我們可以直接 用 LMLiveStreaming予跌,然后打開(kāi) VLC 中 的 file -- Open Network, 直接輸入代碼中的 url:
代碼中的這個(gè)地址.png

然后我們電腦端就可以顯示啦
784630-33c1c2e09eaba2c0.gif

而目前有延遲2秒的情況搏色,話說(shuō)這是正常的。但如何優(yōu)化呢券册?不知道频轿,如有朋友有好建議歡迎告之。備注下:直播中累積延時(shí)的優(yōu)化烁焙。
總結(jié)

PS:上面?zhèn)鬏斨皇峭屏鞫说椒?wù)端的模擬過(guò)程航邢,然而傳輸一般是包括系統(tǒng)的多個(gè)部分,連接推流端骄蝇,服務(wù)端膳殷,播放端等多個(gè)部分。而 iOS 這塊播放端直接用 ijkplayer, 像上一個(gè)筆記——直播初探 , 就很快實(shí)現(xiàn)了拉流的過(guò)程九火,當(dāng)然也是 ijkplayer 過(guò)于強(qiáng)大的原因咯赚窃。
下面宏觀上了解下整個(gè)傳輸過(guò)程:

整體傳輸流程.png

PS: 另外其實(shí)好多第三方的集成也很好用,可參考
七牛云
騰訊的直播 LVB
網(wǎng)易云信 SDK
趣拍云

總的說(shuō)來(lái)吃既,這又是一個(gè)粗略的過(guò)程,站在好多個(gè)巨人的肩膀上跨细,但是還是基本了解了一個(gè)推流的流程鹦倚,沒(méi)有正式項(xiàng)目的經(jīng)驗(yàn),肯定有太很多細(xì)節(jié)點(diǎn)忽略了和好多坑需要填冀惭,還是那個(gè)目的震叙,暫時(shí)先作為自己的預(yù)備知識(shí)點(diǎn)吧,不過(guò)此處可以擴(kuò)展和深入的知識(shí)點(diǎn)真的太多啦散休,如 LFLiveKitGPUImage 僅僅展露的是冰山一角媒楼。

備注參考:
LiveVideoCoreSDK
LFLiveKit
GPUImage
LMLiveStreaming
PLCameraStreamingKit
iOS手機(jī)直播Demo技術(shù)簡(jiǎn)介
iOS視頻開(kāi)發(fā)經(jīng)驗(yàn)
iOS 上的相機(jī)捕捉
CMSampleBufferRef 與 UIImage 的轉(zhuǎn)換
GPUImage詳細(xì)解析(三)- 實(shí)時(shí)美顏濾鏡
iOS8系統(tǒng)H264視頻硬件編解碼說(shuō)明
利用FFmpeg+x264將iOS攝像頭實(shí)時(shí)視頻流編碼為h264文件
使用VideoToolbox硬編碼H.264
使用iOS自帶AAC編碼器
如何搭建一個(gè)完整的視頻直播系統(tǒng)?
直播中累積延時(shí)的優(yōu)化
使用VLC做流媒體服務(wù)器(直播形式)

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末戚丸,一起剝皮案震驚了整個(gè)濱河市划址,隨后出現(xiàn)的幾起案子扔嵌,更是在濱河造成了極大的恐慌,老刑警劉巖夺颤,帶你破解...
    沈念sama閱讀 222,183評(píng)論 6 516
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件痢缎,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡世澜,警方通過(guò)查閱死者的電腦和手機(jī)独旷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,850評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)寥裂,“玉大人嵌洼,你說(shuō)我怎么就攤上這事》馇。” “怎么了麻养?”我有些...
    開(kāi)封第一講書(shū)人閱讀 168,766評(píng)論 0 361
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)俭驮。 經(jīng)常有香客問(wèn)我回溺,道長(zhǎng),這世上最難降的妖魔是什么混萝? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 59,854評(píng)論 1 299
  • 正文 為了忘掉前任遗遵,我火速辦了婚禮,結(jié)果婚禮上逸嘀,老公的妹妹穿的比我還像新娘车要。我一直安慰自己,他們只是感情好崭倘,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,871評(píng)論 6 398
  • 文/花漫 我一把揭開(kāi)白布翼岁。 她就那樣靜靜地躺著,像睡著了一般司光。 火紅的嫁衣襯著肌膚如雪琅坡。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 52,457評(píng)論 1 311
  • 那天残家,我揣著相機(jī)與錄音榆俺,去河邊找鬼。 笑死坞淮,一個(gè)胖子當(dāng)著我的面吹牛茴晋,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播回窘,決...
    沈念sama閱讀 40,999評(píng)論 3 422
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼诺擅,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了烁涌?” 一聲冷哼從身側(cè)響起驰怎,我...
    開(kāi)封第一講書(shū)人閱讀 39,914評(píng)論 0 277
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤二打,失蹤者是張志新(化名)和其女友劉穎症杏,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,465評(píng)論 1 319
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡筐眷,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,543評(píng)論 3 342
  • 正文 我和宋清朗相戀三年武翎,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了符隙。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片露久。...
    茶點(diǎn)故事閱讀 40,675評(píng)論 1 353
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蛉加,到底是詐尸還是另有隱情丁眼,我是刑警寧澤,帶...
    沈念sama閱讀 36,354評(píng)論 5 351
  • 正文 年R本政府宣布硫眨,位于F島的核電站族奢,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,029評(píng)論 3 335
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦亏较、人聲如沸可霎。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,514評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)叉讥。三九已至救崔,卻和暖如春惶看,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,616評(píng)論 1 274
  • 我被黑心中介騙來(lái)泰國(guó)打工本今, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,091評(píng)論 3 378
  • 正文 我出身青樓诈泼,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親煤禽。 傳聞我的和親對(duì)象是個(gè)殘疾皇子铐达,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,685評(píng)論 2 360

推薦閱讀更多精彩內(nèi)容