Android 音視頻開發(fā):Ubuntu OS編譯FFmpeg-android

audio_dev.png

什么是交叉編譯?

引自百度百科的定義:交叉編譯是在一個平臺上生成另一個平臺上的可執(zhí)行代碼册招。同一個體系結(jié)構(gòu)可以運行不同的操作系統(tǒng)岔激;同樣,同一個操作系統(tǒng)也可以在不同的體系結(jié)構(gòu)上運行是掰,就是說使用其他平臺來編譯Android或其他系統(tǒng)的庫虑鼎,于是,交叉編譯出現(xiàn)键痛。

舉例來說炫彩,我們常說的x86 Linux平臺實際上是Intel x86體系結(jié)構(gòu)和Linux for x86操作系統(tǒng)的統(tǒng)稱;而x86 WinNT平臺實際上是Intel x86體系結(jié)構(gòu)和Windows NT for x86操作系統(tǒng)的簡稱絮短。

如何實現(xiàn)交叉編譯江兢?

1、編譯環(huán)境

我們知道PC上的環(huán)境和手機上的運行環(huán)境是絕然不同的戚丸,很顯然交叉編譯非常重要的划址,要配置好編譯過程中使用到的相關(guān)的環(huán)境,而這個環(huán)境其實就是目標(biāo)機器(比如Android手機)運行時的環(huán)境限府,比如在Android上開發(fā)C/C++夺颤,那么他就需要NDK環(huán)境去編譯,這樣在Android上才可以使用胁勺。

2世澜、編譯工具鏈

1、對于C/C++的編譯署穗,通常有兩個工具 GCC 和 CLANG 寥裂。GCC 可能大家都有聽說過,這是一個老牌的編譯工具案疲,不僅可以編譯C/C++封恰,也可以編譯Java,Object-C褐啡,Go等語言诺舔。
2、CLANG 則是一個效率更高的C/C++編譯工具,并且兼容GCC低飒,Google在很早以前就開始建議使用clang進行編譯许昨,并且在 ndk 17 以后,把 GCC 移除了褥赊,全面推行使用 CLANG ,感興趣可以去工具鏈了解一下糕档。
3、 Clang是一個C++編寫拌喉、基于LLVM速那、發(fā)布于LLVM BSD許可證下的C/C++、Objective-C/Objective-C++編譯器司光。它與GNU C語言規(guī)范幾乎完全兼容(當(dāng)然琅坡,也有部分不兼容的內(nèi)容悉患,包括編譯命令選項也會有點差異)残家,并在此基礎(chǔ)上增加了額外的語法特性,比如C函數(shù)重載(通過attribute((overloadable))來修飾函數(shù))售躁,其目標(biāo)(之一)就是超越GCC坞淮。
4、LLVM是構(gòu)架編譯(compiler)的框架系統(tǒng)陪捷,以C++編寫而成回窘,用于優(yōu)化以任意程序語言編寫的程序的編譯時間(compile-time)、鏈接時間(link-time)市袖、運行時間(run-time)以及空閑時間(idle-time)啡直,對開發(fā)者保持開放,并兼容已有腳本苍碟。
-----------------以上引用百度百科

編譯原理

編譯就是將高級語言編寫的程序轉(zhuǎn)換為二進制目標(biāo)程序過程酒觅,在開始之前先來大概了解編譯原理,至少知道每一步做了什么微峰。

預(yù)處理
  • 完成宏替換舷丹、文件引入,以及去除空行蜓肆、注釋等颜凯,為下一步做準(zhǔn)備。

  • 也就是對各種預(yù)處理命令仗扬,包括頭文件的包含症概、宏定義、條件編譯的選擇等早芭。

    #include<stdio.h>
    //test hello
    int main(){
      printf("hello world!\n");
      return 0;
    }
    

    預(yù)處理命令:clang -E test.c -o test.i

主要作用就是處理關(guān)于 #的指令:

  • 刪除#define彼城,展開所有宏定義。例#define hello "helloworld"
  • 處理條件預(yù)編譯 #if, #ifdef, #if, #elif,#endif精肃。
  • 處理#include預(yù)編譯指令秤涩,將包含的.h文件插入對應(yīng)位置。這可是遞歸進行的司抱,文件內(nèi)可能包含其他.h文件筐眷。
  • 刪除所有注釋 /**/,//习柠。
  • 添加行號和文件標(biāo)識符匀谣。用于顯示調(diào)試信息:錯誤或警告的位置。
  • 保留#pragma編譯器指令资溃。(1)設(shè)定編譯器狀態(tài)武翎,(2)指示編譯器完成一些特定的動作
編譯

主要作用:1.掃描(詞法分析),2.語法分析溶锭,3.語義分析宝恶,4.源代碼優(yōu)化(中間語言生成),5.代碼生成趴捅,目標(biāo)代碼優(yōu)化垫毙。

編譯命令:clang -S test.i -o test.s

匯編

主要作用:匯編器是將匯編代碼轉(zhuǎn)變成可以執(zhí)行的指令,生成 目標(biāo)文件拱绑。

匯編命令: clang -c test.s -o test.o

鏈接

主要作用:將多個目標(biāo)文件以及所需的庫文件鏈接成生成可執(zhí)行目標(biāo)文件的過程综芥。

鏈接命令: clang test.o -o test

靜態(tài)庫(.a)和動態(tài)庫(.so)

  • 靜態(tài)庫實際就是一些目標(biāo)文件(一般是.0結(jié)尾,即我們匯編產(chǎn)生的文件)的集合猎拨,靜態(tài)庫一般以.a結(jié)尾膀藐,就是經(jīng)過打包產(chǎn)生.a文件,只用于生成可執(zhí)行文件階段红省。

  • 也就是說當(dāng)我們需要生成可執(zhí)行文件時额各,需要將這個已經(jīng)打包好的靜態(tài)庫,經(jīng)過鏈接器將匯編產(chǎn)生的.o文件的集合即靜態(tài)庫中的代碼直接復(fù)制到可執(zhí)行文件类腮。

  • 那么在ndk的工具鏈中對應(yīng)了aarch64-linux-android-ar臊泰,ndk中就是這個可執(zhí)行文件將.o打包成靜態(tài)庫:
    linux下大打包成靜態(tài)庫命令:ar rcs libtest.a test.o
    使用ndk的打包的命令:aarch64-linux-android-ar rcs libtest.a test.o.
    aarch64-linux-android-as這是匯編器

  • 動態(tài)庫在鏈接階段沒有復(fù)制到程序中,而是在程序運行時有系統(tǒng)動態(tài)加載到內(nèi)存中共程序使用蚜枢。

  • 系統(tǒng)只需載入一次動態(tài)庫缸逃,不同的程序可以得到內(nèi)存中相同的動態(tài)庫的副本。

配置ubuntu系統(tǒng)編譯環(huán)境

首先我使用的是騰訊服務(wù)器使用XShell+Xftp操作服務(wù)器厂抽,為什么使用服務(wù)器編譯ffmpeg需频,我個人沒有mac電腦,而window系統(tǒng)編譯需要配置的環(huán)境太復(fù)雜筷凤,剛好碰到騰訊搞活動索性買了一年昭殉,當(dāng)然使用服務(wù)器的好處有很多苞七。

首先你需要先下載NDK。我這里使用的r17c.
1挪丢、 NDK 版本 r17c蹂风,ffmpeg 版本4.2.3
2、 在ubuntu系統(tǒng)中我們使用命令下載ndk:

wget  https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip?hl=zh_cn

解壓 : tar  xvf   ffmpeg-4.2.3.tar

3乾蓬、下載ffmpeg

git clone https://git.ffmpeg.org/ffmpeg.git ffmpeg

4惠啄、配置環(huán)境變量

vim ~/.bashrc

PATH="$PATH:/usr/local/ffmepg/bin"
export JAVA_HOME=/home/ubuntu/jdk1.8.0_92
export JRE_HOME=${JAVA_HOME}/jre
export CLASSPATH=.:${JAVA_HOME}/lib:${JRE_HOME}/lib
export PATH=${JAVA_HOME}/bin:$PATH
export NDKROOT=/home/ubuntu/android-ndk-r17c
export PATH=$PATH:$NDKROOT

source ~/.bashrc

實際上NDK的環(huán)境可以不用配置,因為我們在編譯腳本中已經(jīng)聲明了NDK的路徑任内,所以無需配置撵渡,當(dāng)然你可以直接引用這個環(huán)境變量。

編寫build for Android的Shell 腳本

在FFMpeg根目錄新建sh文件死嗦,命名為:build_android.sh趋距,復(fù)制腳本到build_android.sh, 內(nèi)容如下:

#!/bin/bash
#構(gòu)建腳本,沒有輸入?yún)?shù)越除,那么默認是64位,如:32 或 64 分別構(gòu)建32位 或 64位
archbit=$1
if [ $archbit -eq 32 ];then
echo "Start build for 32bit for ABI"
#32bit
#ABI是Application Binary Interface的縮寫节腐。
CPU='arm'
ABI='armeabi-v7a'
#架構(gòu) 32位
ARCH='arm'
ANDROID='androideabi'
NATIVE_CPU='armeabi-v7a'
else
#64bit
echo "Start build for 64bit for ABI"
#架構(gòu) 64位
CPU='aarch64'
ABI='arm64-v8a'
ARCH='arm64'
ANDROID='android'
NATIVE_CPU='arm64-v8a'
fi

echo "Biuld param={CPU = $CPU,ABP=$ABI,ARCH=$ARCH,ANDROID=$ANDOIRD,NATIVE_CPU=$NATIVE_CPU}"

#ndk 主目錄,如果已經(jīng)配置了環(huán)境變量廊敌,可以直接引用環(huán)境變量即可
NDKROOT=/home/ubuntu/android-ndk-r17c
#TOOLCHAIN 變量指向ndk中的交叉編譯gcc所在目錄
TOOLCHAIN=$NDKROOT/toolchains/$CPU-linux-$ANDROID-4.9/prebuilt/linux-x86_64
ISYSROOT=$NDKROOT/sysroot
ASM=$ISYSROOT/usr/include/$CPU-linux-$ANDROID
ADDI_CFLAGS=" -marm"
PREFIX=./android/$NATIVE_CPU

echo "NDKROOT=$NDKROOT,TOOLCHAIN=$TOOLCHAIN"

if [ $archbit -eq 32 ];then
FLAGS=" -I$ASM -isysroot $ISYSROOT -D__ANDROID_API__=21 -U_FILE_OFFSET_BITS -Os -fPIC -DANDROID -Wno-deprecated -mfloat-abi=softfp -marm"
else
FLAGS=" -I$ASM -isysroot $ISYSROOT -D__ANDROID_API__=21 -U_FILE_OFFSET_BITS -Os -fPIC -DANDROID -Wno-deprecated"
fi

echo -e "\033[32m build start \033[0m"
./configure \
--prefix=$PREFIX \
--enable-small \
--disable-programs \
--disable-avdevice \
--disable-encoders \
--disable-muxers \
--disable-filters \
--disable-doc \
--enable-cross-compile \
--cc=$TOOLCHAIN/bin/$CPU-linux-$ANDROID-gcc \
--enable-neon \
--cross-prefix=$TOOLCHAIN/bin/$CPU-linux-$ANDROID- \
--enable-static \
--disable-shared \
--sysroot=$NDKROOT/platforms/android-21/arch-$ARCH \
--extra-cflags="$FLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
--arch=$CPU \
--target-os=android
  #執(zhí)行清理
  sudo make clean
#執(zhí)行腳本生成的 makefile
sudo make -j8
sudo make install
echo -e "\033[32m build successful\033[0m"

最后在中端輸入:

sudo ./build_android.sh  32

如果想構(gòu)建64位就把32改為64铜跑,執(zhí)行腳本门怪。

編譯參數(shù)詳解
  • ndk 主目錄

    NDKROOT=/home/ubuntu/android-ndk-r17c
    

實際上我已經(jīng)配置好了NDK環(huán)境變量骡澈,可以直接在編譯腳本$NDKROOT使用。

  • TOOLCHAIN 變量指向ndk中的交叉編譯gcc所在目錄掷空,這些我們在編譯腳本中通過條件邏輯需要編譯那種類型的cup架構(gòu)肋殴,而在工具鏈中32位和64位的工具鏈目錄是不一樣的,詳情參照編譯腳本當(dāng)中的配置坦弟。

    TOOLCHAIN=$NDKROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/
    
  • -extra-cflags 會傳值給gcc的參數(shù)护锤, FLAGS和INCLUDES變量
    可以在 AS NDK工程中的.cxx\cmake\debug\armeabi-v7a\build.ninja拷貝,需要注意的修改地址, 替換ndk主目錄酿傍,刪除-IE:/AndroidStudioprojects/NDKExampl/app/src/main/cpp/inc和- LE:/AndroidStudioprojects/NDKExampl/app/src/main/cpp/../jniLibs/armeabi-v7a烙懦,需要注意的是如果你加入不被支持的選項,會出現(xiàn)C compiler test failed的錯誤赤炒,具體哪些不被識別氯析,請報錯之后查看../ffbuild/config.log文件,比如在編譯arm64-v8a時.那就把不識別的刪掉就可以:

     ../prebuilt/linux-x86_64/bin/arm-linux-androideabi-clang is unable to create an executable file.C compiler test failed.
    
  • --disabble-static --enable-shared 分別用于禁止輸出靜態(tài)庫,以及輸出動態(tài)庫莺褒;

  • ./confiure 腳本掩缓,用于生成makefile

  • --prefix : 安裝目錄,編譯后文件的輸出目錄,用于配置輸出的so庫的存放路徑。

  • --enable--small 優(yōu)化大小

  • --disable-programs 不編譯ffmpeg程序(命令行工具)遵岩,我們是需要獲得靜態(tài)(動態(tài))庫

  • --disable-avdevice 關(guān)閉avdevice模塊你辣,此模塊在android中無用

  • --disable-encoders 關(guān)閉所有編碼器(播放器不需要編碼)

  • --disable-muxers 關(guān)閉所有復(fù)用器(封裝器),不需要生成mp4這樣的文件,所以關(guān)閉

  • --disable-filters 關(guān)閉視頻濾鏡(抖音那種開啟)

  • --enable-cross-compile 開啟交叉編譯(ffmpeg比較 跨平臺 并不是所有庫都有這么happy的選項)

  • --cross-prefix 這個選項直譯為 交叉編譯前綴舍哄,指的是交叉編譯工具的前綴宴凉,他這個是找到ndk 中的工具鏈中的可執(zhí)行的編譯工具來進行編譯的。
    設(shè)置編譯器表悬,不然會報錯跪解,系統(tǒng)默認會使用arm-linux-androideabi-clang,但是此編譯器在NDK不存在签孔,導(dǎo)致編譯失敗叉讥。

  • --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \ 設(shè)置編譯器,不然會報錯饥追,系統(tǒng)默認會使用arm-linux-androideabi-clang图仓,但是此編譯器在NDK不存在,導(dǎo)致編譯失敗但绕,這個和上一點有關(guān)聯(lián)的

  • --sysroot 用于配置交叉編譯環(huán)境的 根路徑 救崔,編譯的時候會默認從這個路徑下去尋找 usr/include usr/lib 這兩個路徑,進而找到相關(guān)的頭文件和庫文件捏顺。

  • --arch 設(shè)置編譯so庫的架構(gòu)六孵,當(dāng)前設(shè)置為arm,可以根據(jù)實際需求修改

  • --target-os=android 設(shè)-target-os=android:在舊版本的 FFmpeg 中幅骄,對Android平臺的支持并不是很完善劫窒,并沒有 android 這個target,所以在一些比較老的文章中都會提到拆座,編譯Android平臺的so庫主巍,需要對 configure 做以下修改,否則會按照 linux 標(biāo)準(zhǔn)的方式輸出so庫挪凑,其命名方式和Android的so不一樣孕索,Android是無法加載的。

  • --arch --cpu 用于配置輸出的so庫是什么架構(gòu)的

需要注意的是:

  • --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \ 這條指定我整了幾天躏碳,這個參數(shù)就是指定編譯器搞旭,不然會報錯,系統(tǒng)默認會使用arm-linux-androideabi-clang菇绵,但是此編譯器在NDK不存在肄渗,導(dǎo)致編譯失敗:

    ../prebuilt/linux-x86_64/bin/arm-linux-androideabi-clang is unable to create an executable file.C compiler test failed.
    
  • 就是ndk中文件的權(quán)限一定是要有可執(zhí)行文件的權(quán)限脸甘。

  • --extra-cflags里不要加不被支持的選項恳啥,否則會出現(xiàn)C compiler test failed的錯誤,具體哪些不被識別丹诀,請報錯之后查看../ffbuild/config.log文件,比如在編譯arm64-v8a時.那就把不識別的刪掉就可以了:
    aarch64-linux-android-gcc: error: unrecognized command line option '-mfloat-abi=softfp'

編譯完成最后會在我們制定的prefix目錄中生成編譯的庫:


1590302769(1).png

使用CLANG編譯FFmpeg

下載Android NDK

Android 的 NDK 已經(jīng)迭代了很多版本钝的,在 r17c 以后翁垂,Google正式移除 GCC ,不再支持 GCC 硝桩,新版本的 NDK 都是使用 CLANG 進行編譯沿猜。

這里就使用目前最新的 NDK r21 版本來編譯。

最主要的就是這兩個路徑:
編譯工具鏈目錄:

toolchains/llvm/prebuilt/linux-x86_64/bin

交叉編譯環(huán)境目錄:

 toolchains/llvm/prebuilt/linux-x86_64/sysroot

在NDK r21這兩個路徑和NDKr17是不同的碗脊。

我們選擇 CPU 架構(gòu) armv7a啼肩,Android版本 21,當(dāng)然你可以選擇最低支持版本比如19也是可以的衙伶。

這個兩個是交叉編譯的工具鏈一個是編譯C的另一個是編譯C++的:
armv7a-linux-androideabi21-clang
armv7a-linux-androideabi21-clang++

下面就是編譯的Shell腳本:

 #!/bin/bash
#構(gòu)建日志輸出文件
LOG_FILE=./android/config.log
#ndk 主目錄祈坠,如果已經(jīng)配置了環(huán)境變量,可以直接引用環(huán)境變量即可
NDKROOT=/home/ubuntu/android-ndk-r21
#TOOLCHAIN 變量指向ndk中的交叉編譯gcc所在目錄
TOOLCHAIN=$NDKROOT/toolchains/llvm/prebuilt/linux-x86_64
ISYSROOT=$NDKROOT/sysroot
ASM=$ISYSROOT/usr/include/arm-linux-androideabi
ADDI_CFLAGS=" -marm"
PREFIX=./android2/armeabi-v7a
echo "NDKROOT=$NDKROOT,TOOLCHAIN=$TOOLCHAIN"
FLAGS=" -I$ASM -isysroot $ISYSROOT -D__ANDROID_API__=21 - U_FILE_OFFSET_BITS -Os -fPIC -DANDROID -Wno-deprecated -mfloat-abi=softfp -marm"

echo -e "\033[32m build start \033[0m"

./configure \
--prefix=$PREFIX \
--enable-small \
--disable-programs \
--disable-avdevice \
--disable-encoders \
--disable-muxers \
--disable-filters \
--disable-doc \
--enable-cross-compile \
--cc=$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--enable-neon \
--enable-static \
--disable-shared \
--sysroot="$TOOLCHAIN/sysroot" \
--extra-cflags="$FLAGS" \
--extra-ldflags="$ADDI_LDFLAGS" \
--arch=arm \
--target-os=android
#執(zhí)行清理
sudo make clean
#執(zhí)行腳本生成的 makefile
sudo make -j8
sudo make install
echo -e "\033[32m build successful\033[0m"

需要注意ndk-r21 已經(jīng)把sysroot移動到 $TOOLCHAIN/sysroot矢劲,而r17c的 sysroot還在 $NDKROOT/platforms/android-21/arch-arm
注意ndk-r21中 --cc也是要指定的赦拘,因為他的cross-prefix命名規(guī)則不一樣了:
比如:--cc=$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang和cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi-明顯不一樣了。

ndk r21版本-----------------------默認的 cc ar nm 路徑前綴是一樣的芬沉,但是在r21之后NDK的ar/nm 和 cc的前綴是不一樣了躺同,如下:

  • 工具鏈:/home/ubuntu/android-ndk-r21/toolchains/llvm/prebuilt/linux-x86_64/bin
    1、構(gòu)建armeabi64-v8a:
    aarch64-linux-android-ar
    aarch64-linux-android-nm
    aarch64-linux-android21-clang
    2丸逸、構(gòu)建armeabi-v7a:
    arm-linux-androideabi-ar
    arm-linux-androideabi-nm
    armv7a-linux-androideabi21-clang

這個問題怎么解決蹋艺,網(wǎng)上有人說修改ffmpeg的configure文件增加corss-prefix-clang命令,是可以解決這個問題黄刚,但是我們有更簡單的捎谨?
這個時候就需要:
指定C的編譯工具--cc=$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang
指定交叉編譯工具前綴而這個前綴 會匹配到ar、nm等編譯工具--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi-

那么我們看看ffmpeg中configure的腳本:

ar_default="ar"
cc_default="gcc"
cxx_default="g++"
host_cc_default="gcc"
doxygen_default="doxygen"

//如果是android 那么就是clang
set_default target_os
if test "$target_os" = android; then
    cc_default="clang"
fi

//cross_prefix默認是[] 意思是"",所以一般我們都需要指定cross_prefix
ar_default="${cross_prefix}${ar_default}"
cc_default="${cross_prefix}${cc_default}"
nm_default="${cross_prefix}${nm_default}"

看到了嗎隘击?ar/nm 和 cc的前綴是不一樣的侍芝,前者是 arm-linux-androideabi- , 后者是 armv7a-linux-androideabi16-埋同。
所以我們直接在命令中直接修改覆蓋了默認的值:
--cc=$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang覆蓋默認值就可以了,那么ar和nm我們可以使用默認值棵红。

最后我建議大家都換成Clang編譯凶赁,Clang會對編譯的代碼做優(yōu)化,感興趣的可以連接Clang編譯器逆甜。
然后要記住每次官方發(fā)布新版NDK時自行使用最新的版本重新編譯

參考鏈接

在Android項目中調(diào)用FFmpeg命令
在Android項目中調(diào)用FFmpeg命令
FFmpegAndroid
EpMedia

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末虱肄,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子交煞,更是在濱河造成了極大的恐慌咏窿,老刑警劉巖,帶你破解...
    沈念sama閱讀 221,548評論 6 515
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件素征,死亡現(xiàn)場離奇詭異集嵌,居然都是意外死亡萝挤,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 94,497評論 3 399
  • 文/潘曉璐 我一進店門根欧,熙熙樓的掌柜王于貴愁眉苦臉地迎上來怜珍,“玉大人,你說我怎么就攤上這事凤粗∷址海” “怎么了?”我有些...
    開封第一講書人閱讀 167,990評論 0 360
  • 文/不壞的土叔 我叫張陵嫌拣,是天一觀的道長柔袁。 經(jīng)常有香客問我,道長异逐,這世上最難降的妖魔是什么瘦馍? 我笑而不...
    開封第一講書人閱讀 59,618評論 1 296
  • 正文 為了忘掉前任,我火速辦了婚禮应役,結(jié)果婚禮上情组,老公的妹妹穿的比我還像新娘披蕉。我一直安慰自己步咪,他們只是感情好银酬,可當(dāng)我...
    茶點故事閱讀 68,618評論 6 397
  • 文/花漫 我一把揭開白布秽晚。 她就那樣靜靜地躺著优炬,像睡著了一般挑辆。 火紅的嫁衣襯著肌膚如雪是复。 梳的紋絲不亂的頭發(fā)上扭弧,一...
    開封第一講書人閱讀 52,246評論 1 308
  • 那天蕉陋,我揣著相機與錄音捐凭,去河邊找鬼。 笑死凳鬓,一個胖子當(dāng)著我的面吹牛茁肠,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播缩举,決...
    沈念sama閱讀 40,819評論 3 421
  • 文/蒼蘭香墨 我猛地睜開眼垦梆,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了仅孩?” 一聲冷哼從身側(cè)響起托猩,我...
    開封第一講書人閱讀 39,725評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎辽慕,沒想到半個月后京腥,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 46,268評論 1 320
  • 正文 獨居荒郊野嶺守林人離奇死亡溅蛉,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 38,356評論 3 340
  • 正文 我和宋清朗相戀三年公浪,在試婚紗的時候發(fā)現(xiàn)自己被綠了他宛。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 40,488評論 1 352
  • 序言:一個原本活蹦亂跳的男人離奇死亡因悲,死狀恐怖堕汞,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情晃琳,我是刑警寧澤讯检,帶...
    沈念sama閱讀 36,181評論 5 350
  • 正文 年R本政府宣布,位于F島的核電站卫旱,受9級特大地震影響人灼,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜顾翼,卻給世界環(huán)境...
    茶點故事閱讀 41,862評論 3 333
  • 文/蒙蒙 一投放、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧适贸,春花似錦灸芳、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,331評論 0 24
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蕊肥,卻和暖如春谒获,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背壁却。 一陣腳步聲響...
    開封第一講書人閱讀 33,445評論 1 272
  • 我被黑心中介騙來泰國打工批狱, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人展东。 一個月前我還...
    沈念sama閱讀 48,897評論 3 376
  • 正文 我出身青樓赔硫,卻偏偏與公主長得像,于是被迫代替她去往敵國和親琅锻。 傳聞我的和親對象是個殘疾皇子卦停,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,500評論 2 359