2

I am writing a utility application using open source java based PDFBox to convert PDF file containing 'Hyperlink to open an mp3 file' to replace it with sound object.

I used PDFBox API since it appears to be mature enough to work with Sound object. I could read the PDF file and find the hyperlink with reference to mp3. But I am not able to replace it with sound object. I created the Sound Object and associate with action but it does not work. I think I am missing some important part how to create Sound object using PDActionSound object. Is it possible to refer to external wav file using PDFBox API?

for (PDPage pdPage : pages) {
   List<PDAnnotation> annotations = pdPage.getAnnotations();
   for (PDAnnotation pdAnnotation : annotations) { 
      if (pdAnnotation instanceof PDAnnotationLink) {
          PDAnnotationLink link = ((PDAnnotationLink) pdAnnotation);
          PDAction action = link.getAction();
          if (action instanceof PDActionLaunch) {
              PDActionLaunch launch = ((PDActionLaunch) action);
              String fileInfo = launch.getFile().getFile();
              if (fileInfo.contains(".mp3")) {
                /* create Sound object referring to external mp3*/
                //something like
                PDActionSound actionSound = new PDActionSound(
                                        soundStream);
                //set the ActionSound to the link. 
                link.setAction(actionSound);  
              }
          }
      }
   }
}

How to create sound object (PDActionSound) and add to link successfully?

Tilman Hausherr
  • 17,731
  • 7
  • 58
  • 97
Dileep K V
  • 53
  • 7

1 Answers1

1

Speaking of mature, that part has never been used, and now that I had a closer look at the code, I think some work remains to be done... Please try this, I created this with PDFBox 2.0 after reading the PDF specification:

PDSimpleFileSpecification fileSpec = new PDSimpleFileSpecification(new COSString("/C/dir1/dir2/blah.mp3")); // see "File Specification Strings" in PDF spec
COSStream soundStream = new COSStream();
soundStream.createOutputStream().close();
soundStream.setItem(COSName.F, fileSpec);
soundStream.setInt(COSName.R, 44100); // put actual sample rate here
PDActionSound actionSound = new PDActionSound(); 
actionSound.getCOSObject().setItem(COSName.getPDFName("Sound"), soundStream)); 
link.setAction(actionSound); // reassign the new action to the link annotation

edit: as the above didn't work, here's an alternative solution as requested in the comments. The file is embedded. It works only with .WAV files, and you have to know details of them. About 1/2 seconds are lost at the beginning. The sound you should hear is "I am Al Bundy". I tried with MP3 and didn't succeed. While googling, I found some texts saying that only "old" formats (wav, aif etc) are supported. I did find another way to play sounds ("Renditions") that even worked with embedded mp3 in another product, but the generated structure in the PDF is even more complex.

COSStream soundStream = new COSStream();
OutputStream os = soundStream.createOutputStream(COSName.FLATE_DECODE);
URL url = new URL("http://cd.textfiles.com/hackchronii/WAV/ALBUNDY1.WAV");
InputStream is = url.openStream();
// FileInputStream is = new FileInputStream(".....WAV");
IOUtils.copy(is, os);
is.close();
os.close();
// See p. 506 in PDF spec, Table 294
soundStream.setInt(COSName.C, 1); // channels
soundStream.setInt(COSName.R, 22050); // sampling rate
//soundStream.setString(COSName.E, "Signed"); // The encoding format for the sample data
soundStream.setInt(COSName.B, 8); // The number of bits per sample value per channel. Default value: 8
// soundStream.setName(COSName.CO, "MP3"); // doesn't work
PDActionSound actionSound = new PDActionSound();
actionSound.getCOSObject().setItem(COSName.getPDFName("Sound"), soundStream);
link.setAction(actionSound);

Update 9.7.2016:

We discussed this on the PDFBox mailing list, and thanks to Gilad Denneboom we know two more things: 1) in Adobe Acrobat it only lets you select either WAV or AIF files 2) code by Gilad Denneboom with MP3SPI to convert MP3 to raw:

private static InputStream getAudioStream(String filename) throws Exception {
    File file = new File(filename);
    AudioInputStream in = AudioSystem.getAudioInputStream(file);
    AudioFormat baseFormat = in.getFormat();
    AudioFormat decodedFormat = new AudioFormat(
        AudioFormat.Encoding.PCM_UNSIGNED,
        baseFormat.getSampleRate(),
        baseFormat.getSampleSizeInBits(),
        baseFormat.getChannels(),
        baseFormat.getChannels(),
        baseFormat.getSampleRate(),
        false);
    return AudioSystem.getAudioInputStream(decodedFormat, in);
}
Community
  • 1
  • 1
Tilman Hausherr
  • 17,731
  • 7
  • 58
  • 97
  • Thank you for your answer. Does actionSound has setItem method? which version of PDXBox API you are using? – Dileep K V Apr 21 '16 at 02:53
  • I'm using 2.0. I forgot to add getCOSObject(), sorry, I've edited my answer. (If your problem gets solved, I'll take care that a setSound() method gets added in the future). – Tilman Hausherr Apr 21 '16 at 05:02
  • Thank you @Tilman Unfortunately it is not solved yet. I have another sound object (manually added).. when I play that sound object it plays a sound and on clicking on the programmatically created Sound Annotation as per your solution it does stop the sound being played. But it does not play the file I attached using .. `PDSimpleFileSpecification fileSpec = new PDSimpleFileSpecification("D:\temp.wav");` I am using PDXBox 2.0.0 RC3 API – Dileep K V Apr 21 '16 at 15:48
  • PDFBox is at 2.0 although that will probably not change anything... can you share the PDF you created? Or any PDF with sound? – Tilman Hausherr Apr 21 '16 at 17:13
  • please find the sample pdf.. https://drive.google.com/open?id=0B0FwsajGrumSQXlabGlUQ2czeUk it contains two type of sound reference. each flag icon represents sound. 1st type is Sound object embedded and all other types are hyperlink reference. I want to replace hyperlink with Sound object referring to external file. I could not create the Sound with External link. Can you help me to create a sound object to external sound file? Thank you for your help in advance – Dileep K V Apr 23 '16 at 15:18
  • Thanks... I have revised my answer but it still doesn't work. I'll think again about this tomorrow or later. I'll leave my answer there for now, but would delete it as soon as somebody else gets it working. – Tilman Hausherr Apr 23 '16 at 16:16
  • Any luck with the solution. It doesnt seem to work for me. I tried many options. But expected result is not achieved. Can we have some alternative solution to this problem? Or can you suggest other API library to make it work? Thanks for you help – Dileep K V Jun 06 '16 at 14:47
  • @DileepKV Sorry, no. Although I tried for hours, even tried to find a sample file where it worked - no success. What you (or anybody) could do is to use Acrobat Professional to create such a file - I could then see how it is done. (sometimes the PDF spec has errors). – Tilman Hausherr Jun 06 '16 at 15:19
  • Thanks for trying. I am kind of losing hope now. did several things. May be as you said specs may have issue. I have working file I shared with you before. May be embedded mp3 version is possible? what do you think? I could think of changing the approach to use embedded mp3 sound object instead of external reference. – Dileep K V Jun 07 '16 at 15:51
  • @DileepKV I can't find your file, maybe I overwrote it or deleted it. I remember that one of the clicks worked. I don't remember if it was embedded or if it launched an external player. – Tilman Hausherr Jun 07 '16 at 16:02
  • It is shared at https://drive.google.com/open?id=0B0FwsajGrumSQXlabGlUQ2czeUk Please check if you can access it. One of the link contains sound object embedded. – Dileep K V Jun 08 '16 at 06:05
  • Ok, I'm gonna try again within the next few days. I see there's an embedded sound at Root/Pages/Kids/[0]/Annots/[12]/A/Sound . – Tilman Hausherr Jun 08 '16 at 06:11
  • the alternative solution seems working for me. I am going to try it on actual tool. But I feel positive now. Thank you!!! – Dileep K V Jun 13 '16 at 04:48
  • Solution works for specific wav file. And does not work for others. What should be made sure when WAV is created? Bitrate or something is incorrect. How can I get/convert compatible WAV file? – Dileep K V Jun 17 '16 at 14:46
  • @DileepKV you'll need some media conversion software... e.g. Nero Wave Editor. – Tilman Hausherr Jun 18 '16 at 20:14