Java tutorial
/* * ==================================================================== * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * ==================================================================== */ import java.awt.Rectangle; import java.awt.image.BufferedImage; import java.io.ByteArrayOutputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.URL; import java.text.DecimalFormat; import javax.imageio.ImageIO; import javax.xml.namespace.QName; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagePartName; import org.apache.poi.openxml4j.opc.PackageRelationship; import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.apache.poi.openxml4j.opc.TargetMode; import org.apache.poi.sl.usermodel.PictureData.PictureType; import org.apache.poi.util.IOUtils; import org.apache.poi.xslf.usermodel.XMLSlideShow; import org.apache.poi.xslf.usermodel.XSLFPictureData; import org.apache.poi.xslf.usermodel.XSLFPictureShape; import org.apache.poi.xslf.usermodel.XSLFSlide; import org.apache.xmlbeans.XmlCursor; import org.openxmlformats.schemas.presentationml.x2006.main.CTExtension; import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink; import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; import org.openxmlformats.schemas.presentationml.x2006.main.CTApplicationNonVisualDrawingProps; import org.openxmlformats.schemas.presentationml.x2006.main.CTPicture; import org.openxmlformats.schemas.presentationml.x2006.main.CTSlide; import org.openxmlformats.schemas.presentationml.x2006.main.CTTLCommonMediaNodeData; import org.openxmlformats.schemas.presentationml.x2006.main.CTTLCommonTimeNodeData; import org.openxmlformats.schemas.presentationml.x2006.main.CTTimeNodeList; import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeIndefinite; import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeNodeFillType; import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeNodeRestartType; import org.openxmlformats.schemas.presentationml.x2006.main.STTLTimeNodeType; import com.xuggle.mediatool.IMediaReader; import com.xuggle.mediatool.MediaListenerAdapter; import com.xuggle.mediatool.ToolFactory; import com.xuggle.mediatool.event.IVideoPictureEvent; import com.xuggle.xuggler.Global; import com.xuggle.xuggler.IContainer; import com.xuggle.xuggler.io.InputOutputStreamHandler; /** * Adding multiple videos to a slide * * need the Xuggler 5.4 jars: * <repositories> * <repository> * <id>xuggle repo</id> * <url>http://xuggle.googlecode.com/svn/trunk/repo/share/java/</url> * </repository> * </repositories> * ... * <dependency> * <groupId>xuggle</groupId> * <artifactId>xuggle-xuggler</artifactId> * <version>5.4</version> * </dependency> * * @see <a href="http://stackoverflow.com/questions/15197300/apache-poi-xslf-adding-movie-to-the-slide">Apache POI XSLF Adding movie to the slide</a> * @see <a href="http://apache-poi.1045710.n5.nabble.com/Question-about-embedded-video-in-PPTX-files-tt5718461.html">Question about embedded video in PPTX files</a> */ public class AddAudioToPptx { static DecimalFormat df_time = new DecimalFormat("0.####"); public static void main(String[] args) throws Exception { URL video = new URL("http://archive.org/download/test-mpeg/test-mpeg.mpg"); // URL video = new URL("file:test-mpeg.mpg"); XMLSlideShow pptx = new XMLSlideShow(); // add video file String videoFileName = "lego_edsheeran.mp3"; PackagePartName partName = PackagingURIHelper.createPartName("/ppt/media/" + videoFileName); PackagePart part = pptx.getPackage().createPart(partName, "audio/mpeg"); OutputStream partOs = part.getOutputStream(); //InputStream fis = video.openStream(); FileInputStream fis = new FileInputStream(videoFileName); byte buf[] = new byte[1024]; for (int readBytes; (readBytes = fis.read(buf)) != -1; partOs.write(buf, 0, readBytes)) ; fis.close(); partOs.close(); XSLFSlide slide1 = pptx.createSlide(); byte[] picture = IOUtils.toByteArray(new FileInputStream("audio.png")); //adding the image to the presentation XSLFPictureData idx = pptx.addPicture(picture, XSLFPictureData.PictureType.PNG); //creating a slide with given picture on it XSLFPictureShape pv1 = slide1.createPicture(idx); //XSLFPictureShape pv1 = // addPreview(pptx, slide1, part, 5, 50, 80); addAudio(pptx, slide1, part, pv1, 5); addTimingInfo(slide1, pv1); //XSLFPictureShape pv2 = addPreview(pptx, slide1, part, 9, 50, 250); //addVideo(pptx, slide1, part, pv2, 9); //addTimingInfo(slide1, pv2); FileOutputStream fos = new FileOutputStream("pptx-with-audio.pptx"); pptx.write(fos); fos.close(); pptx.close(); } static XSLFPictureShape addPreview(XMLSlideShow pptx, XSLFSlide slide1, PackagePart videoPart, double seconds, int x, int y) throws IOException { // get preview after 5 sec. IContainer ic = IContainer.make(); InputOutputStreamHandler iosh = new InputOutputStreamHandler(videoPart.getInputStream()); if (ic.open(iosh, IContainer.Type.READ, null) < 0) return null; IMediaReader mediaReader = ToolFactory.makeReader(ic); // stipulate that we want BufferedImages created in BGR 24bit color space mediaReader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR); ImageSnapListener isl = new ImageSnapListener(seconds); mediaReader.addListener(isl); // read out the contents of the media file and // dispatch events to the attached listener while (!isl.hasFired && mediaReader.readPacket() == null) ; mediaReader.close(); ic.close(); // add snapshot BufferedImage image1 = isl.image; ByteArrayOutputStream bos = new ByteArrayOutputStream(); ImageIO.write(image1, "jpeg", bos); XSLFPictureData snap = pptx.addPicture(bos.toByteArray(), PictureType.JPEG); XSLFPictureShape pic1 = slide1.createPicture(snap); pic1.setAnchor(new Rectangle(x, y, image1.getWidth(), image1.getHeight())); return pic1; } static void addAudio(XMLSlideShow pptx, XSLFSlide slide1, PackagePart videoPart, XSLFPictureShape pic1, double seconds) throws IOException { // add video shape PackagePartName partName = videoPart.getPartName(); PackageRelationship prsEmbed1 = slide1.getPackagePart().addRelationship(partName, TargetMode.INTERNAL, "http://schemas.microsoft.com/office/2007/relationships/media"); PackageRelationship prsExec1 = slide1.getPackagePart().addRelationship(partName, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/audio"); CTPicture xpic1 = (CTPicture) pic1.getXmlObject(); CTHyperlink link1 = xpic1.getNvPicPr().getCNvPr().addNewHlinkClick(); link1.setId(""); link1.setAction("ppaction://media"); // add video relation CTApplicationNonVisualDrawingProps nvPr = xpic1.getNvPicPr().getNvPr(); nvPr.addNewVideoFile().setLink(prsExec1.getId()); CTExtension ext = nvPr.addNewExtLst().addNewExt(); // see http://msdn.microsoft.com/en-us/library/dd950140(v=office.12).aspx ext.setUri("{DAA4B4D4-6D71-4841-9C94-3DE7FCFB9230}"); String p14Ns = "http://schemas.microsoft.com/office/powerpoint/2010/main"; XmlCursor cur = ext.newCursor(); cur.toEndToken(); cur.beginElement(new QName(p14Ns, "media", "p14")); cur.insertNamespace("p14", p14Ns); cur.insertAttributeWithValue(new QName(STRelationshipId.type.getName().getNamespaceURI(), "embed"), prsEmbed1.getId()); cur.beginElement(new QName(p14Ns, "trim", "p14")); cur.insertAttributeWithValue("st", df_time.format(seconds * 1000.0)); cur.dispose(); } static void addTimingInfo(XSLFSlide slide1, XSLFPictureShape pic1) { // add slide timing information, so video can be controlled CTSlide xslide = slide1.getXmlObject(); CTTimeNodeList ctnl; if (!xslide.isSetTiming()) { CTTLCommonTimeNodeData ctn = xslide.addNewTiming().addNewTnLst().addNewPar().addNewCTn(); ctn.setDur(STTLTimeIndefinite.INDEFINITE); ctn.setRestart(STTLTimeNodeRestartType.NEVER); ctn.setNodeType(STTLTimeNodeType.TM_ROOT); ctnl = ctn.addNewChildTnLst(); } else { ctnl = xslide.getTiming().getTnLst().getParArray(0).getCTn().getChildTnLst(); } CTTLCommonMediaNodeData cmedia = ctnl.addNewVideo().addNewCMediaNode(); cmedia.setVol(80000); CTTLCommonTimeNodeData ctn = cmedia.addNewCTn(); ctn.setFill(STTLTimeNodeFillType.HOLD); ctn.setDisplay(false); ctn.addNewStCondLst().addNewCond().setDelay(STTLTimeIndefinite.INDEFINITE); cmedia.addNewTgtEl().addNewSpTgt().setSpid("" + pic1.getShapeId()); } static class ImageSnapListener extends MediaListenerAdapter { final double SECONDS_BETWEEN_FRAMES; final long MICRO_SECONDS_BETWEEN_FRAMES; boolean hasFired = false; BufferedImage image = null; // The video stream index, used to ensure we display frames from one and // only one video stream from the media container. int mVideoStreamIndex = -1; // Time of last frame write long mLastPtsWrite = Global.NO_PTS; public ImageSnapListener(double seconds) { SECONDS_BETWEEN_FRAMES = seconds; MICRO_SECONDS_BETWEEN_FRAMES = (long) (Global.DEFAULT_PTS_PER_SECOND * SECONDS_BETWEEN_FRAMES); } @Override public void onVideoPicture(IVideoPictureEvent event) { if (event.getStreamIndex() != mVideoStreamIndex) { // if the selected video stream id is not yet set, go ahead an // select this lucky video stream if (mVideoStreamIndex != -1) return; mVideoStreamIndex = event.getStreamIndex(); } long evtTS = event.getTimeStamp(); // if uninitialized, back date mLastPtsWrite to get the very first frame if (mLastPtsWrite == Global.NO_PTS) mLastPtsWrite = Math.max(0, evtTS - MICRO_SECONDS_BETWEEN_FRAMES); // if it's time to write the next frame if (evtTS - mLastPtsWrite >= MICRO_SECONDS_BETWEEN_FRAMES) { if (!hasFired) { image = event.getImage(); hasFired = true; } // update last write time mLastPtsWrite += MICRO_SECONDS_BETWEEN_FRAMES; } } } }