我正在为电影编辑应用程序创建一个保存到设备功能,该应用程序将一个视频轨道与一个(或可选的两个)音频轨道合并。
首先,我使用MP4Parser(link)将多个视频剪辑合并到一个视频轨道中。
然后,我想将多个音频剪辑合并到一个音轨中。不应附加这些剪辑,而是在特定时间合并为单个音轨。例如。我们有两个音频剪辑(A1,A2)和一个60秒的视频轨道(V1)。这些音频剪辑可能重叠,或者它们之间有白噪声。整个音轨的长度必须与视频轨道匹配,最长可达60秒。 音频轨道1中最多可添加100个音频剪辑
最后,可能还有一个包含音轨的可选第二音轨,适合V1视频轨道。
这就是它的样子:
视频曲目1:[------------------------------------------ --------------------------------------] 60秒
音轨1:[ - A1 - A2 ------------------------------------- -------------------------------] 60秒
音轨2:[------------------------------------------ -------------------------------------] 60秒
我尝试通过将x秒白噪声(空wav文件)附加到音频轨道以获得如上所述的全长音轨来解决问题,但是如果声音重叠,这显然不起作用。还有哪些方法可以解决这个问题?
private static final String OUTPUT = "output.mp4";
private static final String STORED_LOCATION = "/storage/emulated/0/"
/**
* Merges two videos that are located in /storage/emulated/0/ and saves it to the same place with the given parameters. Uses the ffmpeg/javacv library. All this is done in an Async task, not blocking the UI thread but showing a progress bar and a toast at the end.
*
*/
private void mergeVideosAsync()
{
new AsyncTask<Void, Void, String>()
{
@Override
protected String doInBackground(Void... arg0)
{
try
{
List<Movie> movieList = new ArrayList<>();
for (int i = 0; i < mVideoPathList.size(); ++i)
{
movieList.add(MovieCreator.build(new File(mVideoPathList.get(i)).getAbsolutePath()));
}
List<Track> videoTracks = new LinkedList<>();
List<Track> audioTracks = new LinkedList<>();
for (Movie m : movieList)
{
for (Track t : m.getTracks())
{
if (t.getHandler().equals("soun"))
{
//TODO: Add audio tracks here to the merging process
// audioTracks.add(t);
}
if (t.getHandler().equals("vide"))
{
videoTracks.add(t);
}
}
}
Movie result = new Movie();
if (audioTracks.size() > 0)
{
result.addTrack(new AppendTrack(audioTracks.toArray(new Track[audioTracks.size()])));
}
if (videoTracks.size() > 0)
{
result.addTrack(new AppendTrack(videoTracks.toArray(new Track[videoTracks.size()])));
}
BasicContainer out = (BasicContainer) new DefaultMp4Builder().build(result);
mOutputPath = String.format(STORED_LOCATION + File.separator + OUTPUT_FILENAME);
WritableByteChannel fc = new RandomAccessFile(mOutputPath, "rw").getChannel();
out.writeContainer(fc);
fc.close();
}
catch (Exception e)
{
e.printStackTrace();
}
return mOutputPath;
}
}.execute();
}
答案 0 :(得分:0)
如果您的音轨重叠,那么您就会遇到问题,因为您需要重新编码音频。 如果音轨不重叠,那么您可以使用SilenceTrackImpl:
Track nuAudio = new AppendTrack(
audioTrackA1, new SilenceTrackImpl(100),
audioTrackA2, new SilenceTrackImpl(500),
audioTrackA3, new SilenceTrackImpl(1000),
audioTrackA4, new SilenceTrackImpl(50),
)
等等。