How to play videos from Rich Media Annotations?

If you have a PDF file with Rich Media Annotation, you can visualize them by creating a custom annotation type and scanning the file for rich media annotations that have a video source.

Here is a code snippet for WebViewer 8+ and MP4 rich media annotations:

WebViewer({
  initialDoc: "file-with-rich-media.pdf",
  path: '/lib',
  fullAPI: true
}, document.getElementById('viewer')).then(instance => {
  const { PDFNet, documentViewer, annotationManager, Annotations } = instance.Core;

  const VideoAnnotation = function(videoBlob, rect) {
    Annotations.HTMLAnnotation.call(this, { rect });
    this.Subject = 'Video';
    this.videoBlob = videoBlob;
  };
  VideoAnnotation.prototype = new Annotations.HTMLAnnotation();
  VideoAnnotation.prototype.elementName = 'video';

  VideoAnnotation.prototype.createInnerElement = function() {
    const videoElement = document.createElement('video');
    videoElement.src = window.URL.createObjectURL(this.videoBlob);
    videoElement.controls = true;
    videoElement.playsinline = true;
    return videoElement;
  };

  VideoAnnotation.prototype.serialize = function() {};

  documentViewer.addEventListener('annotationsLoaded', async () => {
    await PDFNet.initialize();
    const pdfDocument = await documentViewer.getDocument().getPDFDoc();

    for (let i = 1; i <= documentViewer.getDocument().getPageCount(); i++) {
      const page = await pdfDocument.getPage(i);

      const numberOfAnnotations = await page.getNumAnnots();

      for (let j = 0; j < numberOfAnnotations; j++) {
        const annotation = await page.getAnnot(j);
        if (!(await annotation.isValid())) {
          continue;
        }
        const type = await annotation.getType();

        if (PDFNet.Annot.Type.e_RichMedia === type) {
          const annotationObject = await annotation.getSDFObj();
          const richMediaContentObject = await annotationObject.findObj("RichMediaContent");

          if (richMediaContentObject) {
            const assets = await (PDFNet.NameTree.createFromObj(await richMediaContentObject.findObj("Assets")));
            if (await assets.isValid()) {
              let iterator = await assets.getIteratorBegin();
              for (; await iterator.hasNext(); await iterator.next()) {
                const file_spec = await PDFNet.FileSpec.createFromObj(await iterator.value());

                const stream = await file_spec.getFileData();
                if (stream) {
                  const filterReader = await PDFNet.FilterReader.create(stream)
                  const arrayBuffer = await filterReader.readAllIntoBuffer();
                  const blob = new Blob([arrayBuffer], {type: 'video/mp4'});

                  const pageNumber = await (await annotation.getPage()).getIndex();
                  const pdfCoords = await annotation.getRect();
                  const document = documentViewer.getDocument();

                  const viewerBottomLeftCornerCoords = document.getViewerCoordinates(pageNumber, pdfCoords.x1, pdfCoords.y1);
                  const viewerTopRightCornerCoords = document.getViewerCoordinates(pageNumber, pdfCoords.x2, pdfCoords.y2);

                  const rect = new Annotations.Rect(viewerBottomLeftCornerCoords.x, viewerTopRightCornerCoords.y, viewerTopRightCornerCoords.x, viewerBottomLeftCornerCoords.y);
                  const videoAnnotation = new VideoAnnotation(blob, rect);

                  videoAnnotation.PageNumber = pageNumber;
                  annotationManager.addAnnotation(videoAnnotation);
                  annotationManager.drawAnnotations({ pageNumber: videoAnnotation.PageNumber, majorRedraw: true })
                }
              }
            }
          }
        }
      }
    }
  });
});
2 Likes