iOS音頻掌柜-- AVAudioSession

音頻輸出作為硬件資源,對(duì)于iOS系統(tǒng)來說是唯一的,那么要如何協(xié)調(diào)和各個(gè)App之間對(duì)這個(gè)稀缺的硬件持有關(guān)系呢?

iOS給出的解決方案是"AVAudioSession" ,通過它可以實(shí)現(xiàn)對(duì)App當(dāng)前上下文音頻資源的控制,比如
插拔耳機(jī)、接電話、是否和其他音頻數(shù)據(jù)混音等。當(dāng)你遇到:

  • 是進(jìn)行錄音還是播放?
  • 當(dāng)系統(tǒng)靜音鍵按下時(shí)該如何表現(xiàn)?
  • 是從揚(yáng)聲器還是從聽筒里面播放聲音?
  • 插拔耳機(jī)后如何表現(xiàn)?
  • 來電話/鬧鐘響了后如何表現(xiàn)?
  • 其他音頻App啟動(dòng)后如何表現(xiàn)?
  • ...

這些場(chǎng)景的時(shí)候,就可以考慮一下“AVAudioSession”了。
??????
在很久以前(其實(shí)也是不是太久--iOS7以前)還有個(gè)AudioSession的存在,其功能與AVAudioSession類似,但是在iOS7 以后就已經(jīng)被標(biāo)記為
“Not Applicable”,所以如果Google到了說AudioSession的內(nèi)容而不是用的AVAudioSession,那么就可以直接PASS了,當(dāng)然如果要兼容iOS6
就另當(dāng)別論了,不過現(xiàn)在QQ/微信都是要求iOS7的情況下,是否需要兼容iOS6就看老板們的意思吧。

Session默認(rèn)行為

  • 可以進(jìn)行播放,但是不能進(jìn)行錄制。
  • 當(dāng)用戶將手機(jī)上的靜音撥片撥到“靜音”狀態(tài)時(shí),此時(shí)如果正在播放音頻,那么播放內(nèi)容會(huì)被靜音。
  • 當(dāng)用戶按了手機(jī)的鎖屏鍵或者手機(jī)自動(dòng)鎖屏了,此時(shí)如果正在播放音頻,那么播放會(huì)靜音并被暫停。
  • 如果你的App在開始播放的時(shí)候,此時(shí)QQ音樂等其他App正在播放,那么其他播放器會(huì)被靜音并暫停。

默認(rèn)的行為相當(dāng)于設(shè)置了Category為“AVAudioSessionCategorySoloAmbient”

來看Demo

demo_player

通過這播放器demo可以驗(yàn)證上面的默認(rèn)Session行為。

AVAudioSession

AVAudioSession以一個(gè)單例實(shí)體的形式存在,通過類方法:

+ (AVAudioSession *)sharedInstance;

獲得單例。

雖然系統(tǒng)會(huì)在App啟動(dòng)的時(shí)候,激活這個(gè)唯一的AVAudioSession,但是最好還是在自己ViewController的viewDidLoad里面再次進(jìn)行激活:

- (BOOL)setActive:(BOOL)active 
        error:(NSError * _Nullable *)outError;

通過設(shè)置active為"YES"激活Session,設(shè)置為“?NO”解除Session的激活狀態(tài)。BOOL返回值表示是否成功,如果失敗的話可以通過NSError的error.localizedDescription查看出錯(cuò)原因。

因?yàn)锳VAudioSession會(huì)影響其他App的表現(xiàn),當(dāng)自己App的Session被激活,其他App的就會(huì)被解除激活,如何要讓自己的Session解除激活后恢復(fù)其他App Session的激活狀態(tài)呢?

此時(shí)可以使用:

  • (BOOL)setActive:(BOOL)active
    withOptions:(AVAudioSessionSetActiveOptions)options
    error:(NSError * _Nullable *)outError;

這里的options傳入AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation 即可。

當(dāng)然,也可以通過otherAudioPlaying變量來提前判斷當(dāng)前是否有其他App在播放音頻。

可以通過:

@property(readonly) NSString *category;

屬性,獲取當(dāng)前的Category,比如上面的播放其,默認(rèn)是

 NSLog(@"Current Category:%@", [AVAudioSession sharedInstance].category);

輸出:

Current Category:AVAudioSessionCategorySoloAmbien

七大Category

AVAudioSession主要能控制App的哪些表現(xiàn)以及如何控制的呢?首先AVAudioSession將使用音頻的場(chǎng)景分成七大類,通過設(shè)置Session為不同的類別,可以控制:

  • 當(dāng)App激活Session的時(shí)候,是否會(huì)打斷其他不支持混音的App聲音
  • 當(dāng)用戶觸發(fā)手機(jī)上的“靜音”鍵時(shí)或者鎖屏?xí)r,是否相應(yīng)靜音
  • 當(dāng)前狀態(tài)是否支持錄音
  • 當(dāng)前狀態(tài)是否支持播放
    每個(gè)App啟動(dòng)時(shí)都會(huì)設(shè)置成上面說的默認(rèn)狀態(tài),即其他App會(huì)被中斷同時(shí)相應(yīng)“靜音”鍵的播放模式。通過下表可以細(xì)分每個(gè)類別的支持情況:
類別 當(dāng)按“靜音”或者鎖屏是是否靜音 是否引起不支持混音的App中斷 是否支持錄音和播放
AVAudioSessionCategoryAmbient 只支持播放
AVAudioSessionCategoryAudioProcessing - 都不支持
AVAudioSessionCategoryMultiRoute 既可以錄音也可以播放
AVAudioSessionCategoryPlayAndRecord 默認(rèn)不引起 既可以錄音也可以播放
AVAudioSessionCategoryPlayback 默認(rèn)引起 只用于播放
AVAudioSessionCategoryRecord 只用于錄音
AVAudioSessionCategorySoloAmbient 只用于播放

可以看到,其實(shí)默認(rèn)的就是“AVAudioSessionCategorySoloAmbient”類別。從表中我們可以總結(jié)如下:

  • AVAudioSessionCategoryAmbient : 只用于播放音樂時(shí),并且可以和QQ音樂同時(shí)播放,比如玩游戲的時(shí)候還想聽QQ音樂的歌,那么把游戲播放背景音就設(shè)置成這種類別。同時(shí),當(dāng)用戶鎖屏或者靜音時(shí)也會(huì)隨著靜音,這種類別基本使用所有App的背景場(chǎng)景。
  • AVAudioSessionCategorySoloAmbient: 也是只用于播放,但是和"AVAudioSessionCategoryAmbient"不同的是,用了它就別想聽QQ音樂了,比如不希望QQ音樂干擾的App,類似節(jié)奏大師。同樣當(dāng)用戶鎖屏或者靜音時(shí)也會(huì)隨著靜音,鎖屏了就玩不了節(jié)奏大師了。
  • AVAudioSessionCategoryPlayback: 如果鎖屏了還想聽聲音怎么辦?用這個(gè)類別,比如App本身就是播放器,同時(shí)當(dāng)App播放時(shí),其他類似QQ音樂就不能播放了。所以這種類別一般用于播放器類App
  • AVAudioSessionCategoryRecord: 有了播放器,肯定要錄音機(jī),比如微信語音的錄制,就要用到這個(gè)類別,既然要安靜的錄音,肯定不希望有QQ音樂了,所以其他播放聲音會(huì)中斷。想想微信語音的場(chǎng)景,就知道什么時(shí)候用他了。
  • AVAudioSessionCategoryPlayAndRecord: 如果既想播放又想錄制該用什么模式呢?比如VoIP,打電話這種場(chǎng)景,PlayAndRecord就是專門為這樣的場(chǎng)景設(shè)計(jì)的 。
  • AVAudioSessionCategoryMultiRoute: 想象一個(gè)DJ用的App,手機(jī)連著HDMI到揚(yáng)聲器播放當(dāng)前的音樂,然后耳機(jī)里面播放下一曲,這種常人不理解的場(chǎng)景,這個(gè)類別可以支持多個(gè)設(shè)備輸入輸出。
  • AVAudioSessionCategoryAudioProcessing: 主要用于音頻格式處理,一般可以配合AudioUnit進(jìn)行使用

了解了這七大類別,我們就可以根據(jù)自己的需要進(jìn)行對(duì)應(yīng)類別的設(shè)置了:

- (BOOL)setCategory:(NSString *)category error:(NSError **)outError;

傳入對(duì)應(yīng)的列表枚舉即可。如果返回"NO"可以通過NSError的error.localizedDescription查看原因。

可以通過:

@property(readonly) NSArray<NSString *> *availableCategories;

屬性,查看當(dāng)前設(shè)備支持哪些類別,然后再進(jìn)行設(shè)置,從而保證傳入?yún)?shù)的合法,減少錯(cuò)誤的可能。

比如修改上面的Demo例子:

    NSLog(@"Current Category:%@", [AVAudioSession sharedInstance].category);
    NSError *error = nil;
    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error:&error];
    if (nil != error) {
        NSLog(@"set Option error %@", error.localizedDescription);
    }
    NSLog(@"Current Category:%@", [AVAudioSession sharedInstance].category);

此時(shí)在播放音樂的時(shí)候,再去按下靜音鍵,會(huì)發(fā)現(xiàn),音樂還在繼續(xù)播放,不會(huì)被靜音。

類別的選項(xiàng)

上面介紹的這個(gè)七大類別,可以認(rèn)為是設(shè)定了七種主場(chǎng)景,而這七類肯定是不能滿足開發(fā)者所有的需求的。CoreAudio提供的方法是,首先定下七種的一種基調(diào),然后在進(jìn)行微調(diào)。CoreAudio為每種Category都提供了些許選項(xiàng)來進(jìn)行微調(diào)。
在設(shè)置完類別后,可以通過

@property(readonly) AVAudioSessionCategoryOptions categoryOptions;

屬性,查看當(dāng)前類別設(shè)置了哪些選項(xiàng),注意這里的返回值是AVAudioSessionCategoryOptions,實(shí)際是多個(gè)options的“|”運(yùn)算。默認(rèn)情況下是0。

選項(xiàng) 適用類別 作用
AVAudioSessionCategoryOptionMixWithOthers AVAudioSessionCategoryPlayAndRecord, AVAudioSessionCategoryPlayback, and AVAudioSessionCategoryMultiRoute 是否可以和其他后臺(tái)App進(jìn)行混音
AVAudioSessionCategoryOptionDuckOthers AVAudioSessionCategoryAmbient, AVAudioSessionCategoryPlayAndRecord, AVAudioSessionCategoryPlayback, and AVAudioSessionCategoryMultiRoute 是否壓低其他App聲音
AVAudioSessionCategoryOptionAllowBluetooth AVAudioSessionCategoryRecord and AVAudioSessionCategoryPlayAndRecord 是否支持藍(lán)牙耳機(jī)
AVAudioSessionCategoryOptionDefaultToSpeaker AVAudioSessionCategoryPlayAndRecord 是否默認(rèn)用免提聲音

目前主要的選項(xiàng)有這幾種,都有對(duì)應(yīng)的使用場(chǎng)景,除此之外,在iOS9還提供了AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers最新的iOS10又新加了兩個(gè)AVAudioSessionCategoryOptionAllowBluetoothA2DPAVAudioSessionCategoryOptionAllowAirPlay用來支持藍(lán)牙A2DP耳機(jī)和AirPlay。

來看每個(gè)選項(xiàng)的基本作用:

  • AVAudioSessionCategoryOptionMixWithOthers : 如果確實(shí)用的AVAudioSessionCategoryPlayback實(shí)現(xiàn)的一個(gè)背景音,但是呢,又想和QQ音樂并存,那么可以在AVAudioSessionCategoryPlayback類別下在設(shè)置這個(gè)選項(xiàng),就可以實(shí)現(xiàn)共存了。
  • AVAudioSessionCategoryOptionDuckOthers:在實(shí)時(shí)通話的場(chǎng)景,比如QQ音樂,當(dāng)進(jìn)行視頻通話的時(shí)候,會(huì)發(fā)現(xiàn)QQ音樂自動(dòng)聲音降低了,此時(shí)就是通過設(shè)置這個(gè)選項(xiàng)來對(duì)其他音樂App進(jìn)行了壓制。
  • AVAudioSessionCategoryOptionAllowBluetooth:如果要支持藍(lán)牙耳機(jī)電話,則需要設(shè)置這個(gè)選項(xiàng)
  • AVAudioSessionCategoryOptionDefaultToSpeaker: 如果在VoIP模式下,希望默認(rèn)打開免提功能,需要設(shè)置這個(gè)選項(xiàng)

通過接口:
- (BOOL)setCategory:(NSString *)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError
來對(duì)當(dāng)前的類別進(jìn)行選項(xiàng)的設(shè)置。

比如Demo中:

    [[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback withOptions:AVAudioSessionCategoryOptionMixWithOthers error:&error];
    if (nil != error) {
        NSLog(@"set Option error %@", error.localizedDescription);
    }
    options = [[AVAudioSession sharedInstance] categoryOptions];
    NSLog(@"Category[%@] has %lu options",  [AVAudioSession sharedInstance].category, options);

此時(shí),先打開QQ音樂播放器,然后再開始進(jìn)行播放,會(huì)發(fā)現(xiàn),QQ和我們的播放器都在播放,并且進(jìn)行了自動(dòng)混音。

不過這個(gè)過程,感覺CoreAudio缺少一個(gè)setOption的接口,既然已經(jīng)是當(dāng)前處于的Category,干嘛還要再設(shè)置選項(xiàng)的時(shí)候再指定Category呢??疑惑。。。

七大模式

剛講完七大類別,現(xiàn)在再來七大模式。通過上面的七大類別,我們基本覆蓋了常用的主場(chǎng)景,在每個(gè)主場(chǎng)景中可以通過Option進(jìn)行微調(diào)。為此CoreAudio提供了七大比較常見微調(diào)后的子場(chǎng)景。叫做各個(gè)類別的模式。

模式 適用的類別 場(chǎng)景
AVAudioSessionModeDefault 所有類別 默認(rèn)的模式
AVAudioSessionModeVoiceChat AVAudioSessionCategoryPlayAndRecord VoIP
AVAudioSessionModeGameChat AVAudioSessionCategoryPlayAndRecord 游戲錄制,由GKVoiceChat自動(dòng)設(shè)置,無需手動(dòng)調(diào)用
AVAudioSessionModeVideoRecording AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord 錄制視頻時(shí)
AVAudioSessionModeMoviePlayback AVAudioSessionCategoryPlayback 視頻播放
AVAudioSessionModeMeasurement AVAudioSessionCategoryPlayAndRecord AVAudioSessionCategoryRecord AVAudioSessionCategoryPlayback 最小系統(tǒng)
AVAudioSessionModeVideoChat AVAudioSessionCategoryPlayAndRecord 視頻通話

每個(gè)模式有其適用的類別,所以,并不是有“七七 四十九”種組合。如果當(dāng)前處于的類別下沒有這個(gè)模式,那么是設(shè)置不成功的。設(shè)置完Category后可以通過:

@property(readonly) NSArray<NSString *> *availableModes;

屬性,查看其支持哪些屬性,做合法性校驗(yàn)。

來看具體應(yīng)用:

  • AVAudioSessionModeDefault: 每種類別默認(rèn)的就是這個(gè)模式,所有要想還原的話,就設(shè)置成這個(gè)模式。
  • AVAudioSessionModeVoiceChat:主要用于VoIP場(chǎng)景,此時(shí)系統(tǒng)會(huì)選擇最佳的輸入設(shè)備,比如插上耳機(jī)就使用耳機(jī)上的麥克風(fēng)進(jìn)行采集。此時(shí)有個(gè)副作用,他會(huì)設(shè)置類別的選項(xiàng)為"AVAudioSessionCategoryOptionAllowBluetooth"從而支持藍(lán)牙耳機(jī)。
  • AVAudioSessionModeVideoChat : 主要用于視頻通話,比如QQ視頻、FaceTime。時(shí)系統(tǒng)也會(huì)選擇最佳的輸入設(shè)備,比如插上耳機(jī)就使用耳機(jī)上的麥克風(fēng)進(jìn)行采集并且會(huì)設(shè)置類別的選項(xiàng)為"AVAudioSessionCategoryOptionAllowBluetooth" 和 "AVAudioSessionCategoryOptionDefaultToSpeaker"。
  • AVAudioSessionModeGameChat : 適用于游戲App的采集和播放,比如“GKVoiceChat”對(duì)象,一般不需要手動(dòng)設(shè)置

另外幾種和音頻APP關(guān)系不大,一般我們只需要關(guān)注VoIP或者視頻通話即可。

通過調(diào)用:

- (BOOL)setMode:(NSString *)mode error:(NSError **)outError

可以在設(shè)置Category之后再設(shè)置模式。

當(dāng)然,這些模式只是CoreAduio總結(jié)的,不一定完全滿足要求,對(duì)于具體的模式,在iOS10中還是可以微調(diào)的。通過接口:

  • (BOOL)setCategory:(NSString *)category mode:(NSString *)mode options:(AVAudioSessionCategoryOptions)options error:(NSError **)outError

但是在iOS9及以下就只能在Category上調(diào)了,其實(shí)本質(zhì)是一樣的,可以認(rèn)為是個(gè)API糖,接口封裝。

系統(tǒng)中斷響應(yīng)

上面說的這些Category啊、Option啊以及Mode都是對(duì)自己作為播放主體時(shí)的表現(xiàn),但是假設(shè),現(xiàn)在正在播放著,突然來電話了、鬧鐘響了或者你在后臺(tái)放歌但是用戶啟動(dòng)其他App用上面的方法影響的時(shí)候,我們的App該如何表現(xiàn)呢?最常用的場(chǎng)景當(dāng)然是先暫停,待恢復(fù)的時(shí)候再繼續(xù)。那我們的App要如何感知到這個(gè)終端以及何時(shí)恢復(fù)呢?

AVAudioSession提供了多種Notifications來進(jìn)行此類狀況的通知。其中將來電話、鬧鈴響等都?xì)w結(jié)為一般性的中斷,用
AVAudioSessionInterruptionNotification來通知。其回調(diào)回來的userInfo主要包含兩個(gè)鍵:

  • AVAudioSessionInterruptionTypeKey: 取值為AVAudioSessionInterruptionTypeBegan表示中斷開始,我們應(yīng)該暫停播放和采集,取值為AVAudioSessionInterruptionTypeEnded表示中斷結(jié)束,我們可以繼續(xù)播放和采集。
  • AVAudioSessionInterruptionOptionKey: 當(dāng)前只有一種值AVAudioSessionInterruptionOptionShouldResume表示此時(shí)也應(yīng)該恢復(fù)繼續(xù)播放和采集。

而將其他App占據(jù)AudioSession的時(shí)候用AVAudioSessionSilenceSecondaryAudioHintNotification來進(jìn)行通知。其回調(diào)回來的userInfo鍵為:

AVAudioSessionSilenceSecondaryAudioHintTypeKey

可能包含的值:

  • AVAudioSessionSilenceSecondaryAudioHintTypeBegin: 表示其他App開始占據(jù)Session
  • AVAudioSessionSilenceSecondaryAudioHintTypeEnd: 表示其他App開始釋放Session

外設(shè)改變

除了其他App和系統(tǒng)服務(wù),會(huì)對(duì)我們的App產(chǎn)生影響以外,用戶的手也會(huì)對(duì)我們產(chǎn)生影響。默認(rèn)情況下,AudioSession會(huì)在App啟動(dòng)時(shí)選擇一個(gè)最優(yōu)的輸出方案,比如插入耳機(jī)的時(shí)候,就用耳機(jī)。但是這個(gè)過程中,用戶可能拔出耳機(jī),我們App要如何感知這樣的情況呢?

同樣AVAudioSession也是通過Notifications來進(jìn)行此類狀況的通知。

假設(shè)有這樣的App:

route_change
route_change

最開始在錄音時(shí),用戶插入和拔出耳機(jī)我們都停止錄音,這里通過Notification來通知有新設(shè)備了,或者設(shè)備被退出了,然后我們控制停止錄音。或者在播放時(shí),當(dāng)耳機(jī)被拔出出時(shí),Notification給了通知,我們先暫停音樂播放,待耳機(jī)插回時(shí),在繼續(xù)播放。

在NSNotificationCenter中對(duì)AVAudioSessionRouteChangeNotification進(jìn)行注冊(cè)。在其userInfo中有鍵:

  • AVAudioSessionRouteChangeReasonKey : 表示改變的原因
枚舉值 意義
AVAudioSessionRouteChangeReasonUnknown 未知原因
AVAudioSessionRouteChangeReasonNewDeviceAvailable 有新設(shè)備可用
AVAudioSessionRouteChangeReasonOldDeviceUnavailable 老設(shè)備不可用
AVAudioSessionRouteChangeReasonCategoryChange 類別改變了
AVAudioSessionRouteChangeReasonOverride App重置了輸出設(shè)置
AVAudioSessionRouteChangeReasonWakeFromSleep 從睡眠狀態(tài)呼醒
AVAudioSessionRouteChangeReasonNoSuitableRouteForCategory 當(dāng)前Category下沒有合適的設(shè)備
AVAudioSessionRouteChangeReasonRouteConfigurationChange Rotuer的配置改變了
  • AVAudioSessionSilenceSecondaryAudioHintTypeKey: 和上面的中斷意義意義。

總結(jié):

AVAudioSession構(gòu)建了一個(gè)音頻使用生命周期的上下文。當(dāng)前狀態(tài)是否可以錄音、對(duì)其他App有怎樣的影響、是否響應(yīng)系統(tǒng)的靜音鍵、如何感知來電話了等都可以通過它來實(shí)現(xiàn)。尤為重要的是AVAudioSession不僅可以和AVFoundation中的AVAudioPlyaer/AVAudioRecorder配合,其他錄音/播放工具比如AudioUnit、AudioQueueService也都需要他進(jìn)行錄音、靜音等上下文配合。

文中Demo參見GitHub

參考文檔

  1. Audio Session Programming Guide
  2. AVAudioSession Class Reference
  3. Audio Session Services Reference
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 227,488評(píng)論 6 531
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 98,034評(píng)論 3 414
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 175,327評(píng)論 0 373
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,554評(píng)論 1 307
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 71,337評(píng)論 6 404
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 54,883評(píng)論 1 321
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 42,975評(píng)論 3 439
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,114評(píng)論 0 286
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 48,625評(píng)論 1 332
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 40,555評(píng)論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 42,737評(píng)論 1 369
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,244評(píng)論 5 355
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 43,973評(píng)論 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,362評(píng)論 0 25
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,615評(píng)論 1 280
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,343評(píng)論 3 390
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 47,699評(píng)論 2 370

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