1 Star 0 Fork 149

惊天 / FFmpegCommand

forked from AnJoiner / FFmpegCommand 
加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
KFFmpegCommandActivity.kt 21.50 KB
一键复制 编辑 原始数据 按行查看 历史
AnJoiner 提交于 2020-11-30 19:08 . 修改使用
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585
package com.coder.ffmpegtest.ui
import android.Manifest
import android.content.Context
import android.content.Intent
import android.content.pm.PackageManager
import android.os.Bundle
import android.text.TextUtils
import android.util.Log
import android.widget.TextView
import androidx.appcompat.app.AppCompatActivity
import androidx.core.app.ActivityCompat
import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.GridLayoutManager
import androidx.recyclerview.widget.RecyclerView
import com.coder.ffmpeg.annotation.Direction
import com.coder.ffmpeg.annotation.ImageFormat
import com.coder.ffmpeg.annotation.MediaAttribute
import com.coder.ffmpeg.annotation.Transpose
import com.coder.ffmpeg.call.CommonCallBack
import com.coder.ffmpeg.jni.FFmpegCommand
import com.coder.ffmpeg.utils.FFmpegUtils
import com.coder.ffmpegtest.R
import com.coder.ffmpegtest.model.CommandBean
import com.coder.ffmpegtest.ui.adapter.FFmpegCommandAdapter
import com.coder.ffmpegtest.ui.dialog.PromptDialog
import com.coder.ffmpegtest.ui.dialog.PromptDialog.OnPromptListener
import com.coder.ffmpegtest.utils.FileUtils
import com.coder.ffmpegtest.utils.ToastUtils
import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch
import java.io.File
import java.util.*
/**
*
* @author: AnJoiner
* @datetime: 20-1-23
*/
class KFFmpegCommandActivity : AppCompatActivity() {
private var mAudioPath: String? = null
private var mVideoPath: String? = null
private var targetPath: String? = null
private var mAudioBgPath: String? = null
private var mImagePath: String? = null
private var tvContent: TextView? = null
private var mRecyclerView: RecyclerView? = null
private var mAdapter: FFmpegCommandAdapter? = null
private var mErrorDialog: PromptDialog? = null;
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_ffmpeg_command)
if (ContextCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE),
100)
}
init()
}
private fun init() {
initView()
initData()
initListener()
}
private fun initView() {
mRecyclerView = findViewById(R.id.rv)
tvContent = findViewById(R.id.tv_content)
}
private fun initData() {
FileUtils.copy2Memory(this, "test.mp3")
FileUtils.copy2Memory(this, "test.mp4")
FileUtils.copy2Memory(this, "testbg.mp3")
FileUtils.copy2Memory(this, "water.png")
mAudioPath = File(externalCacheDir, "test.mp3").absolutePath
mVideoPath = File(externalCacheDir, "test.mp4").absolutePath
mAudioBgPath = File(externalCacheDir, "testbg.mp3").absolutePath
mImagePath = File(externalCacheDir, "water.png").absolutePath
val commands = this.resources.getStringArray(R.array.commands)
val beans: MutableList<CommandBean> = ArrayList()
for (i in commands.indices) {
beans.add(CommandBean(commands[i], i))
}
mAdapter = FFmpegCommandAdapter(beans)
mRecyclerView!!.layoutManager = GridLayoutManager(this, 3)
mRecyclerView!!.adapter = mAdapter
}
private fun initListener() {
mAdapter!!.setItemClickListener(object : FFmpegCommandAdapter.ItemClickListener {
override fun itemClick(id: Int) {
tvContent!!.text = ""
if (mErrorDialog == null) {
mErrorDialog = PromptDialog.newInstance("进度", "完成", "", "停止")
mErrorDialog?.setHasNegativeButton(false)
mErrorDialog?.setOnPromptListener(object : OnPromptListener {
override fun onPrompt(isPositive: Boolean) {
if (isPositive) FFmpegCommand.cancel()
}
})
}
when (id) {
0 -> transformAudio()
1 -> transformVideo()
2 -> cutAudio()
3 -> cutVideo()
4 -> concatAudio()
5 -> concatVideo()
6 -> extractAudio()
7 -> extractVideo()
8 -> mixAudioVideo()
9 -> screenShot()
10 -> video2Image()
11 -> video2Gif()
12 -> addWaterMark()
13 -> image2Video()
14 -> decodeAudio()
15 -> encodeAudio()
16 -> multiVideo()
17 -> reverseVideo()
18 -> picInPic()
19 -> mixAudio()
20 -> videoDoubleDown()
21 -> videoSpeed2()
22 -> denoiseVideo()
23 -> reduceAudio()
24 -> video2YUV()
25 -> yuv2H264()
26 -> fadeIn()
27 -> fadeOut()
28 -> bright()
29 -> contrast()
30 -> rotate()
31 -> videoScale()
32 -> frame2Image()
33 -> audio2Fdkaac()
34 -> audio2Mp3lame()
35 -> video2HLS()
36 -> hls2Video()
37 -> audio2Amr()
38 -> makeMuteAudio()
}
}
})
}
private fun transformAudio() {
targetPath = externalCacheDir.toString() + File.separator + "target.aac"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.transformAudio(mAudioPath, targetPath), callback("音频转码完成", targetPath))
}
}
private fun transformVideo() {
targetPath = externalCacheDir.toString() + File.separator + "target.avi"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.transformVideo(mVideoPath, targetPath), callback("视频转码完成", targetPath))
}
}
private fun cutAudio() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp3"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.cutAudio(mAudioPath, 5, 10, targetPath), callback("音频剪切完成", targetPath))
}
}
private fun cutVideo() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.cutVideo(mVideoPath, 5, 10, targetPath), callback("视频剪切完成", targetPath))
}
}
private fun concatAudio() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp3"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.concatAudio(mAudioPath, mAudioPath, targetPath), callback("音频拼接完成", targetPath))
}
}
private fun concatVideo() {
val path = FileUtils.createInputFile(this, mVideoPath!!, mVideoPath!!, mVideoPath!!)
//val path = FileUtils.createInputFile(this, mVideoPath, mVideoPath, mVideoPath)
if (TextUtils.isEmpty(path)) {
return
}
GlobalScope.launch {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
FFmpegCommand.runCmd(FFmpegUtils.concatVideo(path, targetPath), callback("视频拼接完成", targetPath))
}
}
/**
* 变更声音
*/
private fun reduceAudio() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp3"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.changeVolume(mAudioBgPath, 0.5f, targetPath), callback("音频降音完成", targetPath))
}
}
private fun extractAudio() {
targetPath = externalCacheDir.toString() + File.separator + "target.aac"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.extractAudio(mVideoPath, targetPath), callback("抽取音频完成", targetPath))
}
}
private fun extractVideo() {
targetPath = externalCacheDir.toString() + File.separator + "out.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.extractVideo(mVideoPath, targetPath), callback("抽取视频完成", targetPath))
}
}
private fun mixAudioVideo() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
val video = externalCacheDir.toString() + File.separator + "out.mp4"
val audio = externalCacheDir.toString() + File.separator + "target.aac"
if (!File(video).exists()) {
ToastUtils.show("请先执行抽取视频")
return
}
if (!File(audio).exists()) {
ToastUtils.show("请先执行抽取音频")
return
}
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.mixAudioVideo(video, audio, targetPath), callback("音视频合成完成", targetPath))
}
}
private fun screenShot() {
targetPath = externalCacheDir.toString() + File.separator + "target.jpeg"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.screenShot(mVideoPath, targetPath), callback("视频截图完成", targetPath))
}
}
private fun video2Image() {
val dir = File(externalCacheDir, "images")
if (!dir.exists()) {
dir.mkdir()
} else {
val files = dir.listFiles()
for (file in files) {
file.delete()
}
}
targetPath = dir.absolutePath
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.video2Image(mVideoPath, targetPath,
ImageFormat.JPG), callback("视频截图完成", targetPath))
}
}
private fun video2Gif() {
targetPath = externalCacheDir.toString() + File.separator + "target.gif"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.video2Gif(mVideoPath, 0, 10, targetPath), callback("视频转Gif完成", targetPath))
}
}
private fun addWaterMark() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.addWaterMark(mVideoPath, mImagePath, targetPath), callback("添加视频水印完成", targetPath))
}
}
private fun image2Video() {
val dir = File(externalCacheDir, "images")
if (!dir.exists()) {
ToastUtils.show("请先执行视频转图片")
return
}
targetPath = externalCacheDir.toString() + File.separator + "images" + File.separator + "target" +
".mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.image2Video(dir.absolutePath,
ImageFormat.JPG, targetPath), callback("图片转视频完成", targetPath))
}
}
private fun decodeAudio() {
targetPath = externalCacheDir.toString() + File.separator + "target.pcm"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.decodeAudio(mAudioPath, targetPath, 44100, 2), callback("音频解码PCM完成", targetPath))
}
}
private fun encodeAudio() {
val pcm = externalCacheDir.toString() + File.separator + "target.pcm"
if (!File(pcm).exists()) {
ToastUtils.show("请先执行音频解码PCM")
return
}
targetPath = externalCacheDir.toString() + File.separator + "target.wav"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.encodeAudio(pcm, targetPath, 44100, 2), callback("音频编码完成", targetPath))
}
}
private fun multiVideo() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.multiVideo(mVideoPath, mVideoPath, targetPath,
Direction.LAYOUT_HORIZONTAL), callback("多画面拼接完成", targetPath))
}
}
private fun reverseVideo() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.reverseVideo(mVideoPath, targetPath), callback("反序播放完成", targetPath))
}
}
private fun picInPic() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.picInPicVideo(mVideoPath, mVideoPath, 100, 100,
targetPath), callback("画中画完成", targetPath))
}
}
private fun mixAudio() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp3"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.mixAudio(mAudioPath, mAudioBgPath, targetPath), callback("音频混合完成", targetPath))
}
}
private fun videoDoubleDown() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.videoDoubleDown(mVideoPath, targetPath), callback("视频缩小一倍完成", targetPath))
}
}
private fun videoSpeed2() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.videoSpeed2(mVideoPath, targetPath), callback("视频倍速完成", targetPath))
}
}
private fun denoiseVideo() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.denoiseVideo(mVideoPath, targetPath), callback("视频降噪完成", targetPath))
}
}
private fun video2YUV() {
targetPath = externalCacheDir.toString() + File.separator + "target.yuv"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.decode2YUV(mVideoPath, targetPath), callback("视频解码YUV完成", targetPath))
}
}
private fun yuv2H264() {
targetPath = externalCacheDir.toString() + File.separator + "target.h264"
val video = externalCacheDir.toString() + File.separator + "target.yuv"
if (!File(video).exists()) {
ToastUtils.show("请先执行视频解码YUV")
return
}
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.yuv2H264(video, targetPath), callback("视频编码H264完成", targetPath))
}
}
private fun fadeIn() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp3"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.audioFadeIn(mAudioPath, targetPath), callback("音频淡入完成", targetPath))
}
}
private fun fadeOut() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp3"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.audioFadeOut(mAudioPath, targetPath, 34, 5), callback("音频淡出完成", targetPath))
}
}
private fun bright() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.videoBright(mVideoPath, targetPath, 0.25f), callback("视频提高亮度完成", targetPath))
}
}
private fun contrast() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.videoContrast(mVideoPath, targetPath, 1.5f), callback(
"视频修改对比度完成", targetPath))
}
}
private fun rotate() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.videoRotation(mVideoPath, targetPath,
Transpose.CLOCKWISE_ROTATION_90), callback("视频旋转完成", targetPath))
}
}
private fun videoScale() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.videoScale(mVideoPath, targetPath, 360, 640),
callback("视频缩放完成", targetPath))
}
}
private fun frame2Image() {
targetPath = externalCacheDir.toString() + File.separator + "target.png"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.frame2Image(mVideoPath, targetPath, "00:00:10.234"), callback("获取一帧图片成功", targetPath))
}
}
private fun audio2Fdkaac() {
targetPath = externalCacheDir.toString() + File.separator + "target.aac"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.audio2Fdkaac(mAudioPath, targetPath), callback("mp3转aac成功", targetPath))
}
}
private fun audio2Mp3lame() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp3"
val aac = externalCacheDir.toString() + File.separator + "target.aac"
if (!File(aac).exists()) {
ToastUtils.show("请先执行音频转fdk_aac")
return
}
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.audio2Mp3lame(aac, targetPath), callback("acc转mp3成功", targetPath))
}
}
private fun video2HLS() {
val dir = File(externalCacheDir, "hls")
if (!dir.exists()) {
dir.mkdir()
} else {
val files = dir.listFiles()
for (file in files) {
file.delete()
}
}
targetPath = dir.toString() + File.separator + "target.m3u8"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.video2HLS(mVideoPath, targetPath, 10), callback("切片成功", targetPath))
}
}
private fun hls2Video() {
val dir = File(externalCacheDir, "hls")
if (!dir.exists()) {
ToastUtils.show("请先执行video->hls")
return
}
val videoIndexFile = File(dir, "target.m3u8")
if (!videoIndexFile.exists()) {
ToastUtils.show("请先执行video->hls")
return
}
targetPath = dir.toString() + File.separator + "target.mp4"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.hls2Video(videoIndexFile.absolutePath, targetPath), callback("合成切片成功", targetPath))
}
}
private fun audio2Amr() {
targetPath = externalCacheDir.toString() + File.separator + "target.amr"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.audio2Amr(mAudioPath, targetPath), callback("mp3转amr成功", targetPath))
}
}
private fun makeMuteAudio() {
targetPath = externalCacheDir.toString() + File.separator + "target.mp3"
GlobalScope.launch {
FFmpegCommand.runCmd(FFmpegUtils.makeMuteAudio(targetPath), callback("生成静音文件成功", targetPath))
}
}
private fun splitmute(){
GlobalScope.launch {
var commands = "ffmpeg -i %s -af pan=1c|c0=c0,silencedetect=n=-35dB:d=0.100 -f null /dev/null"
var cmd:Array<String?> = String.format(commands,mAudioPath).split(" ").toTypedArray()
FFmpegCommand.runCmd(cmd, callback("检测静音", targetPath))
}
}
// 推流
private fun rtmp(){
GlobalScope.launch {
// 需替换成你的推流地址
var cmd:Array<String?> = FFmpegUtils.rtmp(mVideoPath,"rtmp://192.168.2.101:1935/live/film")
FFmpegCommand.runCmd(cmd, callback("推流", targetPath))
}
}
private fun callback(msg: String, targetPath: String?): CommonCallBack? {
return object : CommonCallBack() {
override fun onStart() {
Log.d("FFmpegCmd", "onStart")
runOnUiThread {
mErrorDialog?.show(supportFragmentManager, "Dialog")
}
}
override fun onComplete() {
Log.d("FFmpegCmd", "onComplete")
runOnUiThread {
ToastUtils.show(msg)
mErrorDialog?.setContent(0)
mErrorDialog?.dismissAllowingStateLoss()
tvContent?.text = targetPath
}
}
override fun onCancel() {
runOnUiThread {
ToastUtils.show("用户取消")
mErrorDialog?.setContent(0)
}
Log.d("FFmpegCmd", "Cancel")
}
override fun onProgress(progress: Int, pts: Long) {
var duration :Int? = FFmpegCommand.getMediaInfo(mAudioPath,MediaAttribute.DURATION)
var progressN = pts/duration!!
Log.d("FFmpegCmd", progress.toString() + "")
runOnUiThread { mErrorDialog?.setContent(progress) }
}
override fun onError(errorCode: Int, errorMsg: String?) {
Log.d("FFmpegCmd", errorMsg)
runOnUiThread {
ToastUtils.show(errorMsg)
mErrorDialog?.setContent(0)
mErrorDialog?.dismissAllowingStateLoss()
}
}
}
}
companion object {
fun start(context: Context) {
val intent = Intent(context, KFFmpegCommandActivity::class.java)
context.startActivity(intent)
}
}
}
Android
1
https://gitee.com/andios/FFmpegCommand.git
git@gitee.com:andios/FFmpegCommand.git
andios
FFmpegCommand
FFmpegCommand
master

搜索帮助