【问题标题】:Ogg opus granule position to timestampOgg opus 颗粒位置到时间戳
【发布时间】:2022-01-02 16:00:23
【问题描述】:

最终目标是裁剪/剪切/修剪包含单个作品流的 Ogg 文件, 我正在尝试从文件中检索和过滤 ogg 页面以及位于 startTimeMs 和 endTimeMs 裁剪窗口之间的页面,我会将它们附加到 2 个 ogg 头上,从而无需转码即可修剪作品

我已经到了可以访问 ogg 页面的阶段,但我对如何确定页面是否位于裁剪窗口中感到困惑

OggOpusStream oggOpusStream = OggOpusStream.from("audio/technology.opus");

// Get ID Header
IdHeader idHeader = oggOpusStream.getIdHeader();

// Get Comment Header
CommentHeader commentHeader = oggOpusStream.getCommentHeader();

while (true) {
    AudioDataPacket audioDataPacket = oggOpusStream.readAudioPacket();
    if (audioDataPacket == null) break;
    
    for (OpusPacket opusPacket : audioDataPacket.getOpusPackets()) {
    if(packetLiesWithinTrimRange(opusPacket )){ writeToOutput(opusPacket); }
    }
}
// Create an output stream
OutputStream outputStream = ...;

// Create a new Ogg page
OggPage oggPage = OggPage.empty();

// Set header fields by calling setX() method
oggPage.setSerialNum(100);


// Add a data packet to this page
oggPage.addDataPacket(audioDataPacket.dump());

// Call dump() method to dump the OggPage object to byte array binary 
byte[] binary = oggPage.dump();

// Write the binary to stream
outputStream.write(binary);

如果我能够完成此方法,它应该可以工作

private boolean packetLiesWithinTrimRange(OpusPacket packet){
   if(????????){ return true;}
  return false;
}

或许

private boolean pageLiesWithinTrimRange(OggPage page){
   if(????????){ return true;}
  return false;
}

感谢任何 ogg/opus 帮助

https://github.com/leonfancy/oggus/issues/2

带有private long granulePosition;的OggPage.java

https://github.com/leonfancy/oggus/blob/master/src/main/java/org/chenliang/oggus/ogg/OggPage.java

Opus 音频编解码器的 Ogg 封装 https://datatracker.ietf.org/doc/html/rfc7845

【问题讨论】:

    标签: audio audio-processing ogg opus oggvorbis


    【解决方案1】:

    可以使用流的pre-skip 和第一个/初始granule position 计算音频页面的结束时间。可以使用上一页的结束时间获取页面的开始时间。见下面的伪代码:

    sampleRate = 48_000
    streamPreskip = ...
    streamGranulePosFirst = ...
    
    isPageWithinTimeRange(page, prevPage, msStart, msEnd) {
      pageMsStart = getPageMsEnd(prevPage)
      pageMsEnd =   getPageMsEnd(page)
    
      return (pageMsStart >= msStart && pageMsEnd <= msEnd)
    }
    
    getPageMsEnd(page) {
      return (page.granulePos - streamGranulePosFirst - streamPreskip) / sampleRate
    }
    

    【讨论】:

      猜你喜欢
      • 2019-03-23
      • 1970-01-01
      • 2023-03-26
      • 2018-07-27
      • 1970-01-01
      • 2020-02-05
      • 2015-11-16
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多