iOS :視頻嵌入srt字幕方式一

在視頻功能里,一般對視頻加文字是使用AVMutableVideoComposition加載一層文字圖層谜慌,但是想要對一個視頻嵌入一個srt文件中的所有字幕呢?
難點是一個srt文件中测蹲,每一段文字都有一個時間節(jié)點像屋,需要解析時間節(jié)點把文字嵌入到視頻中。
第一種方式:
AVAssetReader+AVAssetWriter
這兩個對象都是AVFoundation中的电禀,通過它們可以對視頻解碼生成CMSampleBufferRef對象幢码,這個對象包含了視頻,音頻中每一片流中的信息尖飞,并且可以轉(zhuǎn)換成UIImage單獨對流操作症副,可以對視頻、音頻文件重新編碼:碼率政基、幀率贞铣、分辨率、比特率沮明、聲道等辕坝。

AVAssetReader讀取視頻中的appendPixelBuffer,把它轉(zhuǎn)換為UIImage荐健,根據(jù)時間節(jié)點把字幕嵌入到UIImage中酱畅,這樣一張圖片就有了文字,然后再轉(zhuǎn)換回CVPixelBufferRef江场,再用AVAssetWriterInputPixelBufferAdaptor的appendPixelBuffer方法寫入一個新的視頻流文件中纺酸,最終生成一個帶有字幕的視頻。
缺點:耗時久址否,cpu加載過高吁峻,把控好內(nèi)存泄漏。
還有一個坑點,因為視頻中可能會有旋轉(zhuǎn)角度用含,比方說我使用8P拍的豎屏視頻矮慕,再使用AVAssetReader解碼的時候,解出來的CMSampleBufferRef都會旋轉(zhuǎn)90度啄骇,所以需要對AVAssetWriterInput對象中的transform賦值痴鳄,但是這種方式是在輸出的時候?qū)α餍D(zhuǎn),在現(xiàn)在的字幕的方案的流程是
CMSampleBufferRef轉(zhuǎn)換UIImage缸夹、
UIImage寫文字痪寻、
UIImage轉(zhuǎn)換CVPixelBufferRef。

所以需要改為:
CMSampleBufferRef轉(zhuǎn)換UIImage虽惭,UIImage旋轉(zhuǎn)90度
UIImage寫文字橡类,UIImage旋轉(zhuǎn)回去、
UIImage轉(zhuǎn)換CVPixelBufferRef芽唇。

效果圖


Untitled.gif

AVAssetReader讀取類:

+ (instancetype)initReader:(NSString *)videoPath{
    
    ccAssetReaderManager* manager = [[ccAssetReaderManager alloc] init];
    manager.videoAsset = [AVAsset assetWithURL:[NSURL fileURLWithPath:videoPath]];
    
    if ([manager.reader canAddOutput:manager.readerTrackOutput_video]) {
        [manager.reader addOutput:manager.readerTrackOutput_video];
    }
    if ([manager.reader canAddOutput:manager.readerTrackOutput_audio]) {
        [manager.reader addOutput:manager.readerTrackOutput_audio];
    }
    [manager.reader startReading];
    return manager;
}

- (CMSampleBufferRef)nextVideoSample{
    if (!_readerTrackOutput_video) {
        return nil;
    }
    return [_readerTrackOutput_video copyNextSampleBuffer];
}
- (CMSampleBufferRef)nextAudioSample{
    if (!_readerTrackOutput_audio) {
        return nil;
    }
    return [_readerTrackOutput_audio copyNextSampleBuffer];
}

- (void)cancel{
    [self.reader cancelReading];
}

-(AVAssetReader *)reader{
    if (!_reader) {
        _reader = [[AVAssetReader alloc] initWithAsset:self.videoAsset error:nil];
    }
    return _reader;
}
-(AVAssetReaderTrackOutput *)readerTrackOutput_video{
    if (!_readerTrackOutput_video) {
        AVAssetTrack *videoTrack = [[self.videoAsset tracksWithMediaType:AVMediaTypeVideo] firstObject];
        _readerTrackOutput_video = [[AVAssetReaderTrackOutput alloc] initWithTrack:videoTrack outputSettings:self.videoSetting];
        _readerTrackOutput_video.alwaysCopiesSampleData = NO;
    }
    return _readerTrackOutput_video;
}
-(AVAssetReaderTrackOutput *)readerTrackOutput_audio{
    if (!_readerTrackOutput_audio) {
        AVAssetTrack *audioTrack = [[self.videoAsset tracksWithMediaType:AVMediaTypeAudio] firstObject];
        _readerTrackOutput_audio = [[AVAssetReaderTrackOutput alloc] initWithTrack:audioTrack outputSettings:self.audioSetting];
        _readerTrackOutput_audio.alwaysCopiesSampleData = NO;
    }
    return _readerTrackOutput_audio;
}
-(NSDictionary *)videoSetting{
    if (!_videoSetting) {
        _videoSetting = @{
            (id)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA),
        };
    }
    return _videoSetting;
}
-(NSDictionary *)audioSetting{
    if (!_audioSetting) {
        _audioSetting = @{
            AVFormatIDKey : [NSNumber numberWithUnsignedInt:kAudioFormatLinearPCM]
        };
    }
    return _audioSetting;
}

AVAssetWriter寫入類:

+ (instancetype)initWriter:(NSString *)outPutPath inputPath:(NSString*)inputPath{
    
    ccAssetWriterManager* manager = [[ccAssetWriterManager alloc] init];
    manager.videoUrl = [NSURL fileURLWithPath:outPutPath];
    manager.videoUrl_input = [NSURL fileURLWithPath:inputPath];
    
    manager.group = dispatch_group_create();
    manager.queue_video = dispatch_queue_create("queue_video", DISPATCH_QUEUE_CONCURRENT);
    manager.queue_audio = dispatch_queue_create("queue_audio", DISPATCH_QUEUE_CONCURRENT);
    
    AVAsset* asset = [AVAsset assetWithURL:[NSURL fileURLWithPath:inputPath]];
    //需要根據(jù)原視頻的旋轉(zhuǎn)角度旋轉(zhuǎn)
    manager.assetWriterInput_video.transform = [manager getVideoOrientationWithAsset:asset];
    
    if ([manager.writer canAddInput:manager.assetWriterInput_video]) {
        [manager.writer addInput:manager.assetWriterInput_video];
    }
    if ([manager.writer canAddInput:manager.assetWriterInput_audio]) {
        [manager.writer addInput:manager.assetWriterInput_audio];
    }
    [manager adaptor];
    
    [manager.writer startWriting];
    [manager.writer startSessionAtSourceTime:kCMTimeZero];
    
    return manager;
}

// 開始寫入
- (void)pushAudioBuffer:(CMSampleBufferRef(^)(void))getBufferBlock{
    
    dispatch_group_enter(self.group);
    [self.assetWriterInput_audio requestMediaDataWhenReadyOnQueue:self.queue_audio usingBlock:^{
        if ([self startWrite:self.assetWriterInput_audio getBufferBlock:getBufferBlock]) {
            //關(guān)閉會話
            [self.assetWriterInput_audio markAsFinished];
            dispatch_group_leave(self.group);
        }
    }];
}
- (void)pushVideoBuff:(CVPixelBufferRef(^)(void))getBufferBlock getBufferTimeBlock:(CMTime(^)(void))getBufferTimeBlock{
    dispatch_group_enter(self.group);
    
    dispatch_async(self.queue_video, ^{
        if ([self startWrite:self.adaptor getBufferBlock:getBufferBlock getBufferTimeBlock:getBufferTimeBlock]) {
            //關(guān)閉會話
            [self.assetWriterInput_video markAsFinished];
            dispatch_group_leave(self.group);
        }
    });
}
- (void)finishHandle:(void(^)(bool))handle{
    //隊列執(zhí)行完成
    dispatch_group_notify(self.group, dispatch_get_main_queue(), ^{
        [self.writer finishWritingWithCompletionHandler:^{
            AVAssetWriterStatus status = self.writer.status;
            
            dispatch_async(dispatch_get_main_queue(), ^{
                if (handle) {
                    handle(status == AVAssetWriterStatusCompleted);
                }
            });
        }];
    });
}

- (void)cancel{
    [self.writer cancelWriting];
}

- (BOOL)startWrite:(AVAssetWriterInputPixelBufferAdaptor*)writerInput getBufferBlock:(CVPixelBufferRef(^)(void))getBufferBlock getBufferTimeBlock:(CMTime(^)(void))getBufferTimeBlock{

    BOOL complete = NO;
    AVAsset* asset = [AVAsset assetWithURL:self.videoUrl_input];
    
    while (!complete && self.assetWriterInput_video.isReadyForMoreMediaData) {
        //可以寫入
        @autoreleasepool {
            CVPixelBufferRef buffer = getBufferBlock();
            CMTime pts = getBufferTimeBlock();
            
            if (CMTIME_COMPARE_INLINE(pts, >, asset.duration)) {
                complete = YES;
                break;
            }
            [self.writer startSessionAtSourceTime:pts];

            NSLog(@"插入圖片:%f---%ld",CMTimeGetSeconds(pts),(long)self.writer.status);
            if (buffer) {
                [_adaptor appendPixelBuffer:buffer withPresentationTime:pts];
                CFRelease(buffer);
                buffer = NULL;
            }else{
                complete = YES;
            }
        }
    }
    return complete;
}

- (BOOL)startWrite:(AVAssetWriterInput*)writerInput getBufferBlock:(CMSampleBufferRef(^)(void))getBufferBlock{
    
    BOOL complete = NO;
    while (!complete && writerInput.isReadyForMoreMediaData) {
        //可以寫入
        @autoreleasepool {
            CMSampleBufferRef buffer = getBufferBlock();
            if (buffer) {
                [writerInput appendSampleBuffer:buffer];
                CFRelease(buffer);
                buffer = NULL;
            }else{
                complete = YES;
            }
        }
    }
    return complete;
}

//獲取視頻旋轉(zhuǎn)角度
- (CGSize)getVideoOutPutNaturalSizeWithAsset:(AVAsset*)asset{
    
    NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
    AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
    CGFloat width = videoTrack.naturalSize.width;
    CGFloat height = videoTrack.naturalSize.height;
    
    CGSize size = CGSizeZero;
    CGAffineTransform videoTransform = videoTrack.preferredTransform;//矩陣旋轉(zhuǎn)角度
    
    if (videoTransform.a == 0 && videoTransform.b == 1.0 && videoTransform.c == -1.0 && videoTransform.d == 0) {
        size = CGSizeMake(width, height);
    }
    if (videoTransform.a == 0 && videoTransform.b == -1.0 && videoTransform.c == 1.0 && videoTransform.d == 0) {
        size = CGSizeMake(width, height);
    }
    if (videoTransform.a == 1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == 1.0) {
        size = CGSizeMake(height, width);
    }
    if (videoTransform.a == -1.0 && videoTransform.b == 0 && videoTransform.c == 0 && videoTransform.d == -1.0) {
        size = CGSizeMake(height, width);
    }
    
    return size;
}

//獲取視頻旋轉(zhuǎn)角度
- (CGAffineTransform)getVideoOrientationWithAsset:(AVAsset*)asset{
    
    NSArray *tracks = [asset tracksWithMediaType:AVMediaTypeVideo];
    AVAssetTrack *videoTrack = [tracks objectAtIndex:0];
    return videoTrack.preferredTransform;
}

-(AVAssetWriter *)writer{
    if (!_writer) {
        _writer = [[AVAssetWriter alloc] initWithURL:self.videoUrl fileType:AVFileTypeMPEG4 error:nil];
    }
    return _writer;
}
-(AVAssetWriterInputPixelBufferAdaptor *)adaptor{
    if (!_adaptor) {
        CGSize size = [self getVideoOutPutNaturalSizeWithAsset:[AVAsset assetWithURL:self.videoUrl_input]];
        NSDictionary *dic = @{
            (id)kCVPixelBufferPixelFormatTypeKey:[NSNumber numberWithInt:kCVPixelFormatType_32BGRA],
            AVVideoCodecKey :  AVVideoCodecTypeH264,
            AVVideoWidthKey :  @(size.width),
            AVVideoHeightKey : @(size.height),
            (id)kCVPixelFormatOpenGLESCompatibility : @(NO)
        };
        _adaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:self.assetWriterInput_video sourcePixelBufferAttributes:dic];
    }
    return _adaptor;
}
-(AVAssetWriterInput *)assetWriterInput_video{
    if (!_assetWriterInput_video) {
        
        CGSize size = [self getVideoOutPutNaturalSizeWithAsset:[AVAsset assetWithURL:self.videoUrl_input]];
        self.videoSetting = @{
            AVVideoCodecKey :  AVVideoCodecTypeH264,
            AVVideoWidthKey :  @(size.width),
            AVVideoHeightKey : @(size.height)
        };
        _assetWriterInput_video = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:self.videoSetting];
        _assetWriterInput_video.expectsMediaDataInRealTime = YES;
    }
    return _assetWriterInput_video;
}
-(AVAssetWriterInput *)assetWriterInput_audio{
    if (!_assetWriterInput_audio) {
        
        self.audioSetting = @{
            AVFormatIDKey :          @(kAudioFormatMPEG4AAC),
            AVNumberOfChannelsKey :  @(2),
            AVSampleRateKey :        @(44100),
            AVEncoderBitRateKey :    @(64000),
        };
        
        _assetWriterInput_audio = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeAudio outputSettings:self.audioSetting];
    }
    return _assetWriterInput_audio;
}

使用它們嵌入字幕

- (void)initReader:(NSString*)inputPath subtitles:(NSArray*)subtitles outputPath:(NSString*)outputPath handle:(void(^)(bool))handle{
    
    //初始化
    ccAssetReaderManager* manager_reader = [ccAssetReaderManager initReader:inputPath];
    ccAssetWriterManager* manager_writer = [ccAssetWriterManager initWriter:outputPath inputPath:inputPath];

    //讀取buffer 寫入文件
    __block CMTime pts;
    [manager_writer pushVideoBuff:^CVPixelBufferRef _Nonnull{
        
        CMSampleBufferRef buffer = [manager_reader nextVideoSample];
        __block CVImageBufferRef CVPixelBuffer = CMSampleBufferGetImageBuffer(buffer);

        //時間點
        pts = CMSampleBufferGetPresentationTimeStamp(buffer);
        CGFloat time = CMTimeGetSeconds(pts);

        [subtitles enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
            float begin = [obj[@"begin"] floatValue];
            float end = [obj[@"end"] floatValue];
            NSString* subtitle = obj[@"subtitle"];

            if (time>=begin && time<=end) {
                UIImage* image = [self imageWithSampleBuffer:buffer];
                UIImage* image_text = [self addText:subtitle addToView:image];
                UIImage* image_transfrom = [self transfromImage:image_text];
                CVPixelBuffer = [self pixelBufferFromCGImage:image_transfrom.CGImage];
            }
        }];
                
        return CVPixelBuffer;
        
    } getBufferTimeBlock:^CMTime{
        return pts;
    }];
    [manager_writer pushAudioBuffer:^CMSampleBufferRef _Nonnull{
        return [manager_reader nextAudioSample];
    }];
    [manager_writer finishHandle:^(bool success) {
        if (success) {
            [manager_reader cancel];
            [manager_writer cancel];
        }
        handle(success);
    }];
}

//轉(zhuǎn)CMSampleBufferRef-->UIImage 并且旋轉(zhuǎn)
- (UIImage*)imageWithSampleBuffer:(CMSampleBufferRef)buffer {
    CVPixelBufferRef pixelBuffer = CMSampleBufferGetImageBuffer(buffer);
    CIImage *ciimage = [CIImage imageWithCVPixelBuffer:pixelBuffer];
   // 旋轉(zhuǎn)的方法
    CIImage *image = [ciimage imageByApplyingCGOrientation:kCGImagePropertyOrientationRight];
    return [UIImage imageWithCIImage:image];
}
//轉(zhuǎn)UIImage-->UIImage 并且旋轉(zhuǎn)回去
- (UIImage*)transfromImage:(UIImage*)image {
    // 旋轉(zhuǎn)的方法
    CIImage* ciimage = [CIImage imageWithCGImage:image.CGImage];
    ciimage = [ciimage imageByApplyingCGOrientation:kCGImagePropertyOrientationLeft];
//    CIImage *ciimage = [image.CIImage imageByApplyingCGOrientation:kCGImagePropertyOrientationLeft];
    CIContext *context = [CIContext contextWithOptions:nil];
    CGImageRef myImage = [context createCGImage:ciimage fromRect:CGRectMake(0, 0, image.size.height, image.size.width)];
    return [UIImage imageWithCGImage:myImage];
}

//CGImageRef --> CVPixelBufferRef
- (CVPixelBufferRef) pixelBufferFromCGImage: (CGImageRef) image
{
    
    CGSize frameSize = CGSizeMake(CGImageGetWidth(image), CGImageGetHeight(image));
    
    NSDictionary *options = [NSDictionary dictionaryWithObjectsAndKeys:
                             [NSNumber numberWithBool:NO], kCVPixelBufferCGImageCompatibilityKey,
                             [NSNumber numberWithBool:NO], kCVPixelBufferCGBitmapContextCompatibilityKey,
                             nil];
    CVPixelBufferRef pxbuffer = NULL;
    CVReturn status = CVPixelBufferCreate(kCFAllocatorDefault, frameSize.width,
                                          frameSize.height,  kCVPixelFormatType_32BGRA, (__bridge CFDictionaryRef) options,
                                          &pxbuffer);
    NSParameterAssert(status == kCVReturnSuccess && pxbuffer != NULL);
    CVPixelBufferLockBaseAddress(pxbuffer, 0);
    void *pxdata = CVPixelBufferGetBaseAddress(pxbuffer);
    CGColorSpaceRef rgbColorSpace = CGColorSpaceCreateDeviceRGB();
    // kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst 需要轉(zhuǎn)換成需要的32BGRA空間
    CGContextRef context = CGBitmapContextCreate(pxdata, frameSize.width,
                                                 frameSize.height, 8, 4*frameSize.width, rgbColorSpace,
                                                 kCGBitmapByteOrder32Little | kCGImageAlphaPremultipliedFirst);
    CGContextDrawImage(context, CGRectMake(0, 0, CGImageGetWidth(image),
                                           CGImageGetHeight(image)), image);
    
    CGColorSpaceRelease(rgbColorSpace);
    CGContextRelease(context);
    CVPixelBufferUnlockBaseAddress(pxbuffer, 0);
    
    return pxbuffer;
}

// 添加文字水印
- (UIImage*)addText:(NSString*)text addToView:(UIImage*)image{
    
    int w = image.size.width;
    int h = image.size.height;
    
    UIGraphicsBeginImageContext(image.size);
    [image drawInRect:CGRectMake(0, 0, w, h)];
    
    NSMutableParagraphStyle *textStyle = [[NSMutableParagraphStyle defaultParagraphStyle] mutableCopy];
    textStyle.lineBreakMode = NSLineBreakByWordWrapping;
    textStyle.alignment = NSTextAlignmentCenter;//水平居中
    UIFont* font = [UIFont systemFontOfSize:40];
    
    NSDictionary *attr = @{NSFontAttributeName: font, NSForegroundColorAttributeName : [UIColor whiteColor], NSParagraphStyleAttributeName:textStyle,NSKernAttributeName:@(2),NSBackgroundColorAttributeName:[UIColor blackColor]};
        
    [text drawInRect:CGRectMake(0, h - 60, w, 60) withAttributes:attr];
    
    UIImage *newImage = UIGraphicsGetImageFromCurrentImageContext();
    UIGraphicsEndImageContext();
    
    return newImage;
}

附帶srt文件解析

// 設(shè)置字幕字符串
- (NSArray*)setSrt:(NSString *)srt {
    // 去除\t\r
    NSString *lyric = [NSString stringWithString:srt];
    lyric = [lyric stringByReplacingOccurrencesOfString:@"\r" withString:@""];
    lyric = [lyric stringByReplacingOccurrencesOfString:@"\t" withString:@""];
    NSArray *arr = [lyric componentsSeparatedByString:@"\n"];
    
    NSMutableArray *tempArr = [NSMutableArray new]; // 存放Item的數(shù)組
    NSMutableDictionary *itemDic = [NSMutableDictionary dictionary]; // 存放歌詞信息的Item
    
    __block NSInteger i = 0; // 標記顾画, 0:序號  1: 時間   2:英文    3:中文
    for (NSString *str in arr) {
        @autoreleasepool {
            NSString *tempStr = [NSString stringWithString:str];
            tempStr = [tempStr stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
            if (tempStr.length > 0) {
                switch (i) {
                    case 0:
                        [itemDic setObject:tempStr forKey:@"index"];
                        break;
                    case 1:{
                        //時間
                        NSRange range2 = [tempStr rangeOfString:@"-->"];
                        if (range2.location != NSNotFound) {
                            NSString *beginstr = [tempStr substringToIndex:range2.location];
                            beginstr = [beginstr stringByReplacingOccurrencesOfString:@" " withString:@""];
                            NSArray * arr = [beginstr componentsSeparatedByString:@":"];
                            if (arr.count == 3) {
                                NSArray * arr1 = [arr[2] componentsSeparatedByString:@","];
                                if (arr1.count == 2) {
                                    //將開始時間數(shù)組中的時間換化成秒為單位的
                                    CGFloat start = [arr[0] floatValue] * 60*60 + [arr[1] floatValue]*60 + [arr1[0] floatValue] + [arr1[1] floatValue]/1000;
                                    [itemDic setObject:@(start) forKey:@"begin"];
                                    
                                    NSString *endstr = [tempStr substringFromIndex:range2.location+range2.length];
                                    endstr = [endstr stringByReplacingOccurrencesOfString:@" " withString:@""];
                                    NSArray * array = [endstr componentsSeparatedByString:@":"];
                                    if (array.count == 3) {
                                        NSArray * arr2 = [array[2] componentsSeparatedByString:@","];
                                        if (arr2.count == 2) {
                                            //將結(jié)束時間數(shù)組中的時間換化成秒為單位的
                                            CGFloat end = [array[0] floatValue] * 60*60 + [array[1] floatValue]*60 + [arr2[0] floatValue] + [arr2[1] floatValue]/1000;
                                            [itemDic setObject:@(end) forKey:@"end"];
                                        }
                                    }
                                }
                            }
                        }
                        break;
                    }
                    case 2:
                        [itemDic setObject:tempStr forKey:@"subtitle"];
                        break;
                        //                    case 3: {
                        //                        [itemDic setObject:tempStr forKey:@"en"];
                        //                        break;
                        //                    }
                    default:
                        break;
                }
                i ++;
            }else {
                // 遇到空行,就添加到數(shù)組
                i = 0;
                NSDictionary *dic = [NSDictionary dictionaryWithDictionary:itemDic];
                [tempArr addObject:dic];
                [itemDic removeAllObjects];
            }
        }
    }
    return tempArr;
}


GitHub鏈接:
https://github.com/qw9685/srt-.git

另一種方式嵌入字幕匆笤,提高性能:http://www.reibang.com/p/e372a7b98b29

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末研侣,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子炮捧,更是在濱河造成了極大的恐慌庶诡,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,755評論 6 507
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件咆课,死亡現(xiàn)場離奇詭異末誓,居然都是意外死亡,警方通過查閱死者的電腦和手機书蚪,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,305評論 3 395
  • 文/潘曉璐 我一進店門喇澡,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人善炫,你說我怎么就攤上這事】饧蹋” “怎么了箩艺?”我有些...
    開封第一講書人閱讀 165,138評論 0 355
  • 文/不壞的土叔 我叫張陵,是天一觀的道長宪萄。 經(jīng)常有香客問我艺谆,道長,這世上最難降的妖魔是什么拜英? 我笑而不...
    開封第一講書人閱讀 58,791評論 1 295
  • 正文 為了忘掉前任静汤,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘虫给。我一直安慰自己藤抡,他們只是感情好,可當我...
    茶點故事閱讀 67,794評論 6 392
  • 文/花漫 我一把揭開白布抹估。 她就那樣靜靜地躺著缠黍,像睡著了一般。 火紅的嫁衣襯著肌膚如雪药蜻。 梳的紋絲不亂的頭發(fā)上瓷式,一...
    開封第一講書人閱讀 51,631評論 1 305
  • 那天,我揣著相機與錄音语泽,去河邊找鬼贸典。 笑死,一個胖子當著我的面吹牛踱卵,可吹牛的內(nèi)容都是我干的廊驼。 我是一名探鬼主播,決...
    沈念sama閱讀 40,362評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼颊埃,長吁一口氣:“原來是場噩夢啊……” “哼蔬充!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起班利,我...
    開封第一講書人閱讀 39,264評論 0 276
  • 序言:老撾萬榮一對情侶失蹤饥漫,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后罗标,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體庸队,經(jīng)...
    沈念sama閱讀 45,724評論 1 315
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,900評論 3 336
  • 正文 我和宋清朗相戀三年闯割,在試婚紗的時候發(fā)現(xiàn)自己被綠了彻消。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,040評論 1 350
  • 序言:一個原本活蹦亂跳的男人離奇死亡宙拉,死狀恐怖宾尚,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情谢澈,我是刑警寧澤煌贴,帶...
    沈念sama閱讀 35,742評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站锥忿,受9級特大地震影響牛郑,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜敬鬓,卻給世界環(huán)境...
    茶點故事閱讀 41,364評論 3 330
  • 文/蒙蒙 一淹朋、第九天 我趴在偏房一處隱蔽的房頂上張望笙各。 院中可真熱鬧,春花似錦础芍、人聲如沸杈抢。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,944評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽春感。三九已至,卻和暖如春虏缸,著一層夾襖步出監(jiān)牢的瞬間鲫懒,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,060評論 1 270
  • 我被黑心中介騙來泰國打工刽辙, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留窥岩,地道東北人。 一個月前我還...
    沈念sama閱讀 48,247評論 3 371
  • 正文 我出身青樓宰缤,卻偏偏與公主長得像颂翼,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子慨灭,可洞房花燭夜當晚...
    茶點故事閱讀 44,979評論 2 355