android 视频画面拼接,Android实现视频剪切、视频拼接以及音视频合并

这个Java类库提供了对MP4文件的处理功能,包括MP4和AAC文件的追加合并、混合、分离以及添加字幕等操作。它支持按顺序合并多个MP4文件的音频和视频轨道,也能将AAC文件与MP4视频合并,同时能从MP4文件中提取音频或视频轨道。此外,还具备MP4视频的裁剪功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/*** mp4处理公共类* Created by lxy on 17-4-21.*/public classMp4ParseUtil {

/***对Mp4文件集合进行追加合并(按照顺序一个一个拼接起来)**@parammp4PathList[输入]Mp4文件路径的集合(支持m4a)(不支持wav)*@paramoutPutPath[输出]结果文件全部名称包含后缀(比如.mp4)*@throwsIOException格式不支持等情况抛出异常*/public static voidappendMp4List(List mp4PathList, String outPutPath){

try{

List mp4MovieList = newArrayList<>();// Movie对象集合[输入]for(String mp4Path : mp4PathList) {//将每个文件路径都构建成一个Movie对象mp4MovieList.add(MovieCreator.build(mp4Path));

}

List audioTracks = newLinkedList<>();//音频通道集合List videoTracks = newLinkedList<>();//视频通道集合for(Movie mp4Movie : mp4MovieList) {//对Movie对象集合进行循环for(Track inMovieTrack : mp4Movie.getTracks()) {

if("soun".equals(inMovieTrack.getHandler())) {//从Movie对象中取出音频通道audioTracks.add(inMovieTrack);

}

if("vide".equals(inMovieTrack.getHandler())) {//从Movie对象中取出视频通道videoTracks.add(inMovieTrack);

}

}

}

Movie resultMovie = newMovie();//结果Movie对象[输出]if(!audioTracks.isEmpty()) {//将所有音频通道追加合并resultMovie.addTrack(newAppendTrack(audioTracks.toArray(newTrack[audioTracks.size()])));

}

if(!videoTracks.isEmpty()) {//将所有视频通道追加合并resultMovie.addTrack(newAppendTrack(videoTracks.toArray(newTrack[videoTracks.size()])));

}

Container outContainer = newDefaultMp4Builder().build(resultMovie);//将结果Movie对象封装进容器FileChannel fileChannel = newRandomAccessFile(String.format(outPutPath), "rw").getChannel();

outContainer.writeContainer(fileChannel);//将容器内容写入磁盘fileChannel.close();

}catch(Exception e){

e.printStackTrace();

}

}

/***对AAC文件集合进行追加合并(按照顺序一个一个拼接起来)**@paramaacPathList[输入]AAC文件路径的集合(不支持wav)*@paramoutPutPath[输出]结果文件全部名称包含后缀(比如.aac)*@throwsIOException格式不支持等情况抛出异常*/public static voidappendAacList(List aacPathList, String outPutPath){

try{

List audioTracks = newLinkedList<>();//音频通道集合for(inti = 0; i < aacPathList.size(); i++) {//将每个文件路径都构建成一个AACTrackImpl对象audioTracks.add(newAACTrackImpl(newFileDataSourceImpl(aacPathList.get(i))));

}

Movie resultMovie = newMovie();//结果Movie对象[输出]if(!audioTracks.isEmpty()) {//将所有音频通道追加合并resultMovie.addTrack(newAppendTrack(audioTracks.toArray(newTrack[audioTracks.size()])));

}

Container outContainer = newDefaultMp4Builder().build(resultMovie);//将结果Movie对象封装进容器FileChannel fileChannel = newRandomAccessFile(String.format(outPutPath), "rw").getChannel();

outContainer.writeContainer(fileChannel);//将容器内容写入磁盘fileChannel.close();

}catch(Exception e){

e.printStackTrace();

}

}

private staticList moviesList= newArrayList<>();

private staticList videoTracks= newArrayList<>();

private staticList audioTracks= newArrayList<>();

//将两个mp4视频进行拼接public static voidappendMp4(List mMp4List,String outputpath){

try{

for(inti=0;i

Movie movie=MovieCreator.build(mMp4List.get(i));

moviesList.add(movie);

}

} catch(IOException e) {

e.printStackTrace();

}

for(Movie m : moviesList) {

for(Track t : m.getTracks()) {

if(t.getHandler().equals("soun")) {

audioTracks.add(t);

}

if(t.getHandler().equals("vide")) {

videoTracks.add(t);

}

}

}

Movie result = newMovie();

try{

if(audioTracks.size() > 0) {

result.addTrack(newAppendTrack(audioTracks.toArray(newTrack[audioTracks.size()])));

}

if(videoTracks.size() > 0) {

result.addTrack(newAppendTrack(videoTracks.toArray(newTrack[videoTracks.size()])));

}

} catch(IOException e) {

e.printStackTrace();

}

Container out = newDefaultMp4Builder().build(result);

try{

FileChannel fc = newFileOutputStream(newFile(outputpath)).getChannel();

out.writeContainer(fc);

fc.close();

} catch(Exception e) {

e.printStackTrace();

}

moviesList.clear();

}

/***将AAC和MP4进行混合[替换了视频的音轨]**@paramaacPath.aac*@parammp4Path.mp4*@paramoutPath.mp4*/public static booleanmuxAacMp4(String aacPath, String mp4Path, String outPath) {

booleanflag=false;

try{

AACTrackImpl aacTrack = newAACTrackImpl(newFileDataSourceImpl(aacPath));

Movie videoMovie = MovieCreator.build(mp4Path);

Track videoTracks = null;//获取视频的单纯视频部分for(Track videoMovieTrack : videoMovie.getTracks()) {

if("vide".equals(videoMovieTrack.getHandler())) {

videoTracks = videoMovieTrack;

}

}

Movie resultMovie = newMovie();

resultMovie.addTrack(videoTracks);//视频部分resultMovie.addTrack(aacTrack);//音频部分Container out = newDefaultMp4Builder().build(resultMovie);

FileOutputStream fos = newFileOutputStream(newFile(outPath));

out.writeContainer(fos.getChannel());

fos.close();

flag=true;

Log.e("update_tag","merge finish");

} catch(Exception e) {

e.printStackTrace();

flag=false;

}

returnflag;

}

/***将M4A和MP4进行混合[替换了视频的音轨]**@paramm4aPath.m4a[同样可以使用.mp4]*@parammp4Path.mp4*@paramoutPath.mp4*/public static voidmuxM4AMp4(String m4aPath, String mp4Path, String outPath) throwsIOException {

Movie audioMovie = MovieCreator.build(m4aPath);

Track audioTracks = null;//获取视频的单纯音频部分for(Track audioMovieTrack : audioMovie.getTracks()) {

if("soun".equals(audioMovieTrack.getHandler())) {

audioTracks = audioMovieTrack;

}

}

Movie videoMovie = MovieCreator.build(mp4Path);

Track videoTracks = null;//获取视频的单纯视频部分for(Track videoMovieTrack : videoMovie.getTracks()) {

if("vide".equals(videoMovieTrack.getHandler())) {

videoTracks = videoMovieTrack;

}

}

Movie resultMovie = newMovie();

resultMovie.addTrack(videoTracks);//视频部分resultMovie.addTrack(audioTracks);//音频部分Container out = newDefaultMp4Builder().build(resultMovie);

FileOutputStream fos = newFileOutputStream(newFile(outPath));

out.writeContainer(fos.getChannel());

fos.close();

}

/***分离mp4视频的音频部分,只保留视频部分**@parammp4Path.mp4*@paramoutPath.mp4*/public static voidsplitMp4(String mp4Path, String outPath){

try{

Movie videoMovie = MovieCreator.build(mp4Path);

Track videoTracks = null;//获取视频的单纯视频部分for(Track videoMovieTrack : videoMovie.getTracks()) {

if("vide".equals(videoMovieTrack.getHandler())) {

videoTracks = videoMovieTrack;

}

}

Movie resultMovie = newMovie();

resultMovie.addTrack(videoTracks);//视频部分Container out = newDefaultMp4Builder().build(resultMovie);

FileOutputStream fos = newFileOutputStream(newFile(outPath));

out.writeContainer(fos.getChannel());

fos.close();

}catch(Exception e){

e.printStackTrace();

}

}

/***分离mp4的视频部分,只保留音频部分**@parammp4Path.mp4*@paramoutPath.aac*/public static voidsplitAac(String mp4Path, String outPath){

try{

Movie videoMovie = MovieCreator.build(mp4Path);

Track videoTracks = null;//获取音频的单纯视频部分for(Track videoMovieTrack : videoMovie.getTracks()) {

if("soun".equals(videoMovieTrack.getHandler())) {

videoTracks = videoMovieTrack;

}

}

Movie resultMovie = newMovie();

resultMovie.addTrack(videoTracks);//音频部分Container out = newDefaultMp4Builder().build(resultMovie);

FileOutputStream fos = newFileOutputStream(newFile(outPath));

out.writeContainer(fos.getChannel());

fos.close();

}catch(Exception e){

e.printStackTrace();

}

}

/***分离mp4视频的音频部分,只保留视频部分**@parammp4Path.mp4*@parammp4OutPathmp4视频输出路径*@paramaacOutPathaac视频输出路径*/public static voidsplitVideo(String mp4Path, String mp4OutPath,String aacOutPath){

try{

Movie videoMovie = MovieCreator.build(mp4Path);

Track videTracks = null;//获取视频的单纯视频部分Track sounTracks = null;//获取视频的单纯音频部分for(Track videoMovieTrack : videoMovie.getTracks()) {

if("vide".equals(videoMovieTrack.getHandler())) {

videTracks = videoMovieTrack;

}

if("soun".equals(videoMovieTrack.getHandler())) {

sounTracks = videoMovieTrack;

}

}

Movie videMovie = newMovie();

videMovie.addTrack(videTracks);//视频部分Movie sounMovie = newMovie();

sounMovie.addTrack(sounTracks);//音频部分//视频部分Container videout = newDefaultMp4Builder().build(videMovie);

FileOutputStream videfos = newFileOutputStream(newFile(mp4OutPath));

videout.writeContainer(videfos.getChannel());

videfos.close();

//音频部分Container sounout = newDefaultMp4Builder().build(sounMovie);

FileOutputStream sounfos = newFileOutputStream(newFile(aacOutPath));

sounout.writeContainer(sounfos.getChannel());

sounfos.close();

}catch(Exception e){

e.printStackTrace();

}

}

/***对Mp4添加字幕**@parammp4Path.mp4添加字幕之前*@paramoutPath.mp4添加字幕之后*/public static voidaddSubtitles(String mp4Path, String outPath) throwsIOException {

Movie videoMovie = MovieCreator.build(mp4Path);

TextTrackImpl subTitleEng = newTextTrackImpl();//实例化文本通道对象subTitleEng.getTrackMetaData().setLanguage("eng");//设置元数据(语言)subTitleEng.getSubs().add(newTextTrackImpl.Line(0, 1000, "Five"));//参数时间毫秒值subTitleEng.getSubs().add(newTextTrackImpl.Line(1000, 2000, "Four"));

subTitleEng.getSubs().add(newTextTrackImpl.Line(2000, 3000, "Three"));

subTitleEng.getSubs().add(newTextTrackImpl.Line(3000, 4000, "Two"));

subTitleEng.getSubs().add(newTextTrackImpl.Line(4000, 5000, "one"));

subTitleEng.getSubs().add(newTextTrackImpl.Line(5001, 5002, " "));//省略去测试videoMovie.addTrack(subTitleEng);//将字幕通道添加进视频Movie对象中Container out = newDefaultMp4Builder().build(videoMovie);

FileOutputStream fos = newFileOutputStream(newFile(outPath));

out.writeContainer(fos.getChannel());

fos.close();

}

/***将MP4切割**@parammp4Path.mp4*@paramfromSample起始位置 不是传入的秒数*@paramtoSample结束位置 不是传入的秒数*@paramoutPath.mp4*/public static voidcropMp4(String mp4Path, longfromSample, longtoSample, String outPath){

try{

Movie mp4Movie = MovieCreator.build(mp4Path);

Track videoTracks = null;//获取视频的单纯视频部分for(Track videoMovieTrack : mp4Movie.getTracks()) {

if("vide".equals(videoMovieTrack.getHandler())) {

videoTracks = videoMovieTrack;

}

}

Track audioTracks = null;//获取视频的单纯音频部分for(Track audioMovieTrack : mp4Movie.getTracks()) {

if("soun".equals(audioMovieTrack.getHandler())) {

audioTracks = audioMovieTrack;

}

}

Movie resultMovie = newMovie();

resultMovie.addTrack(newAppendTrack(newCroppedTrack(videoTracks, fromSample, toSample)));//视频部分resultMovie.addTrack(newAppendTrack(newCroppedTrack(audioTracks, fromSample, toSample)));//音频部分Container out = newDefaultMp4Builder().build(resultMovie);

FileOutputStream fos = newFileOutputStream(newFile(outPath));

out.writeContainer(fos.getChannel());

fos.close();

}catch(Exception e){

e.printStackTrace();

}

}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值