LCWechat -- 封裝錄音與播放

簡(jiǎn)略描述: AVAudioRecorder 與 AVAudioPlayer(只能播放本地音頻, 遠(yuǎn)程音頻使用AVPlayer)都是使用代理的方法判斷是否停止, 錄音的時(shí)候需要設(shè)置recordSetting, 字典的形式存儲(chǔ)了幾種錄音需要的格式,例如:采樣率, 通道數(shù),錄音質(zhì)量等.還有一個(gè)AVAudioSession 是一個(gè)單例 [AVAudioSession sharedInstance] 在錄音和播放音頻的需要設(shè)置一下其模式AVAudioSessionCategoryOptions, 每個(gè)枚舉類型都有其對(duì)應(yīng)的應(yīng)用場(chǎng)景.

摘抄:
在獲得一個(gè)AVAudioSession類的實(shí)例后蹋艺,你就能通過(guò)調(diào)用音頻會(huì)話對(duì)象的setCategory:error:實(shí)例方法庶诡,來(lái)從IOS應(yīng)用可用的不同類別中作出選擇。下面列出了可供使用的音頻會(huì)話類別:
AVAudioSessionCategorySoloAmbient

這個(gè)類別非常像AVAudioSessionCategoryAmbient類別缸兔,除了會(huì)停止其他程序的音頻回放艇挨,比如iPod程序店归。當(dāng)設(shè)備被設(shè)置為靜音模式趁曼,你的音頻回放將會(huì)停止颂碘。

AVAudioSessionCategoryRecord
這會(huì)停止其他應(yīng)用的聲音(比如iPod)并讓你的應(yīng)用也不能初始化音頻回放(比如AVAudioPlayer)邀层。在這種模式下返敬,你只能進(jìn)行錄音。使用這個(gè)類別寥院,調(diào)用AVAudioPlayer的prepareToPlay會(huì)返回YES劲赠,但是調(diào)用play方法將返回NO。主UI界面會(huì)照常工作。這時(shí)凛澎,即使你的設(shè)備屏幕被用戶鎖定了泌绣,應(yīng)用的錄音仍會(huì)繼續(xù)。

AVAudioSessionCategoryPlayback
這個(gè)類別會(huì)靜止其他應(yīng)用的音頻回放(比如iPod應(yīng)用的音頻回放)预厌。你可以使用AVAudioPlayer的prepareToPlay和play方法阿迈,在你的應(yīng)用中播放聲音。主UI界面會(huì)照常工作轧叽。這時(shí)苗沧,即使屏幕被鎖定或者設(shè)備為靜音模式,音頻回放都會(huì)繼續(xù)炭晒。

AVAudioSessionCategoryPlayAndRecord
這個(gè)類別允許你的應(yīng)用中同時(shí)進(jìn)行聲音的播放和錄制待逞。當(dāng)你的聲音錄制或播放開始后,其他應(yīng)用的聲音播放將會(huì)停止网严。主UI界面會(huì)照常工作识樱。這時(shí),即使屏幕被鎖定或者設(shè)備為靜音模式震束,音頻回放和錄制都會(huì)繼續(xù)怜庸。

AVAudioSessionCategoryAudioProcessing
這個(gè)類別用于應(yīng)用中進(jìn)行音頻處理的情形,而不是音頻回放或錄制垢村。設(shè)置了這種模式割疾,你在應(yīng)用中就不能播放和錄制任何聲音。調(diào)用AVAPlayer的prepareToPlay和play方法都將返回NO嘉栓。其他應(yīng)用的音頻回放宏榕,比如iPod,也會(huì)在此模式下停止侵佃。

AVAudioSessionCategoryAmbient
這個(gè)類別不會(huì)停止其他應(yīng)用的聲音麻昼,相反,它允許你的音頻播放于其他應(yīng)用的聲音之上馋辈,比如iPod抚芦。你的應(yīng)用的主UI縣城會(huì)工作正常。調(diào)用AVAPlayer的prepareToPlay和play方法都將返回YES首有。當(dāng)用戶鎖屏?xí)r燕垃,你的應(yīng)用將停止所有正在回放的音頻枢劝。僅當(dāng)你的應(yīng)用是唯一播放該音頻文件的應(yīng)用時(shí)井联,靜音模式將停止你程序的音頻回放。如果正當(dāng)iPod播放一手歌時(shí)您旁,你開始播放音頻烙常,將設(shè)備設(shè)為靜音模式并不能停止你的音頻回放。

思路:

1.創(chuàng)建一個(gè)AudioManager統(tǒng)一管理audioRecord和audioPlay
2.先分別實(shí)現(xiàn)audioRecord和audioPlay
3.基于audioRecord和audioPlay 在AudioManager 統(tǒng)一處理
4.就是一個(gè)封裝, 花點(diǎn)時(shí)間 就能看懂

.h文件
#import <Foundation/Foundation.h>

@interface LCAudioManager : NSObject

+ (instancetype)manager;

#pragma mark - LCAudioRecord
// 判斷麥克風(fēng)是否可用
- (BOOL)checkMicrophoneAvailability;
 
/**
 *  開始錄音
 *
 */
- (void)startRecordingWithFileName:(NSString *)fileName
                             completion:(void(^)(NSError *error))completion;

/**
 *  停止錄音
 *
 */
- (void)stopRecordingWithCompletion:(void(^)(NSString *recordPath,
                                                 NSInteger aDuration,
                                                 NSError *error))completion;
/**
 *  取消錄音
 */
- (void)cancelRecording;

/**
 *  當(dāng)前是否正在錄音
 *
 */
- (BOOL)isRecording;


#pragma mark - LCAudioPlay
/**
 *  播放音頻
 *
 */
- (void)playingWithRecordPath:(NSString *)recordPath
                  completion:(void(^)(NSError *error))completion;

/**
 *  停止播放
 *
 */
- (void)stopPlaying;

/**
 *  當(dāng)前是否正在播放
 *
 */
-(BOOL)isPlaying;
@end

.m文件
// 當(dāng)前代碼是將 錄音轉(zhuǎn)換為mp3, 如不需轉(zhuǎn)換 直接注釋此代碼, 并設(shè)置一下相應(yīng)的錄音格式,例如通道數(shù),采樣率等
//BOOL convertResult = [self convertWAV:recordPath toMP3:mp3FilePath];
#import "LCAudioManager.h"
#import "LCAudioPlay.h"
#import "LCAudioRecord.h"
#import <AVFoundation/AVFoundation.h>
#import "lame.h"

#define audioRecordDurationTooShort -100
#define audioRecordStoping -101
#define audioRecordNotStarted -102
#define audioRecordConvertionFailure -103
#define audioRecordPathNotFound -104

#define recordMinDuration 1.0

typedef NS_ENUM(NSInteger, audioSession){
    audioSessionDefault = 0,
    audioSessionAudioRecord = 1,
    audioSessionPlay = 2
};

@interface LCAudioManager ()

@property (strong, nonatomic) NSDate *recordStartDate;
@property (strong, nonatomic) NSDate *recordEndDate;
@property (copy, nonatomic) NSString *audioSessionCategory;
@property (assign, nonatomic) BOOL currentActive;

@end

@implementation LCAudioManager

+ (instancetype)manager
{
    static LCAudioManager *audioManager = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        audioManager = [[self alloc] init];
    });
    
    return audioManager;
}


- (BOOL)checkMicrophoneAvailability{
    __block BOOL open = NO;
    AVAudioSession *session = [AVAudioSession sharedInstance];
    if ([session respondsToSelector:@selector(requestRecordPermission:)]) {
        [session performSelector:@selector(requestRecordPermission:) withObject:^(BOOL status) {
            open = status;
        }];
    } else {
        open = YES;
    }
    
    return open;
}

#pragma mark - LCAudioRecord
- (void)startRecordingWithFileName:(NSString *)fileName completion:(void (^)(NSError *))completion
{
    if ([self isRecording]) {
        [self cancelRecording];
        if (completion) completion([NSError errorWithDomain:NSLocalizedString(@"LCAudio.recordStop", @"停止當(dāng)前錄音") code:audioRecordStoping userInfo:nil]);
        
        return;
    }
    
    if (!fileName || fileName.length == 0) {
        if (completion) completion([NSError errorWithDomain:NSLocalizedString(@"LCAudio.recordPathNotFound", @"尚未找到文件") code:audioRecordPathNotFound userInfo:nil]);
        return;
    }
    
    [self setCategory:audioSessionAudioRecord isActive:YES];
    [[LCAudioRecord sharedInstance] startRecordingWithRecordPath:[self recordPathWithfileName:fileName] completion:completion];
    
    self.recordStartDate = [NSDate date];
}

- (void)stopRecordingWithCompletion:(void (^)(NSString *, NSInteger, NSError *))completion
{
    if (![self isRecording]) {
        if (completion) completion(nil, 0, [NSError errorWithDomain:NSLocalizedString(@"LCAudio.recordNotStart", @"未有錄音") code:audioRecordNotStarted userInfo:nil]);
        
        return;
    }
    
    self.recordEndDate = [NSDate date];
    __weak typeof(self) weakSelf = self;
    NSTimeInterval duration = [self.recordEndDate timeIntervalSinceDate:self.recordStartDate];
    if (duration < recordMinDuration) {
        if (completion) completion(nil, 0, [NSError errorWithDomain:NSLocalizedString(@"LCAudio.recordTimeTooShort", @"錄音小于1秒") code:audioRecordDurationTooShort userInfo:nil]);
        
        
        [[LCAudioRecord sharedInstance] stopRecordingWithCompletion:^(NSString *recordPath) {
            [weakSelf setCategory:audioSessionDefault isActive:NO];
        }];
        
        return;
    }
    
    [[LCAudioRecord sharedInstance] stopRecordingWithCompletion:^(NSString *recordPath) {
        if (completion) {
            NSString *mp3FilePath = [self MP3FilePath:recordPath];
            BOOL convertResult = [self convertWAV:recordPath toMP3:mp3FilePath];
            if (convertResult) {
                // 刪除錄的wav
                [[NSFileManager defaultManager] removeItemAtPath:recordPath error:nil];
            }
            
            completion(mp3FilePath,(NSInteger)duration, nil);
        }
        
        [weakSelf setCategory:audioSessionDefault isActive:NO];
    }];
}

- (void)cancelRecording
{
    [[LCAudioRecord sharedInstance] cancelRecording];
}

- (BOOL)isRecording
{
    return [[LCAudioRecord sharedInstance] isRecording];
}

#pragma mark - LCAudioPlay

- (void)playingWithRecordPath:(NSString *)recordPath completion:(void (^)(NSError *))completion
{
    if ([self isPlaying]) [self stopPlaying];
    
    [self setCategory:audioSessionPlay isActive:YES];
    
    NSString *mp3FilePath = [self MP3FilePath:recordPath];
    
    if (![[NSFileManager defaultManager] fileExistsAtPath:mp3FilePath]) { // 如果沒(méi)有轉(zhuǎn)化成功,嘗試再次轉(zhuǎn)換
        BOOL convertResult = [self convertWAV:recordPath toMP3:mp3FilePath];
        if (convertResult) {
            // 刪除錄的wav
            [[NSFileManager defaultManager] removeItemAtPath:recordPath error:nil];
        } else {
            if (completion) completion([NSError errorWithDomain:NSLocalizedString(@"LCAudio.recordConvertionFailure", @"轉(zhuǎn)換文件失敗") code:audioRecordConvertionFailure userInfo:nil]);
            
            return;
        }
    }
    
    [[LCAudioPlay sharedInstance] playingWithPath:[self MP3FilePath:recordPath] completion:^(NSError *error) {
        [self setCategory:audioSessionDefault isActive:NO];
        if (completion) completion(error);
    }];
}

- (void)stopPlaying
{
    [[LCAudioPlay sharedInstance] stopPlaying];
    [self setCategory:audioSessionDefault isActive:NO];
}

- (BOOL)isPlaying
{
    return [[LCAudioPlay sharedInstance] isPlaying];
}

#pragma mark - setCategory && setActive
- (void)setCategory:(audioSession)session isActive:(BOOL)active
{
    NSError *error = nil;
    NSString *category = nil;
    AVAudioSession *audioSession = [AVAudioSession sharedInstance];
    
    switch (session) {
        case audioSessionAudioRecord:
            category = AVAudioSessionCategoryRecord;
            break;
        case audioSessionPlay:
            category = AVAudioSessionCategoryPlayback;
            break;
        default:
            category = AVAudioSessionCategoryAmbient;
            break;
    }
    
    if (![self.audioSessionCategory isEqualToString:category]) [audioSession setCategory:category error:nil];
    
    
    if (active != self.currentActive) {
        self.currentActive = active;
        BOOL success = [audioSession setActive:active withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:&error];
        if (!success || error) return ;
    }
    
    self.audioSessionCategory = category;
    
}

#pragma mark - path
- (NSString *)recordPathWithfileName:(NSString *)fileName
{
    NSString *recordPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    recordPath = [NSString stringWithFormat:@"%@/records/",recordPath];
    recordPath = [recordPath stringByAppendingPathComponent:fileName];
    if(![[NSFileManager defaultManager] fileExistsAtPath:[recordPath stringByDeletingLastPathComponent]]){
        [[NSFileManager defaultManager] createDirectoryAtPath:[recordPath stringByDeletingLastPathComponent] withIntermediateDirectories:YES attributes:nil error:nil];
    }
    
    return recordPath;
}

- (NSString *)MP3FilePath:(NSString *)aFilePath
{
    return [[aFilePath stringByDeletingPathExtension] stringByAppendingPathExtension:@"mp3"];
}
#pragma mark - Convert
// 使用三方庫(kù) lame // 需要將libmp3lame 拖進(jìn)項(xiàng)目
- (BOOL)convertWAV:(NSString *)wavFilePath toMP3:(NSString *)mp3FilePath{
    BOOL ret = NO;
    BOOL isFileExists = [[NSFileManager defaultManager] fileExistsAtPath:wavFilePath];
    if (isFileExists) {
        int read, write;
        
        FILE *pcm = fopen([wavFilePath cStringUsingEncoding:1], "rb");   //source 被轉(zhuǎn)換的音頻文件位置
        fseek(pcm, 4*1024, SEEK_CUR);                                                   //skip file header
        FILE *mp3 = fopen([mp3FilePath  cStringUsingEncoding:1], "wb"); //output 輸出生成的Mp3文件位置
        
        const int PCM_SIZE = 8192;
        const int MP3_SIZE = 8192;
        short int pcm_buffer[PCM_SIZE*2];
        unsigned char mp3_buffer[MP3_SIZE];
        
        lame_t lame = lame_init();
        lame_set_in_samplerate(lame, 11025.0);
        lame_set_VBR(lame, vbr_default);
        lame_init_params(lame);
        
        do {
            read = fread(pcm_buffer, 2*sizeof(short int), PCM_SIZE, pcm);
            if (read == 0)
                write = lame_encode_flush(lame, mp3_buffer, MP3_SIZE);
            else
                write = lame_encode_buffer_interleaved(lame, pcm_buffer, read, mp3_buffer, MP3_SIZE);
            
            fwrite(mp3_buffer, write, 1, mp3);
            
        } while (read != 0);
        
        lame_close(lame);
        fclose(mp3);
        fclose(pcm);
        isFileExists = [[NSFileManager defaultManager] fileExistsAtPath:mp3FilePath];
        if (isFileExists) {
            ret = YES;
        }
    }
    
    return ret;
}
@end

audioPlay

.h文件
#import <Foundation/Foundation.h>

@interface LCAudioPlay : NSObject

+ (instancetype)sharedInstance;

/**
 *  當(dāng)前是否正在播放
 *
 */
- (BOOL)isPlaying;

/**
 *  播放音頻
 *
 */
- (void)playingWithPath:(NSString *)recordPath
                  completion:(void(^)(NSError *error))completion;

/**
 *  停止播放
 *
 */
- (void)stopPlaying;
@end

.m文件
#import "LCAudioPlay.h"
#import <AVFoundation/AVFoundation.h>

#define audioFileNotFound -106
#define audioPlayerInitFilure -107

@interface LCAudioPlay ()<AVAudioPlayerDelegate>

@property (strong, nonatomic) AVAudioPlayer *player;
@property (copy, nonatomic) void(^completion)(NSError *);

@end

@implementation LCAudioPlay
+ (instancetype)sharedInstance
{
    static LCAudioPlay *player = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        player = [[self alloc] init];
    });
    
    return player;
}

- (void)playingWithPath:(NSString *)recordPath completion:(void (^)(NSError *))completion
{
    self.completion = completion;
    
    NSError *error = nil;
    
    if (![[NSFileManager defaultManager] fileExistsAtPath:recordPath]) {
        error = [NSError errorWithDomain:NSLocalizedString(@"LCAudio.fileNotFound", @"未找到文件") code:audioFileNotFound userInfo:nil];
        
        if (self.completion) self.completion(error);
        
        self.completion = nil;
        
        return;
    }
    
    NSURL *mp3URL = [NSURL fileURLWithPath:recordPath];
    
    self.player = [[AVAudioPlayer alloc] initWithContentsOfURL:mp3URL error:&error];
    
    if (!self.player || error) {
        error = [NSError errorWithDomain:NSLocalizedString(@"LCAudio.audioPlayerInitFilure", @"初始化播放器失敗") code:audioPlayerInitFilure userInfo:nil];
        
        self.player = nil;
        
        if (self.completion) self.completion(error);
        
        self.completion = nil;
        
        return;
    }
    
    self.player.delegate = self;
    [self.player prepareToPlay];
    [self.player play];
    
}

- (BOOL)isPlaying
{
    return !!self.player;
}

- (void)stopPlaying
{
    if (self.player) {
        self.player.delegate = nil;
        [self.player stop];
        self.player = nil;
    }
    
    if (self.completion) self.completion = nil;
}

- (void)dealloc
{
    [self stopPlaying];
}
#pragma mark - AVAudioPlayerDelegate
- (void)audioPlayerDidFinishPlaying:(AVAudioPlayer *)player successfully:(BOOL)flag
{
    if (self.completion) self.completion(nil);
    [self stopPlaying];
}

@end

audioRecord

.h文件
#import <Foundation/Foundation.h>

@interface LCAudioRecord : NSObject

+ (instancetype)sharedInstance;

/**
 *  開始錄音
 *
 */
- (void)startRecordingWithRecordPath:(NSString *)recordPath
                             completion:(void(^)(NSError *error))completion;

/**
 *  停止錄音
 *
 */
- (void)stopRecordingWithCompletion:(void(^)(NSString *recordPath))completion;

/**
 *  取消錄音
 */
- (void)cancelRecording;

/**
 *  當(dāng)前是否正在錄音
 *
 */
- (BOOL)isRecording;
@end

.m文件
#import "LCAudioRecord.h"
#import <AVFoundation/AVFoundation.h>

#define recorderInitFailure -105

@interface LCAudioRecord ()<AVAudioRecorderDelegate>

@property (nonatomic, strong) AVAudioRecorder *recorder;
@property (nonatomic, strong) NSDictionary *recordSetting;
@property (copy, nonatomic) void(^completion)(NSString *recordPath);

@end

@implementation LCAudioRecord

+ (instancetype)sharedInstance
{
    static LCAudioRecord *audioRecord = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        audioRecord = [[self alloc] init];
    });
    
    return audioRecord;
}   

- (NSDictionary *)recordSetting
{
    if (!_recordSetting) { // 轉(zhuǎn)換為的MP3格式
        _recordSetting = [[NSDictionary alloc] initWithObjectsAndKeys:
                          [NSNumber numberWithFloat: 11025.0],AVSampleRateKey, //采樣率 44100.0
                          [NSNumber numberWithInt: kAudioFormatLinearPCM],AVFormatIDKey,
                          [NSNumber numberWithInt:16],AVLinearPCMBitDepthKey,//采樣位數(shù) 默認(rèn) 16
                          [NSNumber numberWithInt: 2], AVNumberOfChannelsKey,//通道的數(shù)目
                          [NSNumber numberWithInt:AVAudioQualityMax], AVEncoderAudioQualityKey, // 錄音質(zhì)量
                          nil];
    }
    
    return _recordSetting;
}

- (void)startRecordingWithRecordPath:(NSString *)recordPath completion:(void (^)(NSError *))completion
{
    NSError *error = nil;
    NSURL *wavURL = [NSURL fileURLWithPath:[[recordPath stringByDeletingPathExtension] stringByAppendingPathExtension:@"wav"]];
    self.recorder = [[AVAudioRecorder alloc] initWithURL:wavURL settings:self.recordSetting error:&error];
    if (!self.recorder || error) {
        if (completion) {
            error = [NSError errorWithDomain:NSLocalizedString(@"LCAudio.recorderInitFailure", @"初始化失敗") code:recorderInitFailure userInfo:nil];
            completion(error);
        }
        self.recorder = nil;
        return;
    }
    
    self.recorder.meteringEnabled = YES;
    self.recorder.delegate = self;
    [self.recorder record];
    
    if (completion) completion(error);
    
}

- (void)stopRecordingWithCompletion:(void(^)(NSString *recordPath))completion
{
    self.completion = completion;
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        [self.recorder stop];
    });
}

- (BOOL)isRecording
{
    return !!self.recorder;
}

- (void)cancelRecording
{
    self.recorder.delegate = nil;
    if (self.recorder) [self.recorder stop];
    self.recorder = nil;
    
}

- (void)dealloc
{
    if (self.recorder) {
        self.recorder.delegate = nil;
        [self.recorder stop];
        [self.recorder deleteRecording];
        self.recorder = nil;
    }
}

- (void)audioRecorderDidFinishRecording:(AVAudioRecorder *)recorder successfully:(BOOL)flag
{
    NSString *recordPath = [[_recorder url] path];
    if (self.completion) {
        if (!flag) recordPath = nil;
        self.completion(recordPath);
    }
    
    self.recorder = nil;
    self.completion = nil;
}

@end

如何使用:

1.開始錄音
// 檢測(cè)麥克風(fēng)是否可用
[LCAudioManager manager] checkMicrophoneAvailability]
[[LCAudioManager manager] startRecordingWithFileName:[NSString recordFileName] completion:nil];

2.結(jié)束錄音
[[LCAudioManager manager] stopRecordingWithCompletion:^(NSString *recordPath, NSInteger aDuration, NSError *error) {
        if (aDuration < 1) { 
            [MBProgressHUD showError:@"錄音時(shí)間過(guò)短"];
            return ;
        }
        if (!error) { // 錄音成功
          // 執(zhí)行下一步計(jì)劃
        }
    }];

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市蚕脏,隨后出現(xiàn)的幾起案子侦副,更是在濱河造成了極大的恐慌,老刑警劉巖驼鞭,帶你破解...
    沈念sama閱讀 221,548評(píng)論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件秦驯,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡挣棕,警方通過(guò)查閱死者的電腦和手機(jī)译隘,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評(píng)論 3 399
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)洛心,“玉大人固耘,你說(shuō)我怎么就攤上這事〈噬恚” “怎么了厅目?”我有些...
    開封第一講書人閱讀 167,990評(píng)論 0 360
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)法严。 經(jīng)常有香客問(wèn)我损敷,道長(zhǎng),這世上最難降的妖魔是什么深啤? 我笑而不...
    開封第一講書人閱讀 59,618評(píng)論 1 296
  • 正文 為了忘掉前任嗤锉,我火速辦了婚禮,結(jié)果婚禮上墓塌,老公的妹妹穿的比我還像新娘瘟忱。我一直安慰自己,他們只是感情好苫幢,可當(dāng)我...
    茶點(diǎn)故事閱讀 68,618評(píng)論 6 397
  • 文/花漫 我一把揭開白布访诱。 她就那樣靜靜地躺著,像睡著了一般韩肝。 火紅的嫁衣襯著肌膚如雪触菜。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 52,246評(píng)論 1 308
  • 那天哀峻,我揣著相機(jī)與錄音涡相,去河邊找鬼。 笑死剩蟀,一個(gè)胖子當(dāng)著我的面吹牛催蝗,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播育特,決...
    沈念sama閱讀 40,819評(píng)論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼丙号,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起犬缨,我...
    開封第一講書人閱讀 39,725評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤喳魏,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后怀薛,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體刺彩,經(jīng)...
    沈念sama閱讀 46,268評(píng)論 1 320
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,356評(píng)論 3 340
  • 正文 我和宋清朗相戀三年枝恋,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了迂苛。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,488評(píng)論 1 352
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡鼓择,死狀恐怖三幻,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情呐能,我是刑警寧澤念搬,帶...
    沈念sama閱讀 36,181評(píng)論 5 350
  • 正文 年R本政府宣布,位于F島的核電站摆出,受9級(jí)特大地震影響朗徊,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜偎漫,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,862評(píng)論 3 333
  • 文/蒙蒙 一爷恳、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧象踊,春花似錦温亲、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評(píng)論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至史隆,卻和暖如春魂务,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背泌射。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工粘姜, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人熔酷。 一個(gè)月前我還...
    沈念sama閱讀 48,897評(píng)論 3 376
  • 正文 我出身青樓孤紧,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親纯陨。 傳聞我的和親對(duì)象是個(gè)殘疾皇子坛芽,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,500評(píng)論 2 359

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