package org.mp4parser.examples.exportraw; import org.apache.commons.io.IOUtils; import org.mp4parser.boxes.iso14496.part12.SubSampleInformationBox; import org.mp4parser.muxer.Movie; import org.mp4parser.muxer.Track; import org.mp4parser.muxer.builder.DefaultMp4Builder; import org.mp4parser.muxer.container.mp4.MovieCreator; import org.w3c.dom.Document; import org.w3c.dom.NodeList; import org.xml.sax.SAXException; import javax.xml.namespace.NamespaceContext; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; import javax.xml.xpath.*; import java.io.*; import java.nio.ByteBuffer; import java.util.*; import static org.mp4parser.tools.CastUtils.l2i; /** * Created by user on 06.08.2014. */ public class ExportTTMLTrack { public static void main(String[] args) throws IOException, ParserConfigurationException, SAXException, XPathExpressionException { //Movie m = MovieCreator.build("C:\\dev\\mp4parser-github\\ttml-example\\subs.uvu"); Movie m = MovieCreator.build("C:\\dev\\mp4parser-github\\output.mp4"); for (Track track : m.getTracks()) { if (track.getHandler().endsWith("vide")) { Movie vide = new Movie(Collections.singletonList(track)); DefaultMp4Builder builder = new DefaultMp4Builder(); builder.build(vide).writeContainer(new RandomAccessFile("vide_" + track.getTrackMetaData().getTrackId() + ".mp4", "rw").getChannel()); } if (track.getHandler().endsWith("soun")) { Movie vide = new Movie(Collections.singletonList(track)); DefaultMp4Builder builder = new DefaultMp4Builder(); builder.build(vide).writeContainer(new RandomAccessFile("soun_" + track.getTrackMetaData().getTrackId() + ".mp4", "rw").getChannel()); } if (track.getHandler().endsWith("subt")) { for (int i = 0; i < track.getSamples().size(); i++) { File f = new File("subtitle_" + track.getTrackMetaData().getTrackId() + "_" + i + ".xml"); f.delete(); RandomAccessFile raf = new RandomAccessFile(f, "rw"); SubSampleInformationBox subs = track.getSubsampleInformationBox(); int j = 0; ByteBuffer xmlSamplePart = null; for (SubSampleInformationBox.SubSampleEntry subSampleEntry : subs.getEntries()) { j += subSampleEntry.getSampleDelta(); if (j == (i + 1)) { // found sample entry Iterator<SubSampleInformationBox.SubSampleEntry.SubsampleEntry> subsampleIter = subSampleEntry.getSubsampleEntries().iterator(); if (subsampleIter.hasNext()) { SubSampleInformationBox.SubSampleEntry.SubsampleEntry xmlSubSampleEntry = subsampleIter.next(); ByteBuffer sample = track.getSamples().get(i).asByteBuffer(); xmlSamplePart = (ByteBuffer) sample.slice().limit(l2i(xmlSubSampleEntry.getSubsampleSize())); raf.getChannel().write(xmlSamplePart); raf.close(); DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); factory.setNamespaceAware(true); DocumentBuilder builder = factory.newDocumentBuilder(); Document document = builder.parse(f); XPathFactory xPathfactory = XPathFactory.newInstance(); NamespaceContext ctx = new NamespaceContext() { public String getNamespaceURI(String prefix) { if (prefix.equals("ttml")) { return "http://www.w3.org/ns/ttml"; } if (prefix.equals("smpte")) { return "http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt"; } return null; } public Iterator getPrefixes(String val) { return Arrays.asList("ttml", "smpte").iterator(); } public String getPrefix(String uri) { if (uri.equals("http://www.w3.org/ns/ttml")) { return "ttml"; } if (uri.equals("http://www.smpte-ra.org/schemas/2052-1/2010/smpte-tt")) { return "smpte"; } return null; } }; XPath xpath = xPathfactory.newXPath(); xpath.setNamespaceContext(ctx); XPathExpression expr = xpath.compile("/ttml:tt/ttml:body/ttml:div/@smpte:backgroundImage"); NodeList nl = (NodeList) expr.evaluate(document, XPathConstants.NODESET); HashSet<String> names = new HashSet<String>(); for (int n = 0; n < nl.getLength(); n++) { names.add(nl.item(n).getNodeValue()); } List<String> imageNames = new ArrayList<String>(names); Collections.sort(imageNames); System.out.println(nl); System.out.println(document.getFirstChild().getTextContent()); sample = ((ByteBuffer) sample.position(l2i(xmlSubSampleEntry.getSubsampleSize()))).slice(); int p = 0; while (subsampleIter.hasNext()) { SubSampleInformationBox.SubSampleEntry.SubsampleEntry picSubSampleEntry = subsampleIter.next(); ByteBuffer pic = (ByteBuffer) sample.slice().limit(l2i(picSubSampleEntry.getSubsampleSize())); sample = ((ByteBuffer) sample.position(l2i(picSubSampleEntry.getSubsampleSize()))).slice(); FileOutputStream fosPic = new FileOutputStream( "subtitle_" + track.getTrackMetaData().getTrackId() + "_" + i + "_" + imageNames.get(p++).replace(":", "_")); fosPic.getChannel().write(pic); } String content = IOUtils.toString(new FileInputStream(f)); for (String imageName : imageNames) { content = content.replaceAll(imageName, "subtitle_" + track.getTrackMetaData().getTrackId() + "_" + i + "_" + imageName.replace(":", "_")); } IOUtils.write(content, new FileOutputStream(f)); } } } if (xmlSamplePart == null) { xmlSamplePart = track.getSamples().get(i).asByteBuffer(); raf.getChannel().write(xmlSamplePart); } } } } } }