如果不是特别熟悉C/C++,又要使用FFmpeg.API处理一些简单的音视频业务,那么可以使用org.bytedeco:ffmpeg-platform,下面记录一下使用ffmpeg-platform视频转封装的方法。
1. 基本流程
- 打开输入流
- 创建输出AVFormatContext
- 读流、写流
2. 完整代码
流程比较简单,这里直接给出完成代码
public class Remuxing { public static void main(String[] args) throws IOException { remuxing("test1.flv", "t1.mp4"); } public static void remuxing(String input, String output) throws IOException { AVFormatContext ifmt_ctx = null; AVFormatContext ofmt_ctx = null; AVOutputFormat ofmt = null; AVPacket pkt = null; try { ifmt_ctx = avformat.avformat_alloc_context(); int ret = avformat.avformat_open_input(ifmt_ctx, input, null, null); if (ret < 0) { throw new IOException(ret + ":avformat_open_input error"); } ret = avformat.avformat_find_stream_info(ifmt_ctx, (AVDictionary) null); if (ret < 0) { throw new IOException(ret + ":avformat_find_stream_info error"); } ofmt_ctx = new AVFormatContext(null); ret = avformat.avformat_alloc_output_context2(ofmt_ctx, null, null, output); if (ret < 0) { throw new IOException(ret + ":avformat_alloc_output_context2 error"); } int stream_mapping_size = ifmt_ctx.nb_streams(); int[] stream_mapping = new int[stream_mapping_size]; int stream_index = 0; for (int i = 0; i < ifmt_ctx.nb_streams(); i++) { AVStream in_stream = ifmt_ctx.streams(i); AVCodecParameters in_codecpar = in_stream.codecpar(); if (in_codecpar.codec_type() != avutil.AVMEDIA_TYPE_AUDIO && in_codecpar.codec_type() != avutil.AVMEDIA_TYPE_VIDEO && in_codecpar.codec_type() != avutil.AVMEDIA_TYPE_SUBTITLE) { stream_mapping[i] = -1; continue; } stream_mapping[i] = stream_index++; AVStream out_stream = avformat.avformat_new_stream(ofmt_ctx, null); if (out_stream == null) { throw new IOException("avformat_new_stream error"); } ret = avcodec.avcodec_parameters_copy(out_stream.codecpar(), in_codecpar); if (ret < 0) { throw new IOException(ret + ":avcodec_parameters_copy error"); } out_stream.codecpar().codec_tag(0); } ofmt = ofmt_ctx.oformat(); if ((ofmt.flags() & avformat.AVFMT_NOFILE) == 0) { AVIOContext pb = new AVIOContext(null); ret = avformat.avio_open(pb, output, avformat.AVIO_FLAG_WRITE); if (ret < 0) { throw new IOException(ret + ":avio_open error"); } ofmt_ctx.pb(pb); } ret = avformat.avformat_write_header(ofmt_ctx, (AVDictionary) null); if (ret < 0) { throw new IOException(ret + ":avformat_write_header error"); } AVStream in_stream, out_stream; pkt = avcodec.av_packet_alloc(); while (true) { ret = avformat.av_read_frame(ifmt_ctx, pkt); if (ret < 0) { break; } in_stream = ifmt_ctx.streams(pkt.stream_index()); if (pkt.stream_index() >= stream_mapping_size || stream_mapping[pkt.stream_index()] < 0) { avcodec.av_packet_unref(pkt); continue; } pkt.stream_index(stream_mapping[pkt.stream_index()]); out_stream = ofmt_ctx.streams(pkt.stream_index()); pkt.pts(avutil.av_rescale_q_rnd(pkt.pts(), in_stream.time_base(), out_stream.time_base(), avutil.AV_ROUND_NEAR_INF | avutil.AV_ROUND_PASS_MINMAX)); pkt.dts(avutil.av_rescale_q_rnd(pkt.dts(), in_stream.time_base(), out_stream.time_base(), avutil.AV_ROUND_NEAR_INF | avutil.AV_ROUND_PASS_MINMAX)); pkt.duration(avutil.av_rescale_q(pkt.duration(), in_stream.time_base(), out_stream.time_base())); pkt.pos(-1); ret = avformat.av_interleaved_write_frame(ofmt_ctx, pkt); if (ret < 0) { throw new IOException(ret + ":av_interleaved_write_frame error"); } } ret = avformat.av_write_trailer(ofmt_ctx); if (ret < 0) { throw new IOException(ret + ":av_write_trailer error"); } } finally { if (Objects.nonNull(pkt)) { avcodec.av_packet_free(pkt); } if (Objects.nonNull(ifmt_ctx)) { avformat.avformat_close_input(ifmt_ctx); } if (Objects.nonNull(ofmt_ctx)) { if (Objects.nonNull(ofmt)) { if ((ofmt.flags() & avformat.AVFMT_NOFILE) == 0) { avformat.avio_closep(ofmt_ctx.pb()); } } avformat.avformat_free_context(ofmt_ctx); } } } }
注意:视频DTS有问题的话,av_interleaved_write_frame可能会有问题。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· .NET10 - 预览版1新功能体验(一)