Android sdk剪切/修剪视频文件

时间:2012-06-26 10:24:39

标签: android video media trim

有没有办法在Android上剪切视频(mp4或3gp),比如只使用电影的最后5秒......在iphone上这可以使用AVAssetExportSession但是在android上我没有找到类似的东西,可能只是对ffmpeg库的一些引用似乎很复杂。有没有更简单的方法呢?

6 个答案:

答案 0 :(得分:11)

您可以使用我的mp4parser库执行此操作。看一下ShortenExample,它的确与顾名思义完全相同。 由于图书馆无法对视频进行重新编码,因此只能以I帧剪切视频。因此,您可以进行切割的时间点非常粗糙。

在Android 4.1上,您可以通过MediaCodec API访问硬件编解码器,这可能是一个选项(但我还没有看到任何示例)

答案 1 :(得分:6)

我们可以在Android中使用ffmpeg剪切视频。

为了在android中集成FFmpeg,我们可以使用预编译的库,如ffmpeg-android

要剪切视频,我们可以使用以下命令 -

public class SectionListDataAdapter extends RecyclerView.Adapter<SectionListDataAdapter.SingleItemRowHolder> {

    private ArrayList<SingleItemModel> itemsList;
    private Context mContext;

    public SectionListDataAdapter(Context context, ArrayList<SingleItemModel> itemsList) {
        this.itemsList = itemsList;
        this.mContext = context;
    }

    @Override
    public SingleItemRowHolder onCreateViewHolder(ViewGroup viewGroup, int i) {

        switch (i) {

            case 0:
                View viewONE = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_1, null, false);
                SingleItemRowHolder rowONE = new SingleItemRowHolder(viewONE);
                return rowONE;

            case 1:
                View viewTWO = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_2, null, false);
                SingleItemRowHolder rowTWO = new SingleItemRowHolder(viewTWO);
                return rowTWO;

            case 2:
                View viewTHREE = LayoutInflater.from(viewGroup.getContext()).inflate(R.layout.layout_3, null, false);
                SingleItemRowHolder rowTHREE = new SingleItemRowHolder(viewTHREE);
                return rowTHREE;

        }

        return null;

    }

    @Override
    public void onBindViewHolder(SingleItemRowHolder holder, int i) {

        SingleItemModel singleItem = itemsList.get(i);
        holder.tvTitle.setText(singleItem.getName());
    }

    @Override
    public int getItemCount() {
        return (null != itemsList ? itemsList.size() : 0);
    }

    public class SingleItemRowHolder extends RecyclerView.ViewHolder {

        protected TextView tvTitle;

        protected ImageView itemImage;


        public SingleItemRowHolder(View view) {
            super(view);

            this.tvTitle = (TextView) view.findViewById(R.id.tvTitle);
            this.itemImage = (ImageView) view.findViewById(R.id.itemImage);

            view.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {

                    Toast.makeText(v.getContext(), tvTitle.getText(), Toast.LENGTH_SHORT).show();

                }
            });

        }

    }

}

下面,

-ss

寻求定位

-y

无需询问即覆盖输出文件。

-i

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/

答案 2 :(得分:4)

试试这个

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();
}

它在Gallery2包安装设备上的工作

答案 3 :(得分:1)

您可以尝试使用INDE Media for Mobile - https://software.intel.com/en-us/articles/intel-inde-media-pack-for-android-tutorials

它具有代码转换\ remuxing功能作为MediaComposer类,并且可以为结果文件选择段。由于它内部使用MediaCodec API,因此非常适合电池使用,并且工作速度尽可能快

enter image description here

答案 4 :(得分:0)

使用此Android-video-trimmer android库。该库使用Exoplayer2和FFmpeg进行视频修剪

答案 5 :(得分:0)

您可以在 android 中使用 MediaCodec 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()
    }
}

参考文献:https://android.googlesource.com/platform/packages/apps/Gallery2/+/refs/heads/master/src/com/android/gallery3d/app/VideoUtils.java