【问题标题】:How to implement seek on mp3如何在 mp3 上实现 seek
【发布时间】:2012-04-16 08:59:13
【问题描述】:

我即将进入一个涉及解码 + 播放 mp3 流的项目。

我有一个 Java 解码器 (JLayer),但据我所知,它没有搜索功能(我不使用内置播放器,我需要实现自己的播放器)。

另外,流是加密的,所以我需要实时解密 + 解码 - 不能有完整的解密文件。

那么您如何在 mp3 流上进行搜索?我想设置一个时间值,并在文件中获取适当的偏移量以进行解码。

还请考虑支持 VBR。

谢谢

【问题讨论】:

  • 使用已解码、加载的 MP3 可以轻松搜索。对于尚未形成AudioInputStream 的音乐来说,这并不容易,而对于 VBR MP3 来说尤其困难。
  • 这必须是纯Java吗? CASampledSP 支持自定义 seek() 方法,MFSampledSP 也是如此。 CASampledSP 适用于 OS X (CA=CoreAudio),MFSampledSP 适用于 Windows 7 及更高版本 (MF=MediaFoundation)

标签: java mp3 javasound


【解决方案1】:

我一直在寻找完全相同的东西。 JLayer 代码有些混乱。只是浏览它就让我确信 mp3 解码核心是编写的(或从某个地方获取的)然后移植到 Java,然后添加了一个额外的 - 相当不理想的 - 层。在任何情况下。想看看播放器中的代码(http://code.google.com/p/jesuifoo/source/browse/trunk/src/javazoom/jlgui/basicplayer/BasicPlayer.java?r=23)

    /**
     * Skip bytes in the File inputstream. It will skip N frames matching to
     * bytes, so it will never skip given bytes length exactly.
     * 
     * @param bytes
     * @return value>0 for File and value=0 for URL and InputStream
     * @throws BasicPlayerException
     */
    protected long skipBytes(long bytes) throws BasicPlayerException {
            long totalSkipped = 0;
            if (m_dataSource instanceof File) {
                    log.info("Bytes to skip : " + bytes);
                    int previousStatus = m_status;
                    m_status = SEEKING;
                    long skipped = 0;
                    try {
                            synchronized (m_audioInputStream) {
                                    notifyEvent(BasicPlayerEvent.SEEKING,
                                                    getEncodedStreamPosition(), -1, null);
                                    initAudioInputStream();
                                    if (m_audioInputStream != null) {
                                            // Loop until bytes are really skipped.
                                            while (totalSkipped < (bytes - SKIP_INACCURACY_SIZE)) {
                                                    skipped = m_audioInputStream.skip(bytes
                                                                    - totalSkipped);
                                                    if (skipped == 0)
                                                            break;
                                                    totalSkipped = totalSkipped + skipped;
                                                    log.info("Skipped : " + totalSkipped + "/" + bytes);
                                                    if (totalSkipped == -1)
                                                            throw new BasicPlayerException(
                                                                            BasicPlayerException.SKIPNOTSUPPORTED);
                                            }
                                    }
                            }
                            notifyEvent(BasicPlayerEvent.SEEKED,
                                            getEncodedStreamPosition(), -1, null);
                            m_status = OPENED;
                            if (previousStatus == PLAYING)
                                    startPlayback();
                            else if (previousStatus == PAUSED) {
                                    startPlayback();
                                    pausePlayback();
                            }
                    } catch (IOException e) {
                            throw new BasicPlayerException(e);
                    }
            }
            return totalSkipped;
    }

此例程说明如何在不解码的情况下推进比特流。(m_audioInputStream.skip(...))。我不知道它是从一开始跳过(毕竟之前有一个 initAudioStream 调用),还是从当前播放位置跳过。

VBR 没有问题,因为帧是单独跳过的。

关于解密,这无关紧要,因为此例程会跳过从输入流中读取的各个帧。如果输入流支持解码,它应该可以工作。多快当然是另一个问题。在这种情况下,最好为 mp3 建立一个索引,以便您知道要跳转和解码的位置,但这是一个稍微不同的主题:如何在加密流中查找。

【讨论】:

  • 4 年后,我实际上想通过指向我的 JLayer 端口的链接来扩展这个答案。它大约快 4 倍,并提供了有关如何在字节精确位置查找/解码流的可演示代码:bpmdj.yellowcouch.org/credits.html 请参阅 JLayer 1.0.1 部分。它有一个指向图书馆和示例公共存储库的链接。
猜你喜欢
  • 1970-01-01
  • 2021-05-17
  • 1970-01-01
  • 2016-08-07
  • 1970-01-01
  • 1970-01-01
  • 2019-11-22
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多