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 次 |
| 最近记录: |