iOS AVPlayer自定義播放器

最近通過Avplayer自定義了一個(gè)視頻播放器.

項(xiàng)目框架#import <AVFoundation/AVFoundation.h>

1.首先播放網(wǎng)絡(luò)視頻.我需要獲取一個(gè)幀作為視頻簡(jiǎn)介圖片,還需要獲取視頻時(shí)長(zhǎng)來作為視頻的簡(jiǎn)介.

IMG_1047.PNG

這個(gè)時(shí)候我們需要AVURLAsset幫助獲取.

由于AVURLAsset是獲取數(shù)據(jù)是同步的,有時(shí)候會(huì)導(dǎo)致頁面卡頓,所以需要將上方法放到子線程.獲取完成在主線程更新視圖.

    //子線程獲取數(shù)據(jù)
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [weakSelf getThumbnailImageAndTotalTimeWithURL:weakSelf.videoURL];
    });
- (void)getThumbnailImageAndTotalTimeWithURL:(NSString *)videoURL {
    NSDictionary *opts = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:NO] forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
    AVURLAsset *urlAsset = [AVURLAsset URLAssetWithURL:[NSURL URLWithString:videoURL] options:opts];
    
    //獲取image
    AVAssetImageGenerator *assetImageGenerator =[[AVAssetImageGenerator alloc] initWithAsset:urlAsset];
    assetImageGenerator.appliesPreferredTrackTransform = YES;
    assetImageGenerator.maximumSize = CGSizeMake(self.videoImageView.frame.size.width, self.videoImageView.frame.size.height);
    NSError *error = nil;
    //獲取第一秒的幀
    CGImageRef imgRef = [assetImageGenerator copyCGImageAtTime:CMTimeMake(1.0, 1.0) actualTime:NULL error:&error];
    UIImage *image = [UIImage imageWithCGImage:imgRef];
    
    //獲取時(shí)長(zhǎng)
    self.totalTime = (CGFloat)(urlAsset.duration.value / urlAsset.duration.timescale);
    
    //需要在主線程進(jìn)行UI更新
    __weak typeof(self) weakSelf = self;
    dispatch_async(dispatch_get_main_queue(), ^{
        [weakSelf.videoImageView setImage:image];
        weakSelf.totalTimeL.text = [self getVideoLengthFromTimeLength:weakSelf.totalTime];
    });
    
}

2.播放器


IMG_1049.PNG

只是實(shí)現(xiàn)了一些基本的功能.大牛們就別噴我啦.

.h

#import <UIKit/UIKit.h>
#import <AVFoundation/AVFoundation.h>

@protocol VideoPlayerViewControllerDelegate <NSObject>
//點(diǎn)擊返回的回調(diào) time:觀看時(shí)間   isWatchFinish:是否觀看完成
- (void)moviePlayerVCCallbackWithTime:(CMTime)time isWatchFinish:(BOOL)isWatchFinish;
@end

@interface VideoPlayerViewController : UIViewController
@property (nonatomic, assign) id <VideoPlayerViewControllerDelegate> delegate;
@property (nonatomic, assign) CMTime watchCMTime;//觀看時(shí)間,外部傳入
@property (nonatomic, strong) NSURL *url;
@property (nonatomic, copy) NSString *titleStr;//title
@end

.m

#define TopViewHeight 50
#define BottomViewHeight 50
#define ViewWidth [UIScreen mainScreen].bounds.size.width
#define ViewHeight [UIScreen mainScreen].bounds.size.height

#import "VideoPlayerViewController.h"

@interface VideoPlayerViewController ()
//TopView
@property (nonatomic, strong) UIView *topView;
@property (nonatomic, strong) UIButton *backBtn;
@property (nonatomic, strong) UILabel *titleL;
//BottomView
@property (nonatomic, strong) UIView *bottomView;
@property (nonatomic, strong) UIButton *playBtn;
@property (nonatomic, strong) UILabel *timeL;
@property (nonatomic, strong) UISlider *videoSlider;

//Player
@property (nonatomic, strong) AVPlayer *player;
@property (nonatomic, strong) AVPlayerItem *playerItem;
//播放數(shù)據(jù)
@property (nonatomic, assign) CGFloat totalTime;
@property (nonatomic, assign) CMTime currentTime;
@property (nonatomic, assign) id timeObser;
@property (nonatomic, strong) NSTimer *avTimer;

//判斷狀態(tài)
@property (nonatomic, assign) BOOL isPlay;//是否播放
@property (nonatomic, assign) BOOL isShowToolView;//是否展示工具
@property (nonatomic, assign) BOOL isMoveSlider;//是否移動(dòng)滑竿
@property (nonatomic, assign) BOOL isWatchFinish;//是否觀看結(jié)束
@end

@implementation VideoPlayerViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [self prefersStatusBarHidden];
    self.isShowToolView = YES;
    self.isWatchFinish = NO;
    self.view.backgroundColor = [UIColor blackColor];
    [self layoutAVPlayer];
    [self layoutTopView];
    [self layoutBottomView];
    if (0.0 != self.watchCMTime.value && 0.0 != self.watchCMTime.timescale) {
        //已為您跳轉(zhuǎn)上次播放
        [self.player seekToTime:self.watchCMTime];
    }
    [self playerSetPlay:YES];
    //觸發(fā)計(jì)時(shí)
    [self.avTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:5]];
}

#pragma mark - AVPlayer
- (void)layoutAVPlayer {
    CGRect playerFrame = CGRectMake(0, 0, self.view.layer.bounds.size.height, self.view.layer.bounds.size.width);
    
    AVURLAsset *asset = [AVURLAsset assetWithURL: _url];
    //獲取視頻總時(shí)長(zhǎng)
    _totalTime = (CGFloat)(asset.duration.value / asset.duration.timescale);
    _playerItem = [AVPlayerItem playerItemWithAsset: asset];
    _player = [[AVPlayer alloc]initWithPlayerItem:_playerItem];
    
    AVPlayerLayer *playerLayer = [AVPlayerLayer playerLayerWithPlayer:_player];
    playerLayer.frame = playerFrame;
    playerLayer.videoGravity = AVLayerVideoGravityResizeAspect;
    [self.view.layer addSublayer:playerLayer];
    
    //Observer
    [self addVideoTimerObserver];
    [self addNotifications];
}

#pragma mark - TopView
- (void)layoutTopView {
    self.topView = [[UIView alloc]initWithFrame:CGRectMake(0, 0, self.view.bounds.size.height, TopViewHeight)];
    _topView.backgroundColor = [UIColor blackColor];
    _topView.alpha = 0.6;
    
    self.backBtn = [[UIButton alloc]initWithFrame:CGRectMake(20, 10, 30, 30)];
    [_backBtn setImage:[UIImage imageNamed:@"player_back"] forState:UIControlStateNormal];
    [_backBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [_backBtn addTarget:self action:@selector(backClick) forControlEvents:UIControlEventTouchUpInside];
    [_topView addSubview:_backBtn];
    
    self.titleL = [[UILabel alloc]initWithFrame:CGRectMake(70, 10, self.view.bounds.size.width - 140, 30)];
    _titleL.font = [UIFont fontWithName:@"STHeitiSC-Light" size:20];
    _titleL.backgroundColor = [UIColor clearColor];
    _titleL.text = self.titleStr;
    _titleL.textColor = [UIColor whiteColor];
    _titleL.textAlignment = NSTextAlignmentCenter;
    [_topView addSubview:_titleL];
    
    [self.view addSubview:_topView];
}

//返回Click
- (void)backClick {
    [self.player pause];
    if ([self.delegate respondsToSelector:@selector(moviePlayerVCCallbackWithTime:isWatchFinish:)]) {
        [self.delegate moviePlayerVCCallbackWithTime:self.currentTime isWatchFinish:self.isWatchFinish];
    }
    [self dismissViewControllerAnimated:YES completion:nil];
}

//設(shè)置Click
- (void)settingsClick:(UIButton *)btn {
    _isShowToolView = NO;
    [UIView animateWithDuration:0.5 animations:^{
        _topView.hidden = YES;
        _bottomView.hidden = YES;
        _videoSlider.hidden = YES;
    }];
}

#pragma mark - BottomView
- (void)layoutBottomView {
    _bottomView = [[UIView alloc]initWithFrame:CGRectMake(0, ViewWidth - BottomViewHeight, ViewHeight, BottomViewHeight)];
    _bottomView.backgroundColor = [UIColor blackColor];
    _bottomView.alpha = 0.6;
    [self.view addSubview:_bottomView];
    
    _playBtn = [[UIButton alloc]initWithFrame:CGRectMake(10, 10, 30, 30)];
    [_playBtn setImage:[UIImage imageNamed:@"player_play"] forState:UIControlStateNormal];
    [_playBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    [_playBtn addTarget:self action:@selector(playBtnClick:) forControlEvents:UIControlEventTouchUpInside];
    [_bottomView addSubview:_playBtn];
    
    _timeL = [[UILabel alloc]initWithFrame:CGRectMake(50, 10, self.view.bounds.size.height - 70, 30)];
    _timeL.backgroundColor = [UIColor clearColor];
    _timeL.textColor = [UIColor whiteColor];
    _timeL.textAlignment = NSTextAlignmentRight;
    [_bottomView addSubview:_timeL];
    //在totalTimeLabel上顯示總時(shí)間
    _timeL.text = [NSString stringWithFormat:@"00:00/%@", [self getVideoLengthFromTimeLength:_totalTime]];
    
    //進(jìn)度條
    self.videoSlider = [[UISlider alloc]initWithFrame:CGRectMake(0, _bottomView.frame.origin.y - 10, _bottomView.frame.size.width, 20)];
    [_videoSlider setMinimumTrackTintColor:[UIColor whiteColor]];
    [_videoSlider setMaximumTrackTintColor:[UIColor colorWithRed:0.49f green:0.48f blue:0.49f alpha:1.00f]];
    [_videoSlider setThumbImage:[UIImage imageNamed:@"video_slider_progressbar"] forState:UIControlStateNormal];
    [_videoSlider addTarget:self action:@selector(scrubbingDidBegin) forControlEvents:UIControlEventTouchDown];
    [_videoSlider addTarget:self action:@selector(sliderValueChanged) forControlEvents:UIControlEventValueChanged];
    [_videoSlider addTarget:self action:@selector(scrubbingDidEnd) forControlEvents:(UIControlEventTouchUpInside | UIControlEventTouchCancel)];
    [self.view addSubview:_videoSlider];
}

//按住滑塊
- (void)scrubbingDidBegin {
    //暫停播放
    [self playerSetPlay:NO];
    //停止計(jì)時(shí)
    [self.avTimer setFireDate:[NSDate distantFuture]];
    self.isMoveSlider = YES;
}

//滑動(dòng)值變化
- (void)sliderValueChanged {
    //設(shè)置滑動(dòng)的時(shí)間
    float dragedSeconds = floorf(self.totalTime * _videoSlider.value);
    CMTime newCMTime = CMTimeMake(dragedSeconds, 1.0);
    self.timeL.text = [NSString stringWithFormat:@"%@/%@", [self getStringFromCMTime:newCMTime], [self getVideoLengthFromTimeLength:self.totalTime]];
}

//釋放滑塊
- (void)scrubbingDidEnd {
    //1.通過實(shí)際百分比獲取秒數(shù)桐磁。
    float dragedSeconds = floorf(self.totalTime * _videoSlider.value);
    CMTime newCMTime = CMTimeMake(dragedSeconds, 1.0);
    //2.更新電影到實(shí)際秒數(shù)。
    [_player seekToTime:newCMTime];
    //3.重新開始播放
    [self playerSetPlay:YES];
    
    //重新開始計(jì)時(shí)
    [self.avTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:5]];
    self.isMoveSlider = NO;
}

//播放/暫停
- (void)playBtnClick:(UIButton *)btn{
    if (!_isPlay) {
        [self playerSetPlay:YES];
    } else {
        [self playerSetPlay:NO];
    }
}

#pragma mark - Set Play
- (void)playerSetPlay:(BOOL)isPlay{
    if (isPlay) {
        [_player play];
        _isPlay = YES;
        [_playBtn setImage:[UIImage imageNamed:@"player_pause"] forState:UIControlStateNormal];
    } else {
        [_player pause];
        _isPlay = NO;
        [_playBtn setImage:[UIImage imageNamed:@"player_play"] forState:UIControlStateNormal];
    }
}

#pragma mark - Touch
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
    CGPoint point = [[touches anyObject] locationInView:self.view];
    if (_isShowToolView) {
        //上下View為顯示狀態(tài)票渠,此時(shí)點(diǎn)擊上下View直接return
        if ((point.y > CGRectGetMinY(self.topView.frame) && point.y < CGRectGetMaxY(self.topView.frame)) || (point.y < CGRectGetMaxY(self.bottomView.frame) && point.y > CGRectGetMinY(self.bottomView.frame))) {
            return;
        }
        _isShowToolView = NO;
        [UIView animateWithDuration:0.5 animations:^{
            _topView.hidden = YES;
            _bottomView.hidden = YES;
            _videoSlider.hidden = YES;
        }];
        //上下視圖消失,關(guān)閉計(jì)時(shí)
        [self.avTimer setFireDate:[NSDate distantFuture]];
    } else {
        _isShowToolView = YES;
        [UIView animateWithDuration:0.5 animations:^{
            _topView.hidden = NO;
            _bottomView.hidden = NO;
            _videoSlider.hidden = NO;
        }];
        //上下視圖出現(xiàn),開啟計(jì)時(shí)
        [self.avTimer setFireDate:[NSDate dateWithTimeIntervalSinceNow:5]];
    }
}

#pragma mark - Timer
//計(jì)時(shí) 5秒Hide Bar
- (NSTimer *)avTimer {
    if (!_avTimer) {
        self.avTimer = [NSTimer scheduledTimerWithTimeInterval:0 target:self selector:@selector(handleHideBar) userInfo:nil repeats:YES];
    }
    return _avTimer;
}
- (void)handleHideBar {
    _isShowToolView = NO;
    [UIView animateWithDuration:0.5 animations:^{
        _topView.hidden = YES;
        _bottomView.hidden = YES;
        _videoSlider.hidden = YES;
    }];
    [self.avTimer setFireDate:[NSDate distantFuture]];
}


#pragma mark - 狀態(tài)欄與橫屏設(shè)置
//隱藏狀態(tài)欄
- (BOOL)prefersStatusBarHidden{
    return YES;
}
//默認(rèn)為右旋轉(zhuǎn)
- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation {
    return UIInterfaceOrientationLandscapeRight;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}


#pragma mark - TimerObserver
//檢測(cè)觀看時(shí)間
- (void)addVideoTimerObserver {
    __weak typeof(self) weakSelf = self;
    _timeObser = [_player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:NULL usingBlock:^(CMTime time) {
        weakSelf.currentTime = time;
        if (!weakSelf.isMoveSlider) {
            weakSelf.timeL.text = [NSString stringWithFormat:@"%@/%@", [weakSelf getStringFromCMTime:time], [weakSelf getVideoLengthFromTimeLength:weakSelf.totalTime]];
            CGFloat watchTime = time.value / time.timescale;
            CGFloat progress = watchTime / self.totalTime * 1.0f;
            [weakSelf.videoSlider setValue:progress animated:NO];
        }
    }];
}
- (void)removeVideoTimerObserver {
    [_player removeTimeObserver:_timeObser];
}

#pragma mark - Notifications
- (void)addNotifications {
    /*
     *  Video
     */
    //監(jiān)聽status屬性
    [self.playerItem addObserver:self forKeyPath:@"status"options:NSKeyValueObservingOptionNew context:nil];
    //視頻播放完成
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(playerItemDidReachEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:nil];
    
    /*
     *  Application
     */
    //進(jìn)入后臺(tái)
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterBackground) name:UIApplicationWillResignActiveNotification object:nil];
    //進(jìn)入前臺(tái)
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(appDidEnterPlayground) name:UIApplicationDidBecomeActiveNotification object:nil];
    //監(jiān)聽耳機(jī)狀態(tài)
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(audioRouteChangeListenerCallback:) name:UIApplicationDidBecomeActiveNotification object:nil];
}
- (void)removeNotifications {
    [self.playerItem removeObserver:self forKeyPath:@"status"];
    [[NSNotificationCenter defaultCenter] removeObserver:self];
}

#pragma mark - KVO
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context {
    if (object == self.playerItem) {
        if ([keyPath isEqualToString:@"status"]) {
            AVPlayerStatus status = [[change objectForKey:NSKeyValueChangeNewKey] integerValue];
            switch (status) {
                case AVPlayerStatusUnknown:
                {
                    NSLog(@"未知錯(cuò)誤:%@", self.playerItem.error);
                }
                    break;
                case AVPlayerStatusReadyToPlay:
                {
                    NSLog(@"準(zhǔn)備播放");
                }
                    break;
                case AVPlayerStatusFailed:
                {
                    NSLog(@"播放失敗:%@", self.playerItem.error);
                }
                    break;
                    
                default:
                    break;
            }
        }
    }
}
//觀看結(jié)束
- (void)playerItemDidReachEnd:(NSNotification *)notification {
    self.isWatchFinish = YES;
    [self backClick];
}
//進(jìn)入后臺(tái)
- (void)appDidEnterBackground {
    [self playerSetPlay:NO];
}
//進(jìn)入前臺(tái)
- (void)appDidEnterPlayground {
    
}
//檢測(cè)耳機(jī)狀態(tài)
- (void)audioRouteChangeListenerCallback:(NSNotification *)notification {
    NSDictionary *interuptionDict = notification.userInfo;
    NSInteger routeChangeReason = [[interuptionDict valueForKey:AVAudioSessionRouteChangeReasonKey] integerValue];
    switch (routeChangeReason) {
        case AVAudioSessionRouteChangeReasonNewDeviceAvailable:
            NSLog(@"耳機(jī)插入");
            break;
        case AVAudioSessionRouteChangeReasonOldDeviceUnavailable:
        {
            NSLog(@"耳機(jī)拔出");
            [self playerSetPlay:NO];
        }
            break;
            
        default:
            break;
    }
}

#pragma mark - Utils

- (NSString *)getStringFromCMTime:(CMTime)time {
    float currentTimeValue = (CGFloat)time.value/time.timescale;//得到當(dāng)前的播放時(shí)
    
    NSDate * currentDate = [NSDate dateWithTimeIntervalSince1970:currentTimeValue];
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    NSInteger unitFlags = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond ;
    NSDateComponents *components = [calendar components:unitFlags fromDate:currentDate];
    
    if (currentTimeValue >= 3600 ) {
        return [NSString stringWithFormat:@"%@:%@:%@",components.hour < 10 ? [NSString stringWithFormat:@"0%ld", (long)components.hour] : [NSString stringWithFormat:@"%ld", (long)components.hour], components.minute < 10 ? [NSString stringWithFormat:@"0%ld", (long)components.minute] : [NSString stringWithFormat:@"%ld", (long)components.minute], components.second < 10 ? [NSString stringWithFormat:@"0%ld", (long)components.second] : [NSString stringWithFormat:@"%ld", (long)components.second]];
    } else {
        return [NSString stringWithFormat:@"%@:%@",components.minute < 10 ? [NSString stringWithFormat:@"0%ld", (long)components.minute] : [NSString stringWithFormat:@"%ld", (long)components.minute], components.second < 10 ? [NSString stringWithFormat:@"0%ld", (long)components.second] : [NSString stringWithFormat:@"%ld", (long)components.second]];
    }
}

- (NSString *)getVideoLengthFromTimeLength:(CGFloat)timeLength {
    NSDate *date = [NSDate dateWithTimeIntervalSince1970:timeLength];
    NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSCalendarIdentifierGregorian];
    NSInteger unitFlags = NSCalendarUnitHour | NSCalendarUnitMinute | NSCalendarUnitSecond ;
    NSDateComponents *components = [calendar components:unitFlags fromDate:date];
    
    if (timeLength >= 3600 ) {
        return [NSString stringWithFormat:@"%@:%@:%@",components.hour < 10 ? [NSString stringWithFormat:@"0%ld", (long)components.hour] : [NSString stringWithFormat:@"%ld", (long)components.hour], components.minute < 10 ? [NSString stringWithFormat:@"0%ld", (long)components.minute] : [NSString stringWithFormat:@"%ld", (long)components.minute], components.second < 10 ? [NSString stringWithFormat:@"0%ld", (long)components.second] : [NSString stringWithFormat:@"%ld", (long)components.second]];
    } else {
        return [NSString stringWithFormat:@"%@:%@",components.minute < 10 ? [NSString stringWithFormat:@"0%ld", (long)components.minute] : [NSString stringWithFormat:@"%ld", (long)components.minute], components.second < 10 ? [NSString stringWithFormat:@"0%ld", (long)components.second] : [NSString stringWithFormat:@"%ld", (long)components.second]];
    }
}

#pragma mark - dealloc
//回收
- (void)dealloc {
    [self removeVideoTimerObserver];
    [self removeNotifications];
    [self.avTimer invalidate];
    self.avTimer = nil;
    self.player = nil;
    self.playerItem = nil;
}

@end

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末翩活,一起剝皮案震驚了整個(gè)濱河市阱洪,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌菠镇,老刑警劉巖冗荸,帶你破解...
    沈念sama閱讀 217,826評(píng)論 6 506
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異利耍,居然都是意外死亡蚌本,警方通過查閱死者的電腦和手機(jī)盔粹,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,968評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來魂毁,“玉大人玻佩,你說我怎么就攤上這事∠” “怎么了咬崔?”我有些...
    開封第一講書人閱讀 164,234評(píng)論 0 354
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)烦秩。 經(jīng)常有香客問我垮斯,道長(zhǎng),這世上最難降的妖魔是什么只祠? 我笑而不...
    開封第一講書人閱讀 58,562評(píng)論 1 293
  • 正文 為了忘掉前任兜蠕,我火速辦了婚禮,結(jié)果婚禮上抛寝,老公的妹妹穿的比我還像新娘熊杨。我一直安慰自己,他們只是感情好盗舰,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,611評(píng)論 6 392
  • 文/花漫 我一把揭開白布晶府。 她就那樣靜靜地躺著,像睡著了一般钻趋。 火紅的嫁衣襯著肌膚如雪川陆。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,482評(píng)論 1 302
  • 那天蛮位,我揣著相機(jī)與錄音较沪,去河邊找鬼。 笑死失仁,一個(gè)胖子當(dāng)著我的面吹牛尸曼,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播萄焦,決...
    沈念sama閱讀 40,271評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼骡苞,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了楷扬?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,166評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤贴见,失蹤者是張志新(化名)和其女友劉穎烘苹,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體片部,經(jīng)...
    沈念sama閱讀 45,608評(píng)論 1 314
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡镣衡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,814評(píng)論 3 336
  • 正文 我和宋清朗相戀三年霜定,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片廊鸥。...
    茶點(diǎn)故事閱讀 39,926評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡望浩,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出惰说,到底是詐尸還是另有隱情磨德,我是刑警寧澤,帶...
    沈念sama閱讀 35,644評(píng)論 5 346
  • 正文 年R本政府宣布吆视,位于F島的核電站典挑,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏啦吧。R本人自食惡果不足惜您觉,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,249評(píng)論 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望授滓。 院中可真熱鬧琳水,春花似錦、人聲如沸般堆。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,866評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽郁妈。三九已至浑玛,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間噩咪,已是汗流浹背顾彰。 一陣腳步聲響...
    開封第一講書人閱讀 32,991評(píng)論 1 269
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留胃碾,地道東北人涨享。 一個(gè)月前我還...
    沈念sama閱讀 48,063評(píng)論 3 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像仆百,于是被迫代替她去往敵國(guó)和親厕隧。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,871評(píng)論 2 354

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