使用Play框架编写Java应用程序并需要一些HTTP-Live流。我打算根据需要即时分割mp4文件。我尝试了一个c-segmenter(来自Carson McDonald)并且非常快。但是,我喜欢将代码集成到我的Java应用程序中以便于控制,因此尝试了Xuggler。
然而在这个设置中,Xuggler似乎解码并重新编码了对象,因为运行它需要一些重要的时间(在MacbookPro上大约12秒内运行24秒)。有没有办法运行类似的代码,而不会做任何繁重的工作,只是为了分段切割文件?
虽然使用下面的测试代码代码非常简单:
public static void segmentMediaFile (String sourceUrl) {
Logger.debug("Starting segmenting process...");
IMediaReader mediaReader = ToolFactory.makeReader(sourceUrl);
MediaSegmenterListener listener = new MediaSegmenterListener();
IMediaReader reader = ToolFactory.makeReader(sourceUrl);
reader.addListener(listener);
int count = 0;
IMediaWriter currentWriter = makeMediaWriterFromCounter(++count, reader);
reader.addListener(currentWriter);
while (reader.readPacket() == null)
do {
if (listener.newFile()) {
reader.removeListener(currentWriter);
currentWriter.flush();
currentWriter.close();
currentWriter = makeMediaWriterFromCounter(++count, reader);
reader.addListener(currentWriter);
}
} while(false);
}
private static IMediaWriter makeMediaWriterFromCounter (final int counter, IMediaReader reader) {
String destinationUrl = "./public/testdata/test-movie/";
return ToolFactory.makeWriter(destinationUrl + counter + "_some_name.mov", reader);
}
(监听器目前只根据时间戳决定创建一个新文件)
或者这是错误的做法吗?
答案 0 :(得分:0)
我根据IPacket写了代码,算法是这样的 openOutput容器设置视频和音频的流,然后从输入容器中读取数据包并写入outputContainer。 代码工作正常,没有任何例外等,但唯一的事情是我无法看到图片而不是音频工作正常。 让我知道你的身份证我会寄给你代码,也许你会弄清楚那里有什么问题。
由于
答案 1 :(得分:0)
我开发了以下代码来分割媒体文件。但是,因为我也需要编码,
我从来没有对它进行过测试(并且没有编码工作的版本),但是从外面看文件是正确的。也许它会在途中帮助某人。 (肯定不会信任输出.m3u8文件)
public static void segmentMediaFile (String sourceFile, String destinationDir, String extension) throws Exception {
final int segmentSize = 10;
int counter = 0;
final IContainer input = IContainer.make();
// open the input file
if(!(new File(sourceFile).exists())) throw new Exception("Source file " + sourceFile + " does not exist!");
input.open(sourceFile, IContainer.Type.READ,null);
IContainer output = getOutputContainer(counter, input, destinationDir, extension);
double lastNewFilePostion = 0;
double currentFilePostion = 0;
FileWriter fstream = new FileWriter(destinationDir + "prog_index.m3u8");
BufferedWriter out = new BufferedWriter(fstream);
out.write( "#EXTM3U\n#EXT-X-TARGETDURATION:10\n#EXT-X-MEDIA-SEQUENCE:0\n");
out.close();
for(;;)
{
final IPacket pkt = IPacket.make();
if (input.readNextPacket(pkt) < 0)
break;
// Only needed to calculate the last segment size!
currentFilePostion = pkt.getTimeStamp() * pkt.getTimeBase().getValue();
if (((currentFilePostion - lastNewFilePostion) >= segmentSize) ||
(pkt.isKeyPacket() && ((currentFilePostion - lastNewFilePostion) >= segmentSize - 0.5))){
if(!((currentFilePostion - lastNewFilePostion) >= segmentSize)) Logger.debug("Keyframe overrulled segment at " + currentFilePostion);
File filename = new File(output.getURL());
int lastSegementLength = (int) (currentFilePostion - lastNewFilePostion);
writeTrailer(output);
fstream = new FileWriter(destinationDir + "prog_index.m3u8",true);
out = new BufferedWriter(fstream);
out.write("#EXTINF:" + lastSegementLength + ",\n" + filename.getName() + "\n");
out.close();
counter++;
output = getOutputContainer(counter, input, destinationDir, extension);
lastNewFilePostion = currentFilePostion;
}
output.writePacket(pkt, false);
}
// Write the m3u8 file
File filename = new File(output.getURL());
int lastSegementLength = (int) (currentFilePostion - lastNewFilePostion);
String segmentList = "#EXTINF:" + lastSegementLength + ",\n" + filename.getName() + "\n";
segmentList = segmentList + "#EXT-X-ENDLIST\n";
fstream = new FileWriter(destinationDir + "prog_index.m3u8",true);
out = new BufferedWriter(fstream);
out.write(segmentList);
out.close();
writeTrailer(output);
}
private static IContainer getOutputContainer (final int counter, IContainer input, String destinationDir, String extension) throws Exception {
IContainer output = IContainer.make();
output.open(destinationDir + "segment_" + counter + "." + extension, IContainer.Type.WRITE, null);
int numStreams = input.getNumStreams();
for(int i = 0; i < numStreams; i++)
{
final IStream stream = input.getStream(i);
final IStreamCoder coder = stream.getStreamCoder();
coder.open();
IStreamCoder newCoder = IStreamCoder.make(IStreamCoder.Direction.ENCODING, coder);
if(newCoder != null ){
output.addNewStream(i);
output.getStream(i).setStreamCoder(newCoder);
newCoder.open();
} else {
Logger.warn("Is there an invalid stream present in video file: " + input.getURL() + "! IGNORING, but this might be serious");
}
}
// write the output header
writeHeader(output);
return output;
}
private static void writeHeader(IContainer output){
output.writeHeader();
}
private static void writeTrailer(IContainer output){
// write the output trailers
output.writeTrailer();
int streams = output.getNumStreams();
for(int j = 0; j < streams; j++)
{
output.getStream(j).getStreamCoder().close();
}
output.close();
}