iOS 直播 —— 推流

推流,就是將采集到的音頻洛口,視頻數(shù)據(jù)通過(guò)流媒體協(xié)議發(fā)送到流媒體服務(wù)器矫付。

  • 推流前的工作:采集,處理第焰,編碼壓縮
  • 推流中做的工作: 封裝买优,上傳
推流前的工作
推流——采集到的音頻,視頻數(shù)據(jù)通過(guò)流媒體協(xié)議發(fā)送到流媒體服務(wù)器

話說(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è)美顏的流程

不得不說(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 更直接琼了。

軟編碼: 利用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ò)

后來(lái)發(fā)現(xiàn)是自己輸入錯(cuò)了,還是要仔細(xì):
視頻文件地址:/Users/qiu/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常用基本命令崇众。

kobeAndOneal.gif
4-4、手機(jī)直播 - VLC上 顯示

為了更好的感受下航厚,我們可以直接 用 LMLiveStreaming顷歌,然后打開(kāi) VLC 中 的 file -- Open Network, 直接輸入代碼中的 url:

代碼中的這個(gè)地址

然后我們電腦端就可以顯示啦

Live.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ò)程:

整體傳輸流程
PS: 另外其實(shí)好多第三方的集成也很好用份汗,可參考

總的說(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 僅僅展露的是冰山一角嚎幸。

備注參考:
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市嫉晶,隨后出現(xiàn)的幾起案子骑疆,更是在濱河造成了極大的恐慌,老刑警劉巖车遂,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件封断,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡舶担,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門(mén)彬呻,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)衣陶,“玉大人,你說(shuō)我怎么就攤上這事闸氮〖艨觯” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵蒲跨,是天一觀的道長(zhǎng)译断。 經(jīng)常有香客問(wèn)我,道長(zhǎng)或悲,這世上最難降的妖魔是什么孙咪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮巡语,結(jié)果婚禮上翎蹈,老公的妹妹穿的比我還像新娘。我一直安慰自己男公,他們只是感情好荤堪,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著枢赔,像睡著了一般澄阳。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上踏拜,一...
    開(kāi)封第一講書(shū)人閱讀 51,775評(píng)論 1 307
  • 那天碎赢,我揣著相機(jī)與錄音,去河邊找鬼执隧。 笑死揩抡,一個(gè)胖子當(dāng)著我的面吹牛户侥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播峦嗤,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼蕊唐,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了烁设?” 一聲冷哼從身側(cè)響起替梨,我...
    開(kāi)封第一講書(shū)人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎装黑,沒(méi)想到半個(gè)月后副瀑,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡恋谭,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年糠睡,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片疚颊。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡狈孔,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出材义,到底是詐尸還是另有隱情均抽,我是刑警寧澤,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布其掂,位于F島的核電站油挥,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏款熬。R本人自食惡果不足惜深寥,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望华烟。 院中可真熱鬧翩迈,春花似錦、人聲如沸盔夜。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)喂链。三九已至返十,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間椭微,已是汗流浹背洞坑。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蝇率,地道東北人迟杂。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓刽沾,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親排拷。 傳聞我的和親對(duì)象是個(gè)殘疾皇子侧漓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

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