trinity
開(kāi)源地址
https://github.com/wlanjie/trinity
- 歡迎大家提issue和pr
trinity是一個(gè)開(kāi)源的拍攝和短視頻處理工具,用kotlin和c++編寫(xiě),實(shí)現(xiàn)了大部分短視頻編輯軟件熱門(mén)功能。
QQ交流群
125218305
代碼規(guī)范
kotlin縮進(jìn)使用2空格縮進(jìn)
c++代碼遵循google c++風(fēng)格指南
系統(tǒng)版本
支持Android 4.3及以上版本
開(kāi)發(fā)環(huán)境
Android Studio 3.5
NDK r20
kotlin 1.3.41
使用的開(kāi)源庫(kù)
fdk-aac
ffmpeg 3.4
libx264
xlogger
功能
| 功能說(shuō)明 | 是否支持 |
|---|---|
| 多段錄制 | √ |
| 自定義時(shí)長(zhǎng) | √ |
| 自定義相機(jī)配置 | √ |
| 攝像頭切換 | √ |
| 閃光燈 | √ |
| 焦距調(diào)節(jié) | √ |
| 手動(dòng)對(duì)焦 | √ |
| 靜音 | √ |
| 美顏 | x |
| 磨皮 | x |
| 自定義分辨率及碼率 | √ |
| 錄制背景音 | √ |
| 錄制變速 | √ |
| 軟硬編碼 | √ |
| 多段編輯 | √ |
| 替換片段 | √ |
| 設(shè)置片段時(shí)間 | √ |
| 背景音樂(lè) | √ |
| 硬解碼 | √ |
| 濾鏡 | √ |
| 閃白 | √ |
| 兩分屏 | √ |
| 三分屏 | √ |
| 四分屏 | √ |
| 六分屏 | √ |
| 九分屏 | √ |
| 模糊分屏 | √ |
| 高斯模糊 | √ |
| 靈魂出竅 | √ |
| 抖動(dòng) | √ |
| 毛刺 | √ |
| 70s | √ |
| 縮放 | √ |
特效調(diào)試
項(xiàng)目中使用xcode調(diào)試特效效果, 使用前需要安裝glfw
brew install glfw
然后使用xcode打開(kāi)library/src/main/cpp/opengl.xcodeproj即可
切換效果調(diào)用代碼
image_process.OnAction("param/blurScreen", 0);
自動(dòng)化測(cè)試
- 自動(dòng)化測(cè)試使用uiautomator2具體使用請(qǐng)參考文檔
使用方式如下:
cd trinity
python trinity.py
然后使用
adb devices
在終端輸入設(shè)備名即可
使用
<font color=red>注意: SDK中不做權(quán)限判斷,使用時(shí)需要由調(diào)用方申請(qǐng)好權(quán)限, SDK中涉及到的時(shí)間均為毫秒</font>
權(quán)限要求
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
錄制
配置參數(shù)
- 創(chuàng)建錄制預(yù)覽view
val preview = findViewById<TrinityPreviewView>(R.id.preview)
- 創(chuàng)建錄制接口實(shí)例
mRecord = TrinityRecord(preview)
- 銷(xiāo)毀錄制接口實(shí)例
mRecord.release()
回調(diào)設(shè)置
- 設(shè)置視頻渲染回調(diào)
mRecord.setOnRenderListener(this)
- 設(shè)置錄制進(jìn)度回調(diào)
mRecord.setOnRecordingListener(this)
- 設(shè)置相機(jī)回調(diào)
mRecord.setCameraCallback(this)
開(kāi)啟預(yù)覽
- 開(kāi)始預(yù)覽
mRecord.startPreview()
- 結(jié)束預(yù)覽
mRecord.stopPreview()
- 設(shè)置預(yù)覽類(lèi)型
// 設(shè)置顯示類(lèi)型
// 包含裁剪顯示, 原比例上下留黑顯示
mRecord.setFrame(mFrame)
錄制控制/管理
- 切換攝像頭
mRecord.switchCamera()
- 獲取當(dāng)前攝像頭
// 返回當(dāng)前攝像頭id
val facing = mRecord.getCameraFacing()
- 開(kāi)關(guān)閃光燈
mRecord.flash(mFlash)
- 設(shè)置zoom
// 設(shè)置焦距縮放, 0-100 100為最大縮放
mRecord.setZoom(0)
- 設(shè)置曝光度
// 設(shè)置相機(jī)曝光度, 100為最大曝光
mRecord.setExposureCompensation(0)
- 手動(dòng)對(duì)焦
// 設(shè)置手動(dòng)對(duì)焦, 參數(shù)為x和y
mRecord.focus(mPointF)
- 設(shè)置錄制視頻的角度
/**
* @param rotation 旋轉(zhuǎn)角度包含 0 90 180 270
*/
mRecord.setRecordRotation(0)
- 設(shè)置靜音錄制
mRecord.setMute(false)
- 倍速錄制
/**
* @param speed 速度包含 0.25 0.5 1.0 2.0 4.0倍速
*/
mRecord.setSpeed(mSpeed)
開(kāi)始錄制
- 開(kāi)始錄制一段視頻
/**
* 開(kāi)始錄制一段視頻
* @param path 錄制的視頻保存的地址
* @param width 錄制視頻的寬, SDK中會(huì)做16倍整數(shù)的運(yùn)算, 可能最終輸出視頻的寬和設(shè)置進(jìn)去的不一致
* @param height 錄制視頻的高, SDK中會(huì)做16倍整數(shù)的運(yùn)算, 可能最終輸出視頻的寬和設(shè)置進(jìn)去的不一致
* @param videoBitRate 視頻輸出的碼率, 如果設(shè)置的是2000, 則為2M, 最終輸出的和設(shè)置的可能有差別
* @param frameRate 視頻輸出的幀率
* @param useHardWareEncode 是否使用硬編碼, 如果設(shè)置為true, 而硬編碼不支持,則自動(dòng)切換到軟編碼
* @param audioSampleRate 音頻的采樣率
* @param audioChannel 音頻的聲道數(shù)
* @param audioBitRate 音頻的碼率
* @param duration 需要錄制多少時(shí)間
* @return Int ErrorCode.SUCCESS 為成功,其它為失敗
* @throws InitRecorderFailException
*/
mRecord.startRecording("/sdcard/a.mp4",
720,
1280,
2000, // 2M碼率
30,
false,
44100,
1, // 單聲道
128, // 128K 碼率
Int.MAX_VALUE)
- 結(jié)束錄制
mRecord.stopRecording()
視頻編輯
初始化
- 創(chuàng)建編輯器實(shí)例
mVideoEditor = TrinityCore.createEditor(this)
- 設(shè)置預(yù)覽畫(huà)面
val surfaceView = findViewById<SurfaceView>(R.id.surface_view)
mVideoEditor.setSurfaceView(surfaceView)
導(dǎo)入視頻
- 添加一個(gè)片段
val clip = MediaClip(file.absolutePath)
mVideoEditor.insertClip(clip)
- 根據(jù)下標(biāo)添加片段
val clip = MediaClip(file.absolutePath)
mVideoEditor.insertClip(0, clip)
- 刪除一個(gè)片段
/**
* 根據(jù)下標(biāo)刪除一個(gè)片段
*/
mVideoEditor.removeClip(index)
- 獲取片段的數(shù)量
val count = mVideoEditor.getClipsCount()
- 根據(jù)下標(biāo)獲取一個(gè)片段
/**
* 如果片段不存在, 返回一個(gè)null
*/
val clip = mVideoEditor.getClip(index)
- 根據(jù)下標(biāo)替換一個(gè)片段
mVideoEditor.replaceClip(index, clip)
- 獲取所有片段
/**
* 返回所有片段的集合
*/
val clips = mVideoEditor.getVideoClips()
- 獲取所有片段的時(shí)間總長(zhǎng)
val duration = mVideoEditor.getVideoDuration()
- 獲取當(dāng)前播放片段的進(jìn)度
val current = mVideoEditor.getCurrentPosition()
- 獲取指定片段的開(kāi)始和結(jié)束時(shí)間
val timeRange = mVideoEditor.getClipTimeRange(index)
- 根據(jù)時(shí)間查找片段的下標(biāo)
val index = mVideoEditor.getClipIndex(time)
背景音樂(lè)
- 添加背景音樂(lè)
/**
* @param config 背景音樂(lè)json內(nèi)容
* 具體json內(nèi)容如下:
* {
* "path": "/sdcard/trinity.mp3",
* "startTime": 0,
* "endTime": 2000
* }
* json 參數(shù)解釋:
* path: 音樂(lè)的本地地址
* startTime: 這個(gè)音樂(lè)的開(kāi)始時(shí)間
* endTime: 這個(gè)音樂(lè)的結(jié)束時(shí)間 2000代表這個(gè)音樂(lè)只播放2秒鐘
*/
val actionId = mVideoEditor.addMusic(config)
- 更新背景音樂(lè)
/**
* @param config 背景音樂(lè)json內(nèi)容
* 具體json內(nèi)容如下:
* {
* "path": "/sdcard/trinity.mp3",
* "startTime": 2000,
* "endTime": 4000
* }
* json 參數(shù)解釋:
* path: 音樂(lè)的本地地址
* startTime: 這個(gè)音樂(lè)的開(kāi)始時(shí)間
* endTime: 這個(gè)音樂(lè)的結(jié)束時(shí)間 4000代表這個(gè)音樂(lè)從開(kāi)始時(shí)間到結(jié)束時(shí)間播放2秒鐘
*/
val actionId = mVideoEditor.addMusic(config)
- 刪除背景音樂(lè)
/**
* 刪除背景音樂(lè)
* @param actionId 必須為添加背景音樂(lè)時(shí)返回的actionId
*/
mVideoEditor.deleteMusic(actionId)
添加特效
- 添加普通濾鏡
/**
* 添加濾鏡
* 如: content.json的絕對(duì)路徑為 /sdcard/Android/com.trinity.sample/cache/filters/config.json
* 傳入的路徑只需要 /sdcard/Android/com.trinity.sample/cache/filters 即可
* 如果當(dāng)前路徑不包含config.json則添加失敗
* 具體json內(nèi)容如下:
* {
* "type": 0,
* "intensity": 1.0,
* "lut": "lut_124/lut_124.png"
* }
*
* json 參數(shù)解釋:
* type: 保留字段, 目前暫無(wú)作用
* intensity: 濾鏡透明度, 0.0時(shí)和攝像頭采集的無(wú)差別
* lut: 濾鏡顏色表的地址, 必須為本地地址, 而且為相對(duì)路徑
* sdk內(nèi)部會(huì)進(jìn)行路徑拼接
* @param configPath 濾鏡config.json的父目錄
* @return 返回當(dāng)前濾鏡的唯一id
*/
val actionId = mVideoEditor.addFilter(config)
- 更新濾鏡
/**
* 更新濾鏡
* @param configPath config.json的路徑, 目前對(duì)稱(chēng)addFilter說(shuō)明
* @param startTime 濾鏡的開(kāi)始時(shí)間
* @param endTime 濾鏡的結(jié)束時(shí)間
* @param actionId 需要更新哪個(gè)濾鏡, 必須為addFilter返回的actionId
*/
mVideoEditor.updateFilter(config, 0, 2000, actionId)
- 刪除濾鏡
/**
* 刪除濾鏡
* @param actionId 需要?jiǎng)h除哪個(gè)濾鏡, 必須為addFilter時(shí)返回的actionId
*/
mVideoEditor.deleteFilter(actionId)
- 添加抖音特效
/**
* 添加特效
* 如: content.json的絕對(duì)路徑為 /sdcard/Android/com.trinity.sample/cache/effects/config.json
* 傳入的路徑只需要 /sdcard/Android/com.trinity.sample/cache/effects 即可
* 如果當(dāng)前路徑不包含config.json則添加失敗
* @param configPath 濾鏡config.json的父目錄
* @return 返回當(dāng)前特效的唯一id
*/
val actionId = mVideoEditor.addAction(configPath)
- 更新抖音特效
/**
* 更新指定特效
* @param startTime 特效的開(kāi)始時(shí)間
* @param endTime 特效的結(jié)束時(shí)間
* @param actionId 需要更新哪個(gè)特效, 必須為addAction返回的actionId
*/
mVideoEditor.updateAction(0, 2000, actionId)
- 刪除抖音特效
/**
* 刪除一個(gè)特效
* @param actionId 需要?jiǎng)h除哪個(gè)特效, 必須為addAction返回的actionId
*/
mVideoEditor.deleteAction(actionId)
開(kāi)始預(yù)覽
- 播放
/**
* @param repeat 是否循環(huán)播放
*/
mVideoEditor.play(repeat)
- 暫停
mVideoEditor.pause()
- 繼續(xù)播放
mVideoEditor.resume()
- 停止播放
mVideoEditor.stop()
釋放資源
mVideoEditor.destroy()
導(dǎo)出視頻
- 創(chuàng)建導(dǎo)出實(shí)例
val export = TrinityCore.createExport(this)
- 開(kāi)始導(dǎo)出
/**
* 開(kāi)始導(dǎo)出
* @param path 錄制的視頻保存的地址
* @param width 錄制視頻的寬, SDK中會(huì)做16倍整數(shù)的運(yùn)算, 可能最終輸出視頻的寬和設(shè)置進(jìn)去的不一致
* @param height 錄制視頻的高, SDK中會(huì)做16倍整數(shù)的運(yùn)算, 可能最終輸出視頻的寬和設(shè)置進(jìn)去的不一致
* @param videoBitRate 視頻輸出的碼率, 如果設(shè)置的是2000, 則為2M, 最終輸出的和設(shè)置的可能有差別
* @param frameRate 視頻輸出的幀率
* @param sampleRate 音頻的采樣率
* @param channelCount 音頻的聲道數(shù)
* @param audioBitRate 音頻的碼率
* @param l 導(dǎo)出回調(diào) 包含成功 失敗 和進(jìn)度回調(diào)
* @return Int ErrorCode.SUCCESS 為成功,其它為失敗
*/
export.export("/sdcard/export.mp4",
544,
960,
25,
3000,
44100,
1,
128,
this)
- 取消
export.cancel()
- 釋放
export.release()
Copyright 2019 Trinity, Inc.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.