Created
November 2, 2013 00:18
-
-
Save andrelashley/7273946 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.awt.geom.Rectangle2D; | |
import java.awt.image.BufferedImage; | |
import java.io.*; | |
import java.net.URL; | |
import javax.imageio.ImageIO; | |
import javax.xml.namespace.QName; | |
import org.apache.poi.openxml4j.opc.*; | |
import org.apache.poi.xslf.usermodel.*; | |
import org.apache.xmlbeans.XmlCursor; | |
import org.openxmlformats.schemas.drawingml.x2006.main.CTHyperlink; | |
import org.openxmlformats.schemas.officeDocument.x2006.relationships.STRelationshipId; | |
import org.openxmlformats.schemas.presentationml.x2006.main.*; | |
import com.xuggle.mediatool.*; | |
import com.xuggle.mediatool.event.IVideoPictureEvent; | |
import com.xuggle.xuggler.Global; | |
public class AddVideoToPptx { | |
public static void main(String[] args) throws Exception { | |
URL video = new URL("http://archive.org/download/test-mpeg/test-mpeg.mpg"); | |
XMLSlideShow pptx = new XMLSlideShow(); | |
XSLFSlide slide = pptx.createSlide(); | |
// add video file | |
String videoFileName = video.getPath().substring(video.getPath().lastIndexOf('/')+1); | |
PackagePartName partName = PackagingURIHelper.createPartName("/ppt/media/"+videoFileName); | |
PackagePart part = pptx.getPackage().createPart(partName, "video/mpeg"); | |
OutputStream partOs = part.getOutputStream(); | |
InputStream fis = video.openStream(); | |
byte buf[] = new byte[1024]; | |
for (int readBytes; (readBytes = fis.read(buf)) != -1; partOs.write(buf, 0, readBytes)); | |
fis.close(); | |
partOs.close(); | |
PackageRelationship prsEmbed = slide.getPackagePart().addRelationship(partName, TargetMode.INTERNAL, "http://schemas.microsoft.com/office/2007/relationships/media"); | |
PackageRelationship prsExec = slide.getPackagePart().addRelationship(partName, TargetMode.INTERNAL, "http://schemas.openxmlformats.org/officeDocument/2006/relationships/video"); | |
// add snapshot | |
BufferedImage image = getSnapShot(video.toExternalForm()); | |
ByteArrayOutputStream bos = new ByteArrayOutputStream(); | |
ImageIO.write(image, "jpeg", bos); | |
int snapIdx = pptx.addPicture(bos.toByteArray(), XSLFPictureData.PICTURE_TYPE_JPEG); | |
// add video shape | |
XSLFPictureShape pic = slide.createPicture(snapIdx); | |
pic.setAnchor(new Rectangle2D.Double(50, 50, image.getWidth(), image.getHeight())); | |
CTPicture xpic = (CTPicture)pic.getXmlObject(); | |
CTHyperlink link = xpic.getNvPicPr().getCNvPr().addNewHlinkClick(); | |
link.setId(""); | |
link.setAction("ppaction://media"); | |
// add video relation | |
CTApplicationNonVisualDrawingProps nvPr = xpic.getNvPicPr().getNvPr(); | |
nvPr.addNewVideoFile().setLink(prsExec.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}"); | |
XmlCursor cur = ext.newCursor(); | |
cur.toEndToken(); | |
cur.beginElement(new QName("http://schemas.microsoft.com/office/powerpoint/2010/main", "media")); | |
cur.insertAttributeWithValue(new QName(STRelationshipId.type.getName().getNamespaceURI(), "embed"), prsEmbed.getId()); | |
cur.dispose(); | |
// add slide timing information, so video can be controlled | |
CTSlide xslide = slide.getXmlObject(); | |
CTTLCommonTimeNodeData ctn = xslide.addNewTiming().addNewTnLst().addNewPar().addNewCTn(); | |
ctn.setDur(STTLTimeIndefinite.INDEFINITE); | |
ctn.setRestart(STTLTimeNodeRestartType.NEVER); | |
ctn.setNodeType(STTLTimeNodeType.TM_ROOT); | |
CTTLCommonMediaNodeData cmedia = ctn.addNewChildTnLst().addNewVideo().addNewCMediaNode(); | |
cmedia.setVol(80000); | |
ctn = cmedia.addNewCTn(); | |
ctn.setFill(STTLTimeNodeFillType.HOLD); | |
ctn.setDisplay(false); | |
ctn.addNewStCondLst().addNewCond().setDelay(STTLTimeIndefinite.INDEFINITE); | |
cmedia.addNewTgtEl().addNewSpTgt().setSpid(""+pic.getShapeId()); | |
FileOutputStream fos = new FileOutputStream("pptx-with-video.pptx"); | |
pptx.write(fos); | |
fos.close(); | |
} | |
static BufferedImage getSnapShot(String videoURL) { | |
// get preview after 5 sec. | |
IMediaReader mediaReader = ToolFactory.makeReader(videoURL); | |
// stipulate that we want BufferedImages created in BGR 24bit color space | |
mediaReader.setBufferedImageTypeToGenerate(BufferedImage.TYPE_3BYTE_BGR); | |
ImageSnapListener isl = new ImageSnapListener(); | |
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(); | |
return isl.image; | |
} | |
static class ImageSnapListener extends MediaListenerAdapter { | |
static final double SECONDS_BETWEEN_FRAMES = 5; | |
static final long MICRO_SECONDS_BETWEEN_FRAMES = | |
(long)(Global.DEFAULT_PTS_PER_SECOND * 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 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(); | |
} | |
// if uninitialized, back date mLastPtsWrite to get the very first frame | |
if (mLastPtsWrite == Global.NO_PTS) | |
mLastPtsWrite = event.getTimeStamp() - MICRO_SECONDS_BETWEEN_FRAMES; | |
// if it's time to write the next frame | |
if (event.getTimeStamp() - mLastPtsWrite >= MICRO_SECONDS_BETWEEN_FRAMES) { | |
if (!hasFired) { | |
image = event.getImage(); | |
hasFired = true; | |
} | |
// update last write time | |
mLastPtsWrite += MICRO_SECONDS_BETWEEN_FRAMES; | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment