iOS音視頻學(xué)習(xí)10——AVFoundation錄視頻

視頻錄制

其實(shí)有了前面的拍照應(yīng)用之后要在此基礎(chǔ)上做視頻錄制功能并不復(fù)雜,程序只需要做如下修改:

  1. 添加一個(gè)音頻輸入到會話(使用[[AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio] firstObject]獲得輸入設(shè)備褥影,然后根據(jù)此輸入設(shè)備創(chuàng)建一個(gè)設(shè)備輸入對象)墓毒,在拍照程序中已經(jīng)添加了視頻輸入所以此時(shí)不需要添加視頻輸入强重。
  2. 創(chuàng)建一個(gè)音樂播放文件輸出對象AVCaptureMovieFileOutput取代原來的照片輸出對象挑宠。
  3. 將捕獲到的視頻數(shù)據(jù)寫入到臨時(shí)文件并在停止錄制之后保存到相簿(通過AVCaptureMovieFileOutput的代理方法)。

相比拍照程序郑口,程序的修改主要就是以上三點(diǎn)鸳碧。當(dāng)然為了讓程序更加完善在下面的視頻錄制程序中加入了屏幕旋轉(zhuǎn)視頻盾鳞、自動布局和后臺保存任務(wù)等細(xì)節(jié)犬性。下面是修改后的程序:

//
//  ViewController.m
//  AVFoundationCamera
//
//  Created by Kenshin Cui on 14/04/05.
//  Copyright (c) 2014年 cmjstudio. All rights reserved.
//  視頻錄制

#import "ViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <AssetsLibrary/AssetsLibrary.h>
typedef void(^PropertyChangeBlock)(AVCaptureDevice *captureDevice);

@interface ViewController ()<AVCaptureFileOutputRecordingDelegate>//視頻文件輸出代理

@property (strong,nonatomic) AVCaptureSession *captureSession;//負(fù)責(zé)輸入和輸出設(shè)備之間的數(shù)據(jù)傳遞
@property (strong,nonatomic) AVCaptureDeviceInput *captureDeviceInput;//負(fù)責(zé)從AVCaptureDevice獲得輸入數(shù)據(jù)
@property (strong,nonatomic) AVCaptureMovieFileOutput *captureMovieFileOutput;//視頻輸出流
@property (strong,nonatomic) AVCaptureVideoPreviewLayer *captureVideoPreviewLayer;//相機(jī)拍攝預(yù)覽圖層
@property (assign,nonatomic) BOOL enableRotation;//是否允許旋轉(zhuǎn)(注意在視頻錄制過程中禁止屏幕旋轉(zhuǎn))
@property (assign,nonatomic) CGRect *lastBounds;//旋轉(zhuǎn)的前大小
@property (assign,nonatomic) UIBackgroundTaskIdentifier backgroundTaskIdentifier;//后臺任務(wù)標(biāo)識
@property (weak, nonatomic) IBOutlet UIView *viewContainer;
@property (weak, nonatomic) IBOutlet UIButton *takeButton;//拍照按鈕
@property (weak, nonatomic) IBOutlet UIImageView *focusCursor; //聚焦光標(biāo)


@end

@implementation ViewController

#pragma mark - 控制器視圖方法
- (void)viewDidLoad {
    [super viewDidLoad];
}

-(void)viewWillAppear:(BOOL)animated{
    [super viewWillAppear:animated];
    //初始化會話
    _captureSession=[[AVCaptureSession alloc]init];
    if ([_captureSession canSetSessionPreset:AVCaptureSessionPreset1280x720]) {//設(shè)置分辨率
        _captureSession.sessionPreset=AVCaptureSessionPreset1280x720;
    }
    //獲得輸入設(shè)備
    AVCaptureDevice *captureDevice=[self getCameraDeviceWithPosition:AVCaptureDevicePositionBack];//取得后置攝像頭
    if (!captureDevice) {
        NSLog(@"取得后置攝像頭時(shí)出現(xiàn)問題.");
        return;
    }
    //添加一個(gè)音頻輸入設(shè)備
    AVCaptureDevice *audioCaptureDevice=[[AVCaptureDevice devicesWithMediaType:AVMediaTypeAudio] firstObject];
    
    
    NSError *error=nil;
    //根據(jù)輸入設(shè)備初始化設(shè)備輸入對象,用于獲得輸入數(shù)據(jù)
    _captureDeviceInput=[[AVCaptureDeviceInput alloc]initWithDevice:captureDevice error:&error];
    if (error) {
        NSLog(@"取得設(shè)備輸入對象時(shí)出錯(cuò)腾仅,錯(cuò)誤原因:%@",error.localizedDescription);
        return;
    }
    AVCaptureDeviceInput *audioCaptureDeviceInput=[[AVCaptureDeviceInput alloc]initWithDevice:audioCaptureDevice error:&error];
    if (error) {
        NSLog(@"取得設(shè)備輸入對象時(shí)出錯(cuò)乒裆,錯(cuò)誤原因:%@",error.localizedDescription);
        return;
    }
    //初始化設(shè)備輸出對象,用于獲得輸出數(shù)據(jù)
    _captureMovieFileOutput=[[AVCaptureMovieFileOutput alloc]init];
    
    //將設(shè)備輸入添加到會話中
    if ([_captureSession canAddInput:_captureDeviceInput]) {
        [_captureSession addInput:_captureDeviceInput];
        [_captureSession addInput:audioCaptureDeviceInput];
        AVCaptureConnection *captureConnection=[_captureMovieFileOutput connectionWithMediaType:AVMediaTypeVideo];
        if ([captureConnection isVideoStabilizationSupported ]) {
            captureConnection.preferredVideoStabilizationMode=AVCaptureVideoStabilizationModeAuto;
        }
    }
    
    //將設(shè)備輸出添加到會話中
    if ([_captureSession canAddOutput:_captureMovieFileOutput]) {
        [_captureSession addOutput:_captureMovieFileOutput];
    }
    
    //創(chuàng)建視頻預(yù)覽層推励,用于實(shí)時(shí)展示攝像頭狀態(tài)
    _captureVideoPreviewLayer=[[AVCaptureVideoPreviewLayer alloc]initWithSession:self.captureSession];
    
    CALayer *layer=self.viewContainer.layer;
    layer.masksToBounds=YES;
    
    _captureVideoPreviewLayer.frame=layer.bounds;
    _captureVideoPreviewLayer.videoGravity=AVLayerVideoGravityResizeAspectFill;//填充模式
    //將視頻預(yù)覽層添加到界面中
    //[layer addSublayer:_captureVideoPreviewLayer];
    [layer insertSublayer:_captureVideoPreviewLayer below:self.focusCursor.layer];
    
    _enableRotation=YES;
    [self addNotificationToCaptureDevice:captureDevice];
    [self addGenstureRecognizer];
}

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

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

-(BOOL)shouldAutorotate{
    return self.enableRotation;
}

////屏幕旋轉(zhuǎn)時(shí)調(diào)整視頻預(yù)覽圖層的方向
//-(void)willTransitionToTraitCollection:(UITraitCollection *)newCollection withTransitionCoordinator:(id<UIViewControllerTransitionCoordinator>)coordinator{
//    [super willTransitionToTraitCollection:newCollection withTransitionCoordinator:coordinator];
////    NSLog(@"%i,%i",newCollection.verticalSizeClass,newCollection.horizontalSizeClass);
//    UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];
//    NSLog(@"%i",orientation);
//    AVCaptureConnection *captureConnection=[self.captureVideoPreviewLayer connection];
//    captureConnection.videoOrientation=orientation;
//
//}
//屏幕旋轉(zhuǎn)時(shí)調(diào)整視頻預(yù)覽圖層的方向
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration{
    AVCaptureConnection *captureConnection=[self.captureVideoPreviewLayer connection];
    captureConnection.videoOrientation=(AVCaptureVideoOrientation)toInterfaceOrientation;
}
//旋轉(zhuǎn)后重新設(shè)置大小
-(void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation{
    _captureVideoPreviewLayer.frame=self.viewContainer.bounds;
}

-(void)dealloc{
    [self removeNotification];
}
#pragma mark - UI方法
#pragma mark 視頻錄制
- (IBAction)takeButtonClick:(UIButton *)sender {
    //根據(jù)設(shè)備輸出獲得連接
    AVCaptureConnection *captureConnection=[self.captureMovieFileOutput connectionWithMediaType:AVMediaTypeVideo];
    //根據(jù)連接取得設(shè)備輸出的數(shù)據(jù)
    if (![self.captureMovieFileOutput isRecording]) {
        self.enableRotation=NO;
        //如果支持多任務(wù)則則開始多任務(wù)
        if ([[UIDevice currentDevice] isMultitaskingSupported]) {
            self.backgroundTaskIdentifier=[[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:nil];
        }
        //預(yù)覽圖層和視頻方向保持一致
        captureConnection.videoOrientation=[self.captureVideoPreviewLayer connection].videoOrientation;
        NSString *outputFielPath=[NSTemporaryDirectory() stringByAppendingString:@"myMovie.mov"];
        NSLog(@"save path is :%@",outputFielPath);
        NSURL *fileUrl=[NSURL fileURLWithPath:outputFielPath];
        [self.captureMovieFileOutput startRecordingToOutputFileURL:fileUrl recordingDelegate:self];
    }
    else{
        [self.captureMovieFileOutput stopRecording];//停止錄制
    }
}
#pragma mark 切換前后攝像頭
- (IBAction)toggleButtonClick:(UIButton *)sender {
    AVCaptureDevice *currentDevice=[self.captureDeviceInput device];
    AVCaptureDevicePosition currentPosition=[currentDevice position];
    [self removeNotificationFromCaptureDevice:currentDevice];
    AVCaptureDevice *toChangeDevice;
    AVCaptureDevicePosition toChangePosition=AVCaptureDevicePositionFront;
    if (currentPosition==AVCaptureDevicePositionUnspecified||currentPosition==AVCaptureDevicePositionFront) {
        toChangePosition=AVCaptureDevicePositionBack;
    }
    toChangeDevice=[self getCameraDeviceWithPosition:toChangePosition];
    [self addNotificationToCaptureDevice:toChangeDevice];
    //獲得要調(diào)整的設(shè)備輸入對象
    AVCaptureDeviceInput *toChangeDeviceInput=[[AVCaptureDeviceInput alloc]initWithDevice:toChangeDevice error:nil];
    
    //改變會話的配置前一定要先開啟配置鹤耍,配置完成后提交配置改變
    [self.captureSession beginConfiguration];
    //移除原有輸入對象
    [self.captureSession removeInput:self.captureDeviceInput];
    //添加新的輸入對象
    if ([self.captureSession canAddInput:toChangeDeviceInput]) {
        [self.captureSession addInput:toChangeDeviceInput];
        self.captureDeviceInput=toChangeDeviceInput;
    }
    //提交會話配置
    [self.captureSession commitConfiguration];
    
}

#pragma mark - 視頻輸出代理
-(void)captureOutput:(AVCaptureFileOutput *)captureOutput didStartRecordingToOutputFileAtURL:(NSURL *)fileURL fromConnections:(NSArray *)connections{
    NSLog(@"開始錄制...");
}
-(void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error{
    NSLog(@"視頻錄制完成.");
    //視頻錄入完成之后在后臺將視頻存儲到相簿
    self.enableRotation=YES;
    UIBackgroundTaskIdentifier lastBackgroundTaskIdentifier=self.backgroundTaskIdentifier;
    self.backgroundTaskIdentifier=UIBackgroundTaskInvalid;
    ALAssetsLibrary *assetsLibrary=[[ALAssetsLibrary alloc]init];
    [assetsLibrary writeVideoAtPathToSavedPhotosAlbum:outputFileURL completionBlock:^(NSURL *assetURL, NSError *error) {
        if (error) {
            NSLog(@"保存視頻到相簿過程中發(fā)生錯(cuò)誤肉迫,錯(cuò)誤信息:%@",error.localizedDescription);
        }
        if (lastBackgroundTaskIdentifier!=UIBackgroundTaskInvalid) {
            [[UIApplication sharedApplication] endBackgroundTask:lastBackgroundTaskIdentifier];
        }
        NSLog(@"成功保存視頻到相簿.");
    }];
    
}

#pragma mark - 通知
/**
 *  給輸入設(shè)備添加通知
 */
-(void)addNotificationToCaptureDevice:(AVCaptureDevice *)captureDevice{
    //注意添加區(qū)域改變捕獲通知必須首先設(shè)置設(shè)備允許捕獲
    [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
        captureDevice.subjectAreaChangeMonitoringEnabled=YES;
    }];
    NSNotificationCenter *notificationCenter= [NSNotificationCenter defaultCenter];
    //捕獲區(qū)域發(fā)生改變
    [notificationCenter addObserver:self selector:@selector(areaChange:) name:AVCaptureDeviceSubjectAreaDidChangeNotification object:captureDevice];
}
-(void)removeNotificationFromCaptureDevice:(AVCaptureDevice *)captureDevice{
    NSNotificationCenter *notificationCenter= [NSNotificationCenter defaultCenter];
    [notificationCenter removeObserver:self name:AVCaptureDeviceSubjectAreaDidChangeNotification object:captureDevice];
}
/**
 *  移除所有通知
 */
-(void)removeNotification{
    NSNotificationCenter *notificationCenter= [NSNotificationCenter defaultCenter];
    [notificationCenter removeObserver:self];
}

-(void)addNotificationToCaptureSession:(AVCaptureSession *)captureSession{
    NSNotificationCenter *notificationCenter= [NSNotificationCenter defaultCenter];
    //會話出錯(cuò)
    [notificationCenter addObserver:self selector:@selector(sessionRuntimeError:) name:AVCaptureSessionRuntimeErrorNotification object:captureSession];
}

/**
 *  設(shè)備連接成功
 *
 *  @param notification 通知對象
 */
-(void)deviceConnected:(NSNotification *)notification{
    NSLog(@"設(shè)備已連接...");
}
/**
 *  設(shè)備連接斷開
 *
 *  @param notification 通知對象
 */
-(void)deviceDisconnected:(NSNotification *)notification{
    NSLog(@"設(shè)備已斷開.");
}
/**
 *  捕獲區(qū)域改變
 *
 *  @param notification 通知對象
 */
-(void)areaChange:(NSNotification *)notification{
    NSLog(@"捕獲區(qū)域改變...");
}

/**
 *  會話出錯(cuò)
 *
 *  @param notification 通知對象
 */
-(void)sessionRuntimeError:(NSNotification *)notification{
    NSLog(@"會話發(fā)生錯(cuò)誤.");
}

#pragma mark - 私有方法

/**
 *  取得指定位置的攝像頭
 *
 *  @param position 攝像頭位置
 *
 *  @return 攝像頭設(shè)備
 */
-(AVCaptureDevice *)getCameraDeviceWithPosition:(AVCaptureDevicePosition )position{
    NSArray *cameras= [AVCaptureDevice devicesWithMediaType:AVMediaTypeVideo];
    for (AVCaptureDevice *camera in cameras) {
        if ([camera position]==position) {
            return camera;
        }
    }
    return nil;
}

/**
 *  改變設(shè)備屬性的統(tǒng)一操作方法
 *
 *  @param propertyChange 屬性改變操作
 */
-(void)changeDeviceProperty:(PropertyChangeBlock)propertyChange{
    AVCaptureDevice *captureDevice= [self.captureDeviceInput device];
    NSError *error;
    //注意改變設(shè)備屬性前一定要首先調(diào)用lockForConfiguration:調(diào)用完之后使用unlockForConfiguration方法解鎖
    if ([captureDevice lockForConfiguration:&error]) {
        propertyChange(captureDevice);
        [captureDevice unlockForConfiguration];
    }else{
        NSLog(@"設(shè)置設(shè)備屬性過程發(fā)生錯(cuò)誤,錯(cuò)誤信息:%@",error.localizedDescription);
    }
}

/**
 *  設(shè)置閃光燈模式
 *
 *  @param flashMode 閃光燈模式
 */
//-(void)setFlashMode:(AVCaptureFlashMode )flashMode{
//    [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
//        if ([captureDevice isFlashModeSupported:flashMode]) {
//            [captureDevice setFlashMode:flashMode];
//        }
//    }];
//}
/**
 *  設(shè)置聚焦模式
 *
 *  @param focusMode 聚焦模式
 */
-(void)setFocusMode:(AVCaptureFocusMode )focusMode{
    [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
        if ([captureDevice isFocusModeSupported:focusMode]) {
            [captureDevice setFocusMode:focusMode];
        }
    }];
}
/**
 *  設(shè)置曝光模式
 *
 *  @param exposureMode 曝光模式
 */
-(void)setExposureMode:(AVCaptureExposureMode)exposureMode{
    [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
        if ([captureDevice isExposureModeSupported:exposureMode]) {
            [captureDevice setExposureMode:exposureMode];
        }
    }];
}
/**
 *  設(shè)置聚焦點(diǎn)
 *
 *  @param point 聚焦點(diǎn)
 */
-(void)focusWithMode:(AVCaptureFocusMode)focusMode exposureMode:(AVCaptureExposureMode)exposureMode atPoint:(CGPoint)point{
    [self changeDeviceProperty:^(AVCaptureDevice *captureDevice) {
        if ([captureDevice isFocusModeSupported:focusMode]) {
            [captureDevice setFocusMode:AVCaptureFocusModeAutoFocus];
        }
        if ([captureDevice isFocusPointOfInterestSupported]) {
            [captureDevice setFocusPointOfInterest:point];
        }
        if ([captureDevice isExposureModeSupported:exposureMode]) {
            [captureDevice setExposureMode:AVCaptureExposureModeAutoExpose];
        }
        if ([captureDevice isExposurePointOfInterestSupported]) {
            [captureDevice setExposurePointOfInterest:point];
        }
    }];
}

/**
 *  添加點(diǎn)按手勢稿黄,點(diǎn)按時(shí)聚焦
 */
-(void)addGenstureRecognizer{
    UITapGestureRecognizer *tapGesture=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(tapScreen:)];
    [self.viewContainer addGestureRecognizer:tapGesture];
}
-(void)tapScreen:(UITapGestureRecognizer *)tapGesture{
    CGPoint point= [tapGesture locationInView:self.viewContainer];
    //將UI坐標(biāo)轉(zhuǎn)化為攝像頭坐標(biāo)
    CGPoint cameraPoint= [self.captureVideoPreviewLayer captureDevicePointOfInterestForPoint:point];
    [self setFocusCursorWithPoint:point];
    [self focusWithMode:AVCaptureFocusModeAutoFocus exposureMode:AVCaptureExposureModeAutoExpose atPoint:cameraPoint];
}

/**
 *  設(shè)置聚焦光標(biāo)位置
 *
 *  @param point 光標(biāo)位置
 */
-(void)setFocusCursorWithPoint:(CGPoint)point{
    self.focusCursor.center=point;
    self.focusCursor.transform=CGAffineTransformMakeScale(1.5, 1.5);
    self.focusCursor.alpha=1.0;
    [UIView animateWithDuration:1.0 animations:^{
        self.focusCursor.transform=CGAffineTransformIdentity;
    } completion:^(BOOL finished) {
        self.focusCursor.alpha=0;
        
    }];
}
@end
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末喊衫,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子杆怕,更是在濱河造成了極大的恐慌族购,老刑警劉巖,帶你破解...
    沈念sama閱讀 223,126評論 6 520
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件陵珍,死亡現(xiàn)場離奇詭異寝杖,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)互纯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 95,421評論 3 400
  • 文/潘曉璐 我一進(jìn)店門瑟幕,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人留潦,你說我怎么就攤上這事只盹。” “怎么了愤兵?”我有些...
    開封第一講書人閱讀 169,941評論 0 366
  • 文/不壞的土叔 我叫張陵鹿霸,是天一觀的道長。 經(jīng)常有香客問我秆乳,道長懦鼠,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 60,294評論 1 300
  • 正文 為了忘掉前任屹堰,我火速辦了婚禮肛冶,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘扯键。我一直安慰自己睦袖,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 69,295評論 6 398
  • 文/花漫 我一把揭開白布荣刑。 她就那樣靜靜地躺著馅笙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪厉亏。 梳的紋絲不亂的頭發(fā)上董习,一...
    開封第一講書人閱讀 52,874評論 1 314
  • 那天,我揣著相機(jī)與錄音爱只,去河邊找鬼皿淋。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的窝趣。 我是一名探鬼主播疯暑,決...
    沈念sama閱讀 41,285評論 3 424
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼哑舒!你這毒婦竟也來了妇拯?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 40,249評論 0 277
  • 序言:老撾萬榮一對情侶失蹤洗鸵,失蹤者是張志新(化名)和其女友劉穎乖阵,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體预麸,經(jīng)...
    沈念sama閱讀 46,760評論 1 321
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瞪浸,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,840評論 3 343
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了吏祸。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片对蒲。...
    茶點(diǎn)故事閱讀 40,973評論 1 354
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖贡翘,靈堂內(nèi)的尸體忽然破棺而出蹈矮,到底是詐尸還是另有隱情,我是刑警寧澤鸣驱,帶...
    沈念sama閱讀 36,631評論 5 351
  • 正文 年R本政府宣布泛鸟,位于F島的核電站,受9級特大地震影響踊东,放射性物質(zhì)發(fā)生泄漏北滥。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 42,315評論 3 336
  • 文/蒙蒙 一闸翅、第九天 我趴在偏房一處隱蔽的房頂上張望再芋。 院中可真熱鬧,春花似錦坚冀、人聲如沸济赎。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,797評論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽司训。三九已至,卻和暖如春液南,著一層夾襖步出監(jiān)牢的瞬間壳猜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,926評論 1 275
  • 我被黑心中介騙來泰國打工贺拣, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留蓖谢,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 49,431評論 3 379
  • 正文 我出身青樓譬涡,卻偏偏與公主長得像闪幽,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子涡匀,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,982評論 2 361

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