AVPlayer做的一个小视频播放器,包含快进快退音量调节等基本功能

用AVFoundation的AVPlayer做的一个小视频播放器,包含左滑快退,右滑快进,上滑音量加,下滑音量减等基本功能。
支持HLS协议和HTTP协议的视频。

#import "AppDelegate.h"
#import "PlayViewController.h"

@interface AppDelegate ()

@end

@implementation AppDelegate

- (BOOL)application:(UIApplication \*)application didFinishLaunchingWithOptions:(NSDictionary \*)launchOptions {
    PlayViewController \*player=[[PlayViewController alloc]init];
    
    //HLS协议视屏
    //http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8
    //HTTP视频
    //http://www.modrails.com/videos/passenger_nginx.mov
    
    player.urlString=@"http://devimages.apple.com/iphone/samples/bipbop/bipbopall.m3u8";
    player.title=@"播放测试";
    self.window.rootViewController=player;
    
    return YES;
}

@end
#import "PlayViewController.h"
#import <AVFoundation/AVFoundation.h>
#import <MediaPlayer/MediaPlayer.h>
#import "Tools.h"
#import "FGGReachability.h"

@interface PlayViewController ()
@property(nonatomic,strong)AVPlayer \*player;
@property(nonatomic,strong)AVPlayerItem \*item;
@property(nonatomic,strong)NSString \*totalTime;
@property(nonatomic,assign)BOOL isPlaying;
@property(nonatomic,strong)id timeObserver;
@property(nonatomic,strong)UIProgressView \*progress;

@property(nonatomic,strong)UISlider \*slider;      //进度slider
@property(nonatomic,strong)UISlider \*volumeSlider;//音量slider

@property(nonatomic,strong)UIButton \*playBtn;
@property(nonatomic,strong)UILabel \*timeLabel;
@property(nonatomic,strong)id playbackTimeObserver;

//快进
@property(nonatomic,strong)UIImageView \*forward;
//快退
@property(nonatomic,strong)UIImageView \*backward;

@property(nonatomic,strong)UILabel \*volumeLabel;//调节音量时显示当前音量
@property(nonatomic,strong)UIButton \*shareBtn;//分享

//加载指示器
@property(nonatomic,strong)UIActivityIndicatorView *indicator;

//判断网络
@property(nonatomic,strong)Reachability \*reach;

@end

#define kWidth ([UIScreen mainScreen].bounds.size.width)
#define kHeight ([UIScreen mainScreen].bounds.size.height)

@implementation PlayViewController

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
//    隐藏导航栏
    self.navigationController.navigationBarHidden=YES;
}
-(void)showIndicator
{
    _indicator=[[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
    _indicator.center=CGPointMake(kHeight/2, kWidth/2);
    [self.view addSubview:_indicator];
    [_indicator startAnimating];
}
//隐藏状态栏
- (BOOL)prefersStatusBarHidden
{
    return YES;
}
- (void)viewDidLoad
{
    [super viewDidLoad];
    self.view.backgroundColor=[UIColor blackColor];
    //显示网络记载指示器
    [self showIndicator];
    NSLog(@"\n-->%@\n-->%@",self.urlString,self.videoTitle);
    
    //通知中心注册一条监听网络状态的通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(estimateNetworkStatus) name:kReachabilityChangedNotification object:nil];
    _reach=[Reachability reachabilityForInternetConnection];
    [_reach startNotifier];
    
    [self estimateNetworkStatus];
    
    _item=[[AVPlayerItem alloc] initWithURL:[NSURL URLWithString:self.urlString]];
    _player=[[AVPlayer alloc]initWithPlayerItem:_item];
    
    [_item addObserver:self forKeyPath:@"status" options:NSKeyValueObservingOptionNew context:nil];// 监听status属性
    [_item addObserver:self forKeyPath:@"loadedTimeRanges" options:NSKeyValueObservingOptionNew context:nil];// 监听loadedTimeRanges属性
    
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(moviePlayDidEnd:) name:AVPlayerItemDidPlayToEndTimeNotification object:_item];
    
    AVPlayerLayer \*layer=[AVPlayerLayer playerLayerWithPlayer:_player];
    layer.videoGravity=AVLayerVideoGravityResizeAspect;
    layer.frame=CGRectMake(0, 0, kHeight, kWidth);
    layer.backgroundColor=[UIColor clearColor].CGColor;
    
    [self.view.layer addSublayer:layer];
    
    //    标题
    [self createTitleView];
    //    界面
    [self createUI];
    
    //旋转视图
    //self.view.transform=CGAffineTransformMakeRotation(3\*M_PI_2);
    //layer.transform=CATransform3DMakeRotation(M_PI/2, 0, 0, 1);
    self.view.layer.transform=CATransform3DMakeRotation(3\*M_PI_2, 0, 0, 1);
    
    [self addGestures];

}
/\*\*
 \*  添加手势
 \*/
-(void)addGestures
{
    //添加一个手势 隐藏与显示进度条
    UITapGestureRecognizer \*tap=[[UITapGestureRecognizer alloc]initWithTarget:self action:@selector(shiftStatus)];
    [self.view addGestureRecognizer:tap];
    
    //增加音量的手势
    UISwipeGestureRecognizer \*increaseGesture=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(increaseVolume:)];
    increaseGesture.direction=UISwipeGestureRecognizerDirectionUp;
    [self.view addGestureRecognizer:increaseGesture];
    
    //减小音量的手势
    UISwipeGestureRecognizer \*decreaseGesture=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(decreaseVolume:)];
    decreaseGesture.direction=UISwipeGestureRecognizerDirectionDown;
    [self.view addGestureRecognizer:decreaseGesture];
    
    //快进
    UISwipeGestureRecognizer \*stepForward=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(stepForward10Seconds)];
    stepForward.direction=UISwipeGestureRecognizerDirectionRight;
    //快退
    UISwipeGestureRecognizer \*stepBackward=[[UISwipeGestureRecognizer alloc]initWithTarget:self action:@selector(stepBackward10Senconds)];
    stepBackward.direction=UISwipeGestureRecognizerDirectionLeft;
    [self.view addGestureRecognizer:stepForward];
    [self.view addGestureRecognizer:stepBackward];
}
/\*\*
 \*  评估网络状态
 \*/
-(void)estimateNetworkStatus
{
    FGGNetWorkStatus status=[FGGReachability networkStatus];
    if(status==FGGNetWorkStatusNotReachable)
    {
        UIAlertView \*alert=[[UIAlertView alloc]initWithTitle:@"提示"
                                                     message:@"当前网络不可用"
                                                    delegate:nil
                                           cancelButtonTitle:@"知道了"
                                           otherButtonTitles:nil, nil];
        [alert show];
    }
    else if(status!=FGGNetWorkStatusWifi)
    {
        UIAlertView \*alert=[[UIAlertView alloc]initWithTitle:@"提示"
                                                     message:@"非Wifi环境播放视屏会耗费流量!"
                                                    delegate:nil
                                           cancelButtonTitle:@"知道了"
                                           otherButtonTitles:nil, nil];
        [alert show];
    }
}
/\*\*
 \*  向上滑动增加音量
 \*
 \*  @param sender 滑动手势
 \*/
-(void)increaseVolume:(UISwipeGestureRecognizer \*)sender
{
    if(sender.direction==UISwipeGestureRecognizerDirectionUp)
    {
        if(_player.volume>=1.0)
            return;
        _player.volume+=0.1;
//        NSLog(@"+++++音量:%f++++++",10\*_player.volume);
    
        __weak PlayViewController \*weakSelf=self;
        _volumeLabel.text=[NSString stringWithFormat:@"音量:%d",(int)ceilf(_player.volume\*10)];
        [UIView animateWithDuration:0.2 animations:^{
            weakSelf.volumeLabel.alpha=1.0;
        } completion:^(BOOL finished) {
            [UIView animateWithDuration:0.2 animations:^{
                weakSelf.volumeLabel.alpha=0.0;
            }];
        }];
    }
}
/\*\*
 \*  向下滑动减小音量
 \*
 \*  @param sender 滑动手势对象
 \*/
-(void)decreaseVolume:(UISwipeGestureRecognizer \*)sender
{
    if(sender.direction==UISwipeGestureRecognizerDirectionDown)
    {
        if(_player.volume<=0.0)
            return;
        _player.volume-=0.1;
//        NSLog(@"------音量:%f------",10\*_player.volume);
    
        __weak PlayViewController \*weakSelf=self;
        _volumeLabel.text=[NSString stringWithFormat:@"音量:%d",(int)ceilf(_player.volume\*10)];
        [UIView animateWithDuration:0.3 animations:^{
            weakSelf.volumeLabel.alpha=1.0;
        } completion:^(BOOL finished) {
            [UIView animateWithDuration:0.3 animations:^{
                weakSelf.volumeLabel.alpha=0.0;
            }];
        }];
    }
}
#pragma mark -
#pragma mark - 快退快进
//@qustion:seekToTime和seekToTime:toleranceBefore:toleranceAfter的区别是什么?
//快进10秒
-(void)stepForward10Seconds
{
    if(_isPlaying)
    {
        [_item seekToTime:CMTimeMakeWithSeconds(_item.currentTime.value/_item.currentTime.timescale+10, _item.currentTime.timescale) toleranceBefore:CMTimeMake(1, _item.currentTime.timescale) toleranceAfter:CMTimeMake(1, _item.currentTime.timescale)];
        __weak typeof(self) weakSelf=self;
        [UIView animateWithDuration:0.3 animations:^{
            weakSelf.forward.alpha=1.0;
        }completion:^(BOOL finished) {
            [UIView animateWithDuration:0.3 animations:^{
                weakSelf.forward.alpha=0.0;
            }];
        }];
    }
}
//快退10秒
-(void)stepBackward10Senconds
{
    if(_isPlaying)
    {
        [_item seekToTime:CMTimeMakeWithSeconds(_item.currentTime.value/_item.currentTime.timescale-10, _item.currentTime.timescale)];
        __weak typeof(self) weakSelf=self;
        [UIView animateWithDuration:0.3 animations:^{
            weakSelf.backward.alpha=1.0;
        }completion:^(BOOL finished) {
            [UIView animateWithDuration:0.3 animations:^{
                weakSelf.backward.alpha=0.0;
            }];
        }];
    }
}
//界面
-(void)createUI
{
    _playBtn=[[UIButton alloc]initWithFrame:CGRectMake(50, 20, 60, 40)];
    [_playBtn setTitle:@"Play" forState:UIControlStateNormal];
    [_playBtn setTitle:@"Pause" forState:UIControlStateSelected];
    [_playBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateNormal];
    _playBtn.titleLabel.font=[UIFont boldSystemFontOfSize:16];
    [_playBtn setTitleColor:[UIColor whiteColor] forState:UIControlStateSelected];
    [_playBtn addTarget:self action:@selector(playAction:) forControlEvents:UIControlEventTouchUpInside];
    _playBtn.backgroundColor=[UIColor clearColor];
    [self.view  addSubview:_playBtn];
    _progress=[[UIProgressView alloc]initWithFrame:CGRectMake(110, 41, kHeight-230, 2)];
    //    设置轨道颜色,将要走到的路径的颜色
    _progress.trackTintColor=[UIColor whiteColor];
    //    设置进度颜色,已经走过的路径
    _progress.progressTintColor=[UIColor blueColor];
    
    _slider=[[UISlider alloc]initWithFrame:CGRectMake(110, 26,kHeight-230, 31)];
    [_slider setThumbImage:[UIImage imageNamed:@"thumb"] forState:UIControlStateNormal];
    _slider.minimumTrackTintColor=[UIColor blueColor];//设置左边颜色
    _slider.maximumTrackTintColor=[UIColor clearColor];//设置右边颜色
    _slider.continuous=NO;
    [_slider addTarget:self action:@selector(sliderDidSlided:) forControlEvents:UIControlEventValueChanged];
    
    
    [self.view addSubview:_progress];
    [self.view addSubview:_slider];
    
    _timeLabel=[Tools createLabelWithFrame:CGRectMake(kHeight-130, 30, 110, 20) text:nil textColor:[UIColor whiteColor] textAligment:NSTextAlignmentRight andBgColor:[UIColor clearColor] font:[UIFont systemFontOfSize:14]];
    _timeLabel.text=@"--:--/--:--";
    [self.view addSubview:_timeLabel];
    
    //    音量label
    _volumeLabel=[[UILabel alloc]initWithFrame:CGRectMake(kHeight-100, kWidth/2-20, 80, 40)];
    _volumeLabel.text=[NSString stringWithFormat:@"音量:%d",(int)ceil(_player.volume)\*10];
    _volumeLabel.alpha=0.0;
    _volumeLabel.backgroundColor=[UIColor clearColor];
    _volumeLabel.font=[UIFont boldSystemFontOfSize:22];
    _volumeLabel.textColor=[UIColor whiteColor];
    [self.view addSubview:_volumeLabel];
    
    //快进
    _forward=[[UIImageView alloc]initWithFrame:CGRectMake(kHeight-164, kWidth/2-32, 64, 64)];
    _forward.image=[UIImage imageNamed:@"stepforward"];
    [self.view addSubview:_forward];
    _forward.alpha=0.0;
    
    //快退
    _backward=[[UIImageView alloc]initWithFrame:CGRectMake(100, kWidth/2-32, 64, 64)];
    _backward.image=[UIImage imageNamed:@"stepbackward"];
    [self.view addSubview:_backward];
    _backward.alpha=0.0;
}

//标题视图
-(void)createTitleView
{
    UILabel \*titleLabel=[Tools createLabelWithFrame:CGRectMake(50, 10, kHeight-100, 20) text:self.videoTitle textColor:[UIColor whiteColor] textAligment:NSTextAlignmentCenter andBgColor:[UIColor clearColor] font:[UIFont boldSystemFontOfSize:12]];
    [self.view addSubview:titleLabel];
    titleLabel.tag=111;
    
    //    返回按钮
    UIButton \*backBtn=[[UIButton alloc]initWithFrame:CGRectMake(10, 20, 40, 40)];
    [backBtn setBackgroundImage:[UIImage imageNamed:@"back"] forState:UIControlStateNormal];
    [backBtn addTarget:self action:@selector(backAction) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:backBtn];
}
//返回
-(void)backAction
{
    [self.navigationController popViewControllerAnimated:YES];
    [self dismissViewControllerAnimated:YES completion:nil];
}

/\*\*
 \*  滑动进度条时执行该方法
 \*
 \*  @param sender slider对象
 \*/
-(void)sliderDidSlided:(UISlider \*)sender
{
    if(_player.status==AVPlayerStatusReadyToPlay)
    {
        CGFloat value=sender.value;
        [_item seekToTime:CMTimeMake(value, 1)];
    }
}
//隐藏上方的条条
-(void)hideStatusLabels
{
    __weak PlayViewController \*weakSelf=self;
    
    if(!_isPlaying)
        return;
    UILabel \*label=(UILabel \*)[self.view viewWithTag:111];
    [UIView animateWithDuration:0.5 animations:^{
//        自动播放视频
        [weakSelf.player play];
        weakSelf.isPlaying=YES;
        
        label.alpha=0;
        weakSelf.timeLabel.alpha=0;
        weakSelf.slider.alpha=0;
        weakSelf.progress.alpha=0;
        weakSelf.playBtn.alpha=0;
    } completion:^(BOOL finished) {
        
    }];
}
//显示上方的条条
-(void)showStatusLabels
{
    __weak PlayViewController \*weakSelf=self;
    
    UILabel \*label=(UILabel \*)[self.view viewWithTag:111];
    
    [UIView animateWithDuration:0.5 animations:^{
        
        weakSelf.timeLabel.alpha=1;
        weakSelf.slider.alpha=1;
        weakSelf.progress.alpha=1;
        weakSelf.playBtn.alpha=1;
        label.alpha=1;
    } completion:^(BOOL finished) {
    
    }];
}
//手势点击屏幕触发的方法
-(void)shiftStatus
{
    if(_playBtn.alpha==0)
    {
//        显示上方条条
       [self performSelector:@selector(showStatusLabels) withObject:nil];
//        6秒后 自动隐藏上方条条
        [self performSelector:@selector(hideStatusLabels) withObject:nil afterDelay:6];
    }
    else
//        隐藏条条
        [self performSelector:@selector(hideStatusLabels) withObject:nil];
    
}
/\*\*
 \*  点击播放按钮时执行的方法
 \*
 \*  @param sender 播放按钮
 \*/
-(void)playAction:(UIButton \*)sender
{
    sender.selected=!sender.isSelected;
    if(_isPlaying)
    {
        [_player pause];
    }
    else
    {
        [_player play];
    }
    _isPlaying=!_isPlaying;
}
/\*\*
 \*  收到播放完毕的通知时执行该方法
 \*
 \*  @param notification 通知
 \*/
- (void)moviePlayDidEnd:(NSNotification \*)notification
{
    NSLog(@"Play end");
    [_player seekToTime:kCMTimeZero completionHandler:^(BOOL finished)
     {
        [self updateVideoSlider:0.0];
        [_playBtn setTitle:@"Play" forState:UIControlStateNormal];
    }];
}
- (void)observeValueForKeyPath:(NSString \*)keyPath ofObject:(id)object change:(NSDictionary \*)change context:(void \*)context
{

    AVPlayerItem \*playerItem = (AVPlayerItem \*)object;

    if ([keyPath isEqualToString:@"status"])
    {
    
        if ([playerItem status] == AVPlayerStatusReadyToPlay)
        {
          
            NSLog(@"AVPlayerStatusReadyToPlay");
//            开始播放视频
            [_player play];
//            播放状态置为YES
            _isPlaying=YES;
            _playBtn.selected=YES;
//            隐藏上方的条条
            [self hideStatusLabels];
//            隐藏加载指示器
            [_indicator stopAnimating];
            [_indicator removeFromSuperview];
            
            CMTime duration = _item.duration;// 获取视频总长度
    
            CGFloat totalSecond = playerItem.duration.value / playerItem.duration.timescale;// 转换成秒
          
            _totalTime = [self convertTime:totalSecond];// 转换成播放时间
          
            [self customVideoSlider:duration];
          
            NSLog(@"movie total duration:%f",CMTimeGetSeconds(duration));
         
            [self monitoringPlayback:_item];// 监听播放状态
        
        }
        else if ([playerItem status] == AVPlayerStatusFailed)
        {
            //移除网络加载指示器
            [_indicator stopAnimating];
            [_indicator removeFromSuperview];
            //NSLog(@"AVPlayerStatusFailed");
            UIAlertView \*alert=[[UIAlertView alloc]initWithTitle:@"提示" message:@"加载失败" delegate:nil cancelButtonTitle:nil otherButtonTitles:nil, nil];
            [alert show];
            [alert dismissWithClickedButtonIndex:0 animated:YES];
        }
    
    } else if ([keyPath isEqualToString:@"loadedTimeRanges"])
    {
     
        NSTimeInterval timeInterval = [self availableDuration];// 计算缓冲进度
     
//        NSLog(@"Time Interval:%f",timeInterval);
    
        CMTime duration = _item.duration;
     
        CGFloat totalDuration = CMTimeGetSeconds(duration);
//      设置进度处理器的进度值
        [_progress setProgress:timeInterval / totalDuration animated:YES];
    
    }
}
/\*\*
 \*  获取缓冲总进度
 \*
 \*  @return 缓冲总进度
 \*/
- (NSTimeInterval)availableDuration
{
  
    NSArray \*loadedTimeRanges = [[_player currentItem] loadedTimeRanges];
  
    CMTimeRange timeRange = [loadedTimeRanges.firstObject CMTimeRangeValue];// 获取缓冲区域
   
    float startSeconds = CMTimeGetSeconds(timeRange.start);
   
    float durationSeconds = CMTimeGetSeconds(timeRange.duration);
  
    NSTimeInterval result = startSeconds + durationSeconds;// 计算缓冲总进度

    return result;
}
/\*\*
 \*  将视频播放的当前时间和总时间,格式化显示在界面上
 \*
 \*  @param second 播放器的当前时间
 \*
 \*  @return 格式化后的显示时间
 \*/
- (NSString \*)convertTime:(CGFloat)second
{
  
    NSDate \*d = [NSDate dateWithTimeIntervalSince1970:second];
  
    NSDateFormatter \*formatter = [[NSDateFormatter alloc] init];
 
    if (second/3600 >= 1)
    {
       
        [formatter setDateFormat:@"HH:mm:ss"];
      
    }
    else
    {
       
        [formatter setDateFormat:@"mm:ss"];
    }
    NSString \*showtimeNew = [formatter stringFromDate:d];
   
    return showtimeNew;
}

- (void)monitoringPlayback:(AVPlayerItem \*)playerItem
{
    __weak PlayViewController  \*weakSelf=self;
    
    self.playbackTimeObserver = [_player addPeriodicTimeObserverForInterval:CMTimeMake(1, 1) queue:NULL usingBlock:^(CMTime time)
    {
        CGFloat currentSecond = playerItem.currentTime.value/playerItem.currentTime.timescale;// 计算当前在第几秒
        [weakSelf updateVideoSlider:currentSecond];
        NSString \*timeString = [weakSelf convertTime:currentSecond];
        weakSelf.timeLabel.text = [NSString stringWithFormat:@"%@/%@",timeString,weakSelf.totalTime];
    }];
}
- (void)customVideoSlider:(CMTime)duration
{
 
    _slider.maximumValue = CMTimeGetSeconds(duration);
 
    UIGraphicsBeginImageContextWithOptions((CGSize){ 1, 1 }, NO, 0.0f);
 
    UIImage \*transparentImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    [_slider setMinimumTrackImage:transparentImage forState:UIControlStateNormal];
    [_slider setMaximumTrackImage:transparentImage forState:UIControlStateNormal];
}
/\*\*
 \*  更新滑块的值
 \*
 \*  @param currentSecond 当前的播放时间
 \*/
- (void)updateVideoSlider:(CGFloat)currentSecond
{
    [_slider setValue:currentSecond animated:YES];
}
/\*\*
\*  视图即将消失时移除观察者对象,注销通知,如果播放器在播放,让其暂停,让播放器指向nil
 \*
 \*  @param animated 动画效果
 \*/
- (void)viewWillDisappear:(BOOL)animated
{
    [super viewWillDisappear:animated];
    
    [_item removeObserver:self forKeyPath:@"status" context:nil];
    [_item removeObserver:self forKeyPath:@"loadedTimeRanges" context:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:AVPlayerItemDidPlayToEndTimeNotification object:_item];
    [_player removeTimeObserver:self.playbackTimeObserver];
    if(_isPlaying)
    {
        [_player pause];
        _player=nil;
    }
}

@end

附上GitHub代码地址:AVFoundationPlayer

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,185评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,445评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,684评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,564评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,681评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,874评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,025评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,761评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,217评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,545评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,694评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,351评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,988评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,778评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,007评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,427评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,580评论 2 349

推荐阅读更多精彩内容