PDFBox 创建带有外部 mp3 或 wav 文件的链接/引用的 Sound 对象

Posted

技术标签:

【中文标题】PDFBox 创建带有外部 mp3 或 wav 文件的链接/引用的 Sound 对象【英文标题】:PDFBox creating Sound object with link/reference to external mp3 or wav file 【发布时间】:2016-04-20 16:32:03 【问题描述】:

我正在编写一个实用程序应用程序,使用基于 Java 的开源 PDFBox 来转换包含“打开 mp3 文件的超链接”的 PDF 文件,以将其替换为声音对象。

我使用了 PDFBox API,因为它看起来已经足够成熟,可以使用 Sound 对象了。我可以阅读 PDF 文件并找到参考 mp3 的超链接。但我无法用声音对象替换它。我创建了声音对象并与动作相关联,但它不起作用。我想我错过了如何使用 PDActionSound 对象创建 Sound 对象的一些重要部分。是否可以使用 PDFBox API 引用外部 wav 文件?

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);  
              
          
      
   

如何创建声音对象(PDActionSound)并成功添加到链接?

【问题讨论】:

【参考方案1】:

说到成熟,那部分从来没有用过,现在仔细看代码,我觉得还有一些工作要做......请试试这个,我是在阅读后用PDFBox 2.0创建的PDF 规范:

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

编辑:由于上述方法不起作用,这是 cmets 中要求的替代解决方案。该文件已嵌入。它仅适用于 .WAV 文件,您必须了解它们的详细信息。开始时大约损失了 1/2 秒。您应该听到的声音是“我是 Al Bundy”。我尝试使用 MP3 并没有成功。在谷歌搜索时,我发现一些文本说只支持“旧”格式(wav、aif 等)。我确实找到了另一种播放声音的方法(“Renditions”),它甚至可以与another product 中的嵌入式 mp3 一起使用,但 PDF 中生成的结构更加复杂。

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);

2016 年 7 月 9 日更新:

我们在 PDFBox 邮件列表中讨论了这个问题,感谢 Gilad Denneboom,我们知道了另外两件事: 1) 在 Adob​​e Acrobat 中,它只允许您选择 WAV 或 AIF 文件 2) Gilad Denneboom 使用MP3SPI 将 MP3 转换为 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);

【讨论】:

感谢您的回答。 actionSound 有 setItem 方法吗?您使用的是哪个版本的 PDXBox API? 我使用的是 2.0.我忘了添加 getCOSObject(),对不起,我已经编辑了我的答案。 (如果您的问题得到解决,我会注意在将来添加 setSound() 方法)。 谢谢@Tilman 不幸的是它还没有解决。我有另一个声音对象(手动添加)..当我播放该声音对象时,它会播放声音,并根据您的解决方案单击以编程方式创建的声音注释,它确实会停止播放声音。但它不播放我使用 .. PDSimpleFileSpecification fileSpec = new PDSimpleFileSpecification("D:\temp.wav"); 附加的文件我正在使用 PDXBox 2.0.0 RC3 API PDFBox 是 2.0 虽然这可能不会改变任何东西......你能分享你创建的 PDF 吗?或者任何有声音的PDF? 请找到示例 pdf。drive.google.com/open?id=0B0FwsajGrumSQXlabGlUQ2czeUk 它包含两种类型的声音参考。每个标志图标代表声音。第一种类型是嵌入的声音对象,所有其他类型都是超链接引用。我想用引用外部文件的 Sound 对象替换超链接。我无法使用外部链接创建声音。你能帮我为外部声音文件创建一个声音对象吗?提前感谢您的帮助

以上是关于PDFBox 创建带有外部 mp3 或 wav 文件的链接/引用的 Sound 对象的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 pydub 库从 mp3 文件中生成带有 G.711alaw 的 wav?

PHP - 将 .wav 文件转换为 .mp3?

NodeMCU 播放 .wav 或 .mp3 文件

在linux环境下一个文件夹里面有MP3和wav,怎么将其分开

在 Windows 中简单的 .wav 或 .mp3 播放 - 它去哪儿了?

如何在 asp.net mvc 项目中添加 .mp3 或 .wav 文件?