AVFoundation 拍照/錄制視頻

首先介紹下實現(xiàn)拍照和錄制視頻需要用到的類:

  • AVCaptureVideoPreviewLayer:捕獲視頻預覽層析桥。
  • AVCaptureSession:捕獲會話類巡蘸。
  • AVCaptureDevice:捕獲設備類壤巷。
  • AVCaptureDeviceInput:捕獲設備輸入類。
  • AVCapturePhotoOutput:捕獲照片輸出類。
  • AVCaptureMovieFileOutput:捕獲電影文件輸出類。
  • AVCaptureConnection:捕獲連接類喝检。
  • AVCapturePhotoSettings:捕獲照片設置類。
  • AVAsset:資產(chǎn)類撼泛。
  • AVAssetImageGenerator:資產(chǎn)圖片生成器類停蕉。

首先來看下AVCaptureSession初始化的流程:

AVCaptureSession初始化配置

通過該流程圖可以看出,AVCaptureSession的初始化配置需要:
1锨并、視頻輸入設備 。
2译暂、音頻輸入設備。
3撩炊、照片輸出對象 外永。
3、電影文件輸出對象拧咳。

看核心代碼:

- (BOOL)setupSession:(NSError **)error {
    self.captureSession = [[AVCaptureSession alloc] init];
    self.captureSession.sessionPreset = AVCaptureSessionPresetHigh;
    //視頻輸入設備
    AVCaptureDevice *videoDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
    AVCaptureDeviceInput *videoDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:videoDevice error:error];
    if (videoDeviceInput) {
        if ([self.captureSession canAddInput:videoDeviceInput]) {
            [self.captureSession addInput:videoDeviceInput];
            self.activeVideoInput = videoDeviceInput;
        } else {
            return NO;
        }
    } else {
        return NO;
    }
    
    //音頻輸入設備
    AVCaptureDevice *audioDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
    AVCaptureDeviceInput *audioDeviceInput = [[AVCaptureDeviceInput alloc] initWithDevice:audioDevice error:error];
    if (audioDeviceInput) {
        if ([self.captureSession canAddInput:audioDeviceInput]) {
            [self.captureSession addInput:audioDeviceInput];
        } else {
            return NO;
        }
    } else {
        return NO;
    }
    
    //從實例攝像頭中捕捉靜態(tài)圖片
    self.photoOutput = [[AVCapturePhotoOutput alloc] init];
    if ([self.captureSession canAddOutput:self.photoOutput]) {
        [self.captureSession addOutput:self.photoOutput];
    }
    
    
    //用于將電影錄制到文件系統(tǒng)
    self.movieOutput = [[AVCaptureMovieFileOutput alloc] init];
    if ([self.captureSession canAddOutput:self.movieOutput]) {
        [self.captureSession addOutput:self.movieOutput];
    } 
    self.videoQueue = dispatch_queue_create("CQCamera.Video.Queue", NULL);
    return YES;
}

這段代碼最后我們還創(chuàng)建了個全局的串行隊列videoQueue伯顶,在后面開始捕獲和錄制時需要使用。

從上圖中我們還看到骆膝,在AVCaptureSession初始化配置結(jié)束后又做了兩個操作祭衩。
1、我們將AVCaptureVideoPreviewLayersession設置為AVCaptureSession阅签。

[(AVCaptureVideoPreviewLayer*)self.layer setSession:session];
  • 將捕捉數(shù)據(jù)直接輸出到圖層中掐暮,并確保與會話狀態(tài)同步。

2政钟、開始捕獲

- (void)startSession {
    if (![self.captureSession isRunning]) {
        dispatch_async(self.videoQueue, ^{
          [self.captureSession startRunning];
        });
    }
}

下面看下如何將捕獲的內(nèi)容生產(chǎn)圖片路克。

一、拍照

同樣先看流程圖:


AVCapturePhotoOutput

很明顯拍照我們需要使用AVCapturePhotoOutput 捕獲照片輸出對象养交。

看代碼:

- (void)captureStillImage {
    AVCaptureConnection *connection = [self.photoOutput connectionWithMediaType:AVMediaTypeVideo];
    if (connection.isVideoOrientationSupported) {
          connection.videoOrientation = [self currentVideoOrientation];
      }
    self.photoSettings = [AVCapturePhotoSettings photoSettingsWithFormat:@{AVVideoCodecKey:AVVideoCodecTypeJPEG}];
    [self.photoOutput capturePhotoWithSettings:self.photoSettings delegate:self];
}
  • 拍照時我們需要拿到捕獲連接對象(AVCaptureConnection)精算,設置視頻的方向,否則在橫豎屏切換時會出現(xiàn)問題碎连。
  • 在代理方法中我們利用捕獲連接對象(AVCaptureConnection)調(diào)用fileDataRepresentation方法獲取二進制圖片灰羽。

獲取到圖片后需要利用Photos庫將圖片保存到相冊。

Photos

將圖片保存到相冊我們首先要判斷是否有權(quán)限鱼辙,這個需要在plist文件中配置在這就不多說了廉嚼。

下面我們來看下將圖片添加到指定相冊的流程:

  • 第一步:添加圖片到【相機膠卷】。
    1.1: UIImageWriteToSavedPhotosAlbum函數(shù)
    1.2: AssetsLibrary框架(已過期,一般不用了)
    1.3: Photos框架(推薦)

  • 第二步:擁有一個【自定義相冊】
    2.1: AssetsLibrary框架
    2.2: Photos框架(推薦)

  • 第三步:將剛才添加到【相機膠卷】的圖片座每,引用(添加)到【自定義相冊】
    3.1: AssetsLibrary框架
    3.2: Photos框架(推薦)

Photos框架相關(guān)類須知:
1前鹅、PHAsset:一個PHAsset對象代表一張圖片或者一個視頻文件。
負責查詢一堆的圖片或者視頻文件(PHAsset對象)峭梳。

2舰绘、PHAssetCollection:一個PHAssetCollection對象代表一個相冊。
負責查詢一堆的相冊(PHAssetCollection對象)葱椭。

3捂寿、PHAssetChangeRequest: 負責執(zhí)行對PHAsset(照片或視頻)的【增刪改】操作。
這個類只能放在-[PHPhotoLibrary performChanges:completionHandler:]或者 -[PHPhotoLibrary performChangesAndWait:error:]方法的block中使用孵运。

4秦陋、PHAssetCollectionChangeRequest:負責執(zhí)行對PHAssetCollection(相冊)的【增刪改】操作。
這個類只能放在-[PHPhotoLibrary performChanges:completionHandler:] 或者 -[PHPhotoLibrary performChangesAndWait:error:]方法的block中使用治笨。

  • 保存圖片到 相機膠卷:
+ (PHFetchResult<PHAsset *> *)savePhoto:(UIImage *)image {
    __block NSString *createdAssetId = nil;
    // Synchronously 同步執(zhí)行操作
    NSError *error;
    [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
        createdAssetId = [PHAssetChangeRequest creationRequestForAssetFromImage:image].placeholderForCreatedAsset.localIdentifier;
    } error:&error];
    if (error == nil) {
        NSLog(@"保存成功");
    } else {
        NSLog(@"保存圖片Error: %@", error.localizedDescription);
        return nil;
    }
//    // Asynchronously 異步執(zhí)行操作
//    [[PHPhotoLibrary sharedPhotoLibrary] performChanges:^{
//        [PHAssetChangeRequest creationRequestForAssetFromImage:image];
//    } completionHandler:^(BOOL success, NSError * _Nullable error) {
//        if (success) {
//            NSLog(@"保存成功");
//        } else {
//            NSLog(@"保存圖片Error: %@", error.localizedDescription);
//        }
//    }];
    
    //PHAsset:查詢圖片/視屏
    PHFetchOptions *options = nil;
    PHFetchResult<PHAsset *> *createdAssets = [PHAsset fetchAssetsWithLocalIdentifiers:@[createdAssetId] options:options];
    return createdAssets;
}
  • 獲取指定相冊:
+ (PHAssetCollection *)getAlbumWithTitle:(NSString *)title {
    __block PHAssetCollection *createdCollection = nil;// 已經(jīng)創(chuàng)建的自定義相冊
    //PHAssetCollection: 查詢所有的自定義相冊
    PHFetchResult<PHAssetCollection *> *collections = [PHAssetCollection fetchAssetCollectionsWithType:PHAssetCollectionTypeAlbum subtype:PHAssetCollectionSubtypeAlbumRegular options:nil];
    [collections enumerateObjectsUsingBlock:^(PHAssetCollection * _Nonnull collection, NSUInteger idx, BOOL * _Nonnull stop) {
        if ([collection.localizedTitle isEqualToString:title]) {
            createdCollection = collection;
            *stop = YES;
        }
    }];

    if (!createdCollection) { // 沒有創(chuàng)建過相冊
        __block NSString *createdCollectionId = nil;
        [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
            //PHAssetCollectionChangeRequest:【增】相冊
            createdCollectionId = [PHAssetCollectionChangeRequest creationRequestForAssetCollectionWithTitle:title].placeholderForCreatedAssetCollection.localIdentifier;
        } error:nil];
        
        //PHAssetCollection:【查】出相冊
        createdCollection = [PHAssetCollection fetchAssetCollectionsWithLocalIdentifiers:@[createdCollectionId] options:nil].firstObject;
    }
    
    return createdCollection;
}
  • 保存圖片到 指定相冊:
+ (BOOL)addAssetsToAlbumWithAssets:(id<NSFastEnumeration>)assets withAlbum:(PHAssetCollection *)assetCollection {
    // 將剛才添加到【相機膠卷】的圖片驳概,引用(添加)到【自定義相冊】
    NSError *errorCollection = nil;
    [[PHPhotoLibrary sharedPhotoLibrary] performChangesAndWait:^{
        PHAssetCollectionChangeRequest *request = [PHAssetCollectionChangeRequest changeRequestForAssetCollection:assetCollection];
        // 自定義相冊封面默認保存第一張圖,所以使用以下方法把最新保存照片設為封面
        [request insertAssets:assets atIndexes:[NSIndexSet indexSetWithIndex:0]];
    } error:&errorCollection];
    
    // 保存結(jié)果
    if (errorCollection) {
        NSLog(@"保存到指定 相冊 失敵嘟馈!");
        return NO;
    } else {
        NSLog(@"保存到指定 相冊 成功顺又!");
        return YES;
    }
}

二更卒、錄頻

看下錄頻的操作:


AVCaptureMovieFileOutput

錄頻核心代碼:

- (void)startRecording {
    if (self.isRecording) return;
    AVCaptureDevice *device = [self activeCamera];
    //平滑對焦,減緩攝像頭對焦速度稚照。移動拍攝時蹂空,攝像頭會嘗試快速對焦
    if (device.isSmoothAutoFocusEnabled) {
        NSError *error;
        if ([device lockForConfiguration:&error]) {
            device.smoothAutoFocusEnabled = YES;
            [device unlockForConfiguration];
        } else {
            [self.delegate deviceConfigurationFailedWithError:error];
        }
    }
    
    AVCaptureConnection *connection = [self.movieOutput connectionWithMediaType:AVMediaTypeVideo];
    if (connection.isVideoOrientationSupported) {
        connection.videoOrientation = [self currentVideoOrientation];
    }
    //判斷是否支持視頻穩(wěn)定。提高視頻的質(zhì)量果录。
    if (connection.isVideoStabilizationSupported) {
        connection.preferredVideoStabilizationMode = AVCaptureVideoStabilizationModeAuto;
    }
    
    self.outputURL = [self uniqueURL];
    [self.movieOutput startRecordingToOutputFileURL:self.outputURL recordingDelegate:self];
}
  • 1上枕、我們首先需要拿到設置AVCaptureSession是創(chuàng)建的 視頻捕獲設備輸入(AVCaptureDeviceInput),然后取出設備(AVCaptureDevice)弱恒,配置設備的平滑對焦屬性辨萍。
  • 2、然后同樣需要拿到捕獲連接對象(AVCaptureConnection)斤彼,設置視頻的方向分瘦,否則在橫豎屏切換時會出現(xiàn)問題。并且需要設置preferredVideoStabilizationMode屬性提高視頻的質(zhì)量琉苇。
  • 3、調(diào)用startRecordingToOutputFileURL:recordingDelegate:方法開始錄屏悦施。
  • 4并扇、停止錄屏。
  • 5抡诞、錄屏結(jié)束后在代理方法中獲取到我們的視頻地址穷蛹。

錄屏結(jié)束后我們可能需要獲取視頻的某一幀圖片,用來顯示到UI上昼汗‰妊看下操作步驟:


流程圖很簡單,看下代碼:

//生成視頻縮略圖
- (void)generateThumbnailForVideoAtURL:(NSURL *)videoURL {
    dispatch_async(self.videoQueue, ^{
        AVAsset *asset = [AVAsset assetWithURL:videoURL];
        AVAssetImageGenerator *imageGenerator = [AVAssetImageGenerator assetImageGeneratorWithAsset:asset];
        //設置maximumSize 寬為100顷窒,高為0 根據(jù)視頻的寬高比來計算圖片的高度
        imageGenerator.maximumSize = CGSizeMake(100.0, 0.0);
        //捕捉視頻縮略圖會考慮視頻的變化(如視頻的方向變化)蛙吏,如果不設置,縮略圖的方向可能出錯.
        imageGenerator.appliesPreferredTrackTransform = YES;
        NSError *error;
        CGImageRef imageRef = [imageGenerator copyCGImageAtTime:kCMTimeZero actualTime:NULL error:&error];
        if (imageRef == nil) {
            NSLog(@"imageRefError: %@", error);
        }
        UIImage *image = [UIImage imageWithCGImage:imageRef];
        CGImageRelease(imageRef);
    });
}

到此我們的拍照和錄屏的核心功能已經(jīng)實現(xiàn)了鞋吉。下面介紹一下跟拍照錄屏相關(guān)的一些功能:切換攝像頭鸦做、聚焦、曝光谓着、閃光燈泼诱、手電筒。

切換攝像頭

我們現(xiàn)在的手機設備一般都有前置和后置攝像頭赊锚,所以我們這里就是對前置和后置攝像頭的切換治筒。

- (BOOL)switchCameras {
    AVCaptureDevice *currentDevice = [self activeCamera];
    AVCaptureDevice *device;
    if (currentDevice.position == AVCaptureDevicePositionBack) {
        device = [self cameraWithPosition:AVCaptureDevicePositionFront];
    } else {
        device = [self cameraWithPosition:AVCaptureDevicePositionBack];
    }
    if (device == nil) { return NO; }
    
    NSError *error;
    AVCaptureDeviceInput *deviceInput = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error];
    if (deviceInput) {
        [self.captureSession beginConfiguration];
        [self.captureSession removeInput:self.activeVideoInput];
        if ([self.captureSession canAddInput:deviceInput]) {
            [self.captureSession addInput:deviceInput];
            self.activeVideoInput = deviceInput;
        } else {
            [self.captureSession addInput:self.activeVideoInput];
        }
        //配置完成后. 會分批的將所有變更整合在一起屉栓。
        [self.captureSession commitConfiguration];
        return YES;
    } else {
        [self.delegate deviceConfigurationFailedWithError:error];
        return NO;
    }
}
  • 1、先拿到攝像頭設備device耸袜。
  • 2友多、將攝像頭包裝到AVCaptureDeviceInput類型的對象中。
  • 3句灌、一定要先調(diào)用beginConfiguration方法夷陋,準備配置。
  • 4胰锌、removeInput:移除原來的捕獲設備輸入對象(`AVCaptureDeviceInput )骗绕。
  • 5、判斷能否添加canAddInput:新的捕獲設備輸入對象(`AVCaptureDeviceInput )资昧。
  • 6酬土、如果可以就添加addInput:,設置為當前正在使用的捕獲設備輸入對象格带。
  • 7撤缴、如果不可以添加,再將原來的捕獲設備輸入對象(`AVCaptureDeviceInput )添加進去叽唱。
  • 8屈呕、最后調(diào)用commitConfiguration方法,分批的將所有變更整合在一起棺亭。

獲取前置或后置攝像頭的代碼:

- (AVCaptureDevice *)cameraWithPosition:(AVCaptureDevicePosition)position {
       //AVCaptureDeviceTypeBuiltIn Microphone:話筒
        //AVCaptureDeviceTypeBuiltIn WideAngleCamera:廣角照相機
        //AVCaptureDeviceTypeBuiltIn TelephotoCamera:長焦照相機
        //AVCaptureDeviceTypeBuiltIn UltraWideCamera:超寬攝影機
        //AVCaptureDeviceTypeBuiltIn DualCamera:雙攝像頭
        //AVCaptureDeviceTypeBuiltIn DualWideCamera:雙寬攝像頭
        //AVCaptureDeviceTypeBuiltIn TripleCamera:三重攝影機
        //AVCaptureDeviceTypeBuiltIn TrueDepthCamera:真深度照相機
        //AVCaptureDeviceTypeBuiltIn DuoCamera:雙后置攝像頭
        NSArray<AVCaptureDeviceType> *deviceTypes =@[
        AVCaptureDeviceTypeBuiltInMicrophone,
        AVCaptureDeviceTypeBuiltInTelephotoCamera,
        AVCaptureDeviceTypeBuiltInWideAngleCamera,
        AVCaptureDeviceTypeBuiltInDualCamera
        ];
    AVCaptureDeviceDiscoverySession *deviceDiscoverySession = [AVCaptureDeviceDiscoverySession discoverySessionWithDeviceTypes:deviceTypes mediaType:AVMediaTypeVideo position:position];
    return deviceDiscoverySession.devices.firstObject;
}

聚焦 & 曝光

  • 聚焦
- (void)focusAtPoint:(CGPoint)point {
    AVCaptureDevice *device = [self activeCamera];
    //是否支持興趣點聚焦 和 自動聚焦
    if (device.isFocusPointOfInterestSupported && [device isFocusModeSupported:AVCaptureFocusModeAutoFocus]) {
        NSError *error;
        if ([device lockForConfiguration:&error]) {//鎖定設備
            device.focusPointOfInterest = point;//聚焦點
            device.focusMode = AVCaptureFocusModeAutoFocus;//設置為自動聚焦
            [device unlockForConfiguration];//解鎖設備
        } 
    }
}
  • 曝光
- (void)exposeAtPoint:(CGPoint)point {
    AVCaptureDevice *device = [self activeCamera];
    AVCaptureExposureMode exposureMode = AVCaptureExposureModeContinuousAutoExposure;
    //是否支持興趣點曝光 和 持續(xù)自動曝光虎眨。
    if (device.isExposurePointOfInterestSupported && [device isExposureModeSupported:exposureMode]) {
        NSError *error;
        if ([device lockForConfiguration:&error]) {
            //配置期望值
            device.exposurePointOfInterest = point;
            device.exposureMode = exposureMode;
            //判斷設備是否支持鎖定曝光的模式。
            if ([device isExposureModeSupported:AVCaptureExposureModeLocked]) {
                
                //支持镶摘,則使用kvo確定設備的adjustingExposure屬性的狀態(tài)嗽桩。
                [device addObserver:self forKeyPath:@"adjustingExposure" options:NSKeyValueObservingOptionNew context:&THCameraAdjustingExposureContext];
            }
            [device unlockForConfiguration];
        } 
    }
}

這里曝光用到了kvo進行監(jiān)聽屬性的狀態(tài):

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
    if (context == &THCameraAdjustingExposureContext) {
        AVCaptureDevice *device = (AVCaptureDevice *)object;
        //判斷設備是否不再調(diào)整曝光等級,
        //確認設備的exposureMode是否可以設置為AVCaptureExposureModeLocked
        if(!device.isAdjustingExposure && [device isExposureModeSupported:AVCaptureExposureModeLocked]) {
            //移除作為adjustingExposure 的self凄敢,就不會得到后續(xù)變更的通知
            [object removeObserver:self forKeyPath:@"adjustingExposure" context:&THCameraAdjustingExposureContext];
            dispatch_async(dispatch_get_main_queue(), ^{
                NSError *error;
                if ([device lockForConfiguration:&error]) {
                    //修改exposureMode
                    device.exposureMode = AVCaptureExposureModeLocked;
                    [device unlockForConfiguration];
                } 
            });
        }
    } else {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    } 
}

閃光燈 & 手電筒

  • 閃光燈
- (void)setFlashMode:(AVCaptureFlashMode)flashMode {
    if ([self.photoOutput.supportedFlashModes containsObject:@(flashMode)]) {
        self.photoSettings.flashMode = flashMode;
    }
}
  • 手電筒
- (void)setTorchMode:(AVCaptureTorchMode)torchMode {
    AVCaptureDevice *device = [self activeCamera];
    if ([device isTorchModeSupported:torchMode]) {
        NSError *error;
        if ([device lockForConfiguration:&error]) {
            device.torchMode = torchMode;
            [device unlockForConfiguration];
        } 
    }
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末碌冶,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子涝缝,更是在濱河造成了極大的恐慌扑庞,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,682評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件俊卤,死亡現(xiàn)場離奇詭異嫩挤,居然都是意外死亡,警方通過查閱死者的電腦和手機消恍,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,277評論 3 395
  • 文/潘曉璐 我一進店門岂昭,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事约啊∫囟簦” “怎么了?”我有些...
    開封第一講書人閱讀 165,083評論 0 355
  • 文/不壞的土叔 我叫張陵恰矩,是天一觀的道長记盒。 經(jīng)常有香客問我,道長外傅,這世上最難降的妖魔是什么纪吮? 我笑而不...
    開封第一講書人閱讀 58,763評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮萎胰,結(jié)果婚禮上碾盟,老公的妹妹穿的比我還像新娘。我一直安慰自己技竟,他們只是感情好冰肴,可當我...
    茶點故事閱讀 67,785評論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著榔组,像睡著了一般熙尉。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上搓扯,一...
    開封第一講書人閱讀 51,624評論 1 305
  • 那天检痰,我揣著相機與錄音,去河邊找鬼锨推。 笑死攀细,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的爱态。 我是一名探鬼主播,決...
    沈念sama閱讀 40,358評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼境钟,長吁一口氣:“原來是場噩夢啊……” “哼锦担!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起慨削,我...
    開封第一講書人閱讀 39,261評論 0 276
  • 序言:老撾萬榮一對情侶失蹤洞渔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后缚态,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體磁椒,經(jīng)...
    沈念sama閱讀 45,722評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年玫芦,在試婚紗的時候發(fā)現(xiàn)自己被綠了浆熔。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,030評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡桥帆,死狀恐怖医增,靈堂內(nèi)的尸體忽然破棺而出慎皱,到底是詐尸還是另有隱情,我是刑警寧澤叶骨,帶...
    沈念sama閱讀 35,737評論 5 346
  • 正文 年R本政府宣布茫多,位于F島的核電站,受9級特大地震影響忽刽,放射性物質(zhì)發(fā)生泄漏天揖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,360評論 3 330
  • 文/蒙蒙 一跪帝、第九天 我趴在偏房一處隱蔽的房頂上張望今膊。 院中可真熱鬧,春花似錦歉甚、人聲如沸万细。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,941評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至聘裁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間衡便,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,057評論 1 270
  • 我被黑心中介騙來泰國打工镣陕, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人呆抑。 一個月前我還...
    沈念sama閱讀 48,237評論 3 371
  • 正文 我出身青樓,卻偏偏與公主長得像鹊碍,于是被迫代替她去往敵國和親厌殉。 傳聞我的和親對象是個殘疾皇子侈咕,可洞房花燭夜當晚...
    茶點故事閱讀 44,976評論 2 355