Seb*_*ies 13
您可以使用我的mp4parser库执行此操作.看看ShortenExample,它完全符合名称的建议.由于图书馆无法对视频进行重新编码,因此只能以I帧剪切视频.因此,您可以进行切割的时间点非常粗糙.
在Android 4.1上,您可以通过MediaCodec API访问硬件编解码器,这可能是一个选项(但我还没有看到任何示例)
我们可以在Android中使用ffmpeg剪切视频.
为了在android中集成FFmpeg,我们可以使用像ffmpeg-android这样的预编译库.
要剪切视频,我们可以使用以下命令 -
String[] complexCommand = {"-ss", "" + startMs / 1000, "-y", "-i", inputFileAbsolutePath, "-t", "" + (endMs - startMs) / 1000, "-s", "320x240", "-r", "15", "-vcodec", "mpeg4", "-b:v", "2097152", "-b:a", "48000", "-ac", "2", "-ar", "22050", outputFileAbsolutePath};
Run Code Online (Sandbox Code Playgroud)
这里,
-ss
寻求定位
-y
无需询问即可覆盖输出文件.
-一世
ffmpeg从-i选项指定的任意数量的输入"文件"中读取
-t
限制从输入文件读取的数据的持续时间
-s
视频输出大小
-r
设置帧速率
-vcodec
设置视频编解码器.
-b:v
设置视频比特率
-b:一
设置音频比特率
-ac
设置音频通道的数量.
-ar
如果编码,则设置音频流的采样率
startMs
从您想要剪切的位置开始的视频开始时间(以毫秒为单位)
endMs
视频的结束时间,以毫秒为单位,您希望剪切
我已经创建了一个使用FFMpeg编辑视频的示例android项目,其中包括剪切视频.请查看 -
https://github.com/bhuvnesh123/FFmpeg-Video-Editor-Android
及其教程 -
https://androidlearnersite.wordpress.com/2017/03/17/ffmpeg-video-editor/
尝试这个
Intent trimVideoIntent = new Intent("com.android.camera.action.TRIM");
// The key for the extra has been discovered from com.android.gallery3d.app.PhotoPage.KEY_MEDIA_ITEM_PATH
trimVideoIntent.putExtra("media-item-path",FilePath);
trimVideoIntent.setData(videoUri);
// Check if the device can handle the Intent
List<ResolveInfo> list = getPackageManager().queryIntentActivities(trimVideoIntent, 0);
if (null != list && list.size() > 0) {
startActivity(trimVideoIntent); // Fires TrimVideo activity into being active
}else {
Toast.makeText(this, "not supported",Toast.LENGTH_SHORT).show();
}
Run Code Online (Sandbox Code Playgroud)
它适用于已安装 Gallery2 软件包的设备
您可以MediaCodec
在android中使用API。
import android.media.MediaCodec.BufferInfo
import android.media.MediaExtractor
import android.media.MediaFormat
import android.media.MediaMetadataRetriever
import android.media.MediaMuxer
import java.io.IOException
import java.nio.ByteBuffer
import android.os.Handler
import android.os.Looper
class VideoUtils {
companion object {
/**
* @param srcPath the path of source video file.
* @param dstPath the path of destination video file.
* @param startMs starting time in milliseconds for trimming. Set to
* negative if starting from beginning.
* @param endMs end time for trimming in milliseconds. Set to negative if
* no trimming at the end.
* @param useAudio true if keep the audio track from the source.
* @param useVideo true if keep the video track from the source.
* @throws IOException
*/
@Throws(IOException::class)
fun startTrim(
srcPath: String, dstPath: String,
startMs: Int, endMs: Int, useAudio: Boolean, useVideo: Boolean,
listener: Listener
) {
runOnUiThread {
listener.onStart()
}
// Set up MediaExtractor to read from the source.
val extractor = MediaExtractor()
extractor.setDataSource(srcPath)
val trackCount = extractor.trackCount
// Set up MediaMuxer for the destination.
val muxer = MediaMuxer(dstPath, MediaMuxer.OutputFormat.MUXER_OUTPUT_MPEG_4)
// Set up the tracks and retrieve the max buffer size for selected
// tracks.
val indexMap = HashMap<Int, Int>(trackCount)
var bufferSize = -1
for (i in 0 until trackCount) {
val format = extractor.getTrackFormat(i)
val mime = format.getString(MediaFormat.KEY_MIME)
var selectCurrentTrack = false
if (mime!!.startsWith("audio/") && useAudio) {
selectCurrentTrack = true
} else if (mime.startsWith("video/") && useVideo) {
selectCurrentTrack = true
}
if (selectCurrentTrack) {
extractor.selectTrack(i)
val dstIndex = muxer.addTrack(format)
indexMap[i] = dstIndex
if (format.containsKey(MediaFormat.KEY_MAX_INPUT_SIZE)) {
val newSize = format.getInteger(MediaFormat.KEY_MAX_INPUT_SIZE)
bufferSize = if (newSize > bufferSize) newSize else bufferSize
}
}
}
if (bufferSize < 0) {
bufferSize = DEFAULT_BUFFER_SIZE
}
// Set up the orientation and starting time for extractor.
val retrieverSrc = MediaMetadataRetriever()
retrieverSrc.setDataSource(srcPath)
val degreesString = retrieverSrc.extractMetadata(
MediaMetadataRetriever.METADATA_KEY_VIDEO_ROTATION
)
if (degreesString != null) {
val degrees = degreesString.toInt()
if (degrees >= 0) {
muxer.setOrientationHint(degrees)
}
}
if (startMs > 0) {
extractor.seekTo((startMs * 1000).toLong(), MediaExtractor.SEEK_TO_CLOSEST_SYNC)
}
// Copy the samples from MediaExtractor to MediaMuxer. We will loop
// for copying each sample and stop when we get to the end of the source
// file or exceed the end time of the trimming.
val offset = 0
var trackIndex: Int
val dstBuf = ByteBuffer.allocate(bufferSize)
val bufferInfo = BufferInfo()
val totalTimeMs = endMs - startMs
try {
muxer.start()
while (true) {
bufferInfo.offset = offset
bufferInfo.size = extractor.readSampleData(dstBuf, offset)
if (bufferInfo.size < 0) {
runOnUiThread {
listener.onComplete()
}
bufferInfo.size = 0
break
} else {
bufferInfo.presentationTimeUs = extractor.sampleTime
if (endMs > 0 && bufferInfo.presentationTimeUs > endMs * 1000) {
runOnUiThread {
listener.onComplete()
}
break
} else {
bufferInfo.flags = extractor.sampleFlags
trackIndex = extractor.sampleTrackIndex
muxer.writeSampleData(
indexMap[trackIndex]!!, dstBuf,
bufferInfo
)
runOnUiThread {
listener.onProgress((bufferInfo.presentationTimeUs / 1000 - startMs).toFloat() / totalTimeMs)
}
extractor.advance()
}
}
}
muxer.stop()
} catch (e: IllegalStateException) {
runOnUiThread {
listener.onError("The source video file is malformed")
}
} finally {
muxer.release()
}
return
}
}
interface Listener {
fun onStart()
fun onProgress(value: Float)
fun onComplete()
fun onError(message: String)
}
}
private val mHandler = Handler(Looper.getMainLooper())
fun runOnUiThread(closure: () -> Unit) {
mHandler.post {
closure()
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
27753 次 |
最近记录: |