MP3:对于任何给定的字节位置,以毫秒为单位的位置获取方法? [英] MP3: a way to get position in milliseconds for any given byte position?

查看:114
本文介绍了MP3:对于任何给定的字节位置,以毫秒为单位的位置获取方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了一个servlet,该servlet返回一个流(来自MP3文件),该流从客户端请求的任何给定字节位置开始.这样一来,客户端就可以在任意给定的字节位置立即开始播放,而无需进行任何本地搜索.

I've created a servlet which returns a stream (from an MP3 file) beginning at any given byte position requested by a client. This allows the client to start playback instantly at any given byte position without doing any local seek.

现在,我有一个滑块,可以直观地看到进度.我正在使用当前字节位置来更新滑块.但是,我也想以秒为单位显示当前位置.

Now, I've got a slider which visualises the progress. I'm using the the current byte position to update the slider. However, I'd also like to show the current position in seconds.

这要求服务器可以将以字节为单位的当前位置转换"为以毫秒为单位的位置.然后,服务器可以只提供以毫秒为单位的流开始位置作为响应头.

This requires that the server can "convert" the current position in bytes to the position in milliseconds. The server could then just provided the stream start position in milliseconds as a response header.

有人对如何计算以字节为单位的当前位置有经验吗?

Does anyone have experience as to how one can calculate the current position in bytes to milliseconds?

更新

从注释中可以明显看出,没有一种精确的方法可以将转换字节转换为毫秒,反之亦然,而无需解码MP3文件直到该点(以毫秒或字节为单位),然后确定已经存储了多少个字节.阅读或已播放的毫秒数.但是,考虑到一台服务器(例如100个用户将同时请求文件)的服务器,这种方法显然效果不佳.然后,服务器将不得不解码MP3文件直到请求的位置,然后从该点返回流.我选择了以性能来交换精度,并采取了一种方法,该方法可以为我提供大概的位置,并且对播放器来说已经足够了,其目的只是播放音轨(而不与其他来源的音频同步至毫秒).

It is clear, from the comments, that there is no precise way to get convert bytes to milliseconds and vice versa without decoding the MP3 file up to the point (in milliseconds or bytes) and then determine how many bytes that have been read or milliseconds that have been played. However, this approach would obviously not perform too well considering a server where, say, 100 users would request files at the same time. The server would then have to decode the MP3 files up to the requested position, and then return streams from that point. I chose to exchange precision with performance, and took an approach which gives me approximate positions and which is more than good enough for a player which purpose is just to play a track (and not synch the audio against other sources down to the millisecond).

我所做的是,播放器(在客户端)现在仅关心毫秒(MS).也就是说,进度条的当前值和最大值以MS为单位,而不是字节数(如其最初那样).为了从任何给定位置开始播放,客户端请求服务器(servlet)提供从MS中任何给定位置开始的音频流. servlet使用JAudioTagger获取有关文件的详细信息,然后对MS位置对应的字节位置进行近似计算.我已经对其进行了测试,它可以与CBR(恒定比特率)文件一起很好地工作.该方法不适用于VBR(可变比特率)文件,因为帧大小可能会有所不同.请注意,这只是一个播放器,用于播放音乐文件.并非旨在将音频与其他媒体同步到MS.下面提供了从MS转换为字节的代码片段.

What I've done is that the player (on the client side) only cares about milliseconds (MS) now. That is, the current value and maximum value of the progress bar is in MS, and not bytes as it first did. To begin playback from any given position, the client requests the server (servlet) to provide the audio stream beginning at any given position in MS. The servlet use JAudioTagger to get details about the file, and then makes an approximate calculation as to what byte position the MS position corresponds to. I've tested it and it works well with CBR (constant bitrate) files. The approach will not work with VBR (variable bitrate) files as frame size can vary. Please note that this is just a player which purpose is to play music files. It's not intended to synchronize the audio against some other media down to the MS. The code snipped which converts from MS to bytes is provided below.

更新(2012年7月3日)

该servlet已经使用下面的代码运行了一段时间,并且运行良好.已经播放了成千上万个MP3,并且从ms到字节的近似值可以正常工作.

The servlet has been running with the below code for quite a while now, and things work very well. Thousands of MP3's have been played, and the approximation from ms to bytes works fine.

更新(2017年1月3日)

该servlet仍以完全相同的代码运行,并且成千上万的MP3播放良好.在制作期间,没有任何关于播放和定时的抱怨.

The servlet is still running with this exact same code, and hundreds of thousands of MP3s have been played nicely. During it's time in production, no single complaint has been made with regards to playback and timing.

/**
 * Returns the approximate byte position for any given position in
 * milliseconds.
 *
 * http://www.java2s.com/Open-Source/Android/Mp3/needletagger/org/jaudiotagger/audio/mp3/MP3AudioHeader.java.htm
 * http://www.autohotkey.com/forum/topic29420.html
 *
 * @param   file the <code>File</code> for which the byte position for the
 *          provided position in milliseconds is to be returned.
 * @param   ms a <code>long</code> being the position in milliseconds for
 *          which the corresponding byte position is to be returned.
 * @return  a <code>long</code> being the byte position, or <b>-1</b> if the
 *          position in bytes could not be obtained.
 */
public static long getApproximateBytePositionForMilliseconds(File file, long ms) {

    long bytePosition = -1;

    try {

        AudioFile audioFile = AudioFileIO.read(file);
        AudioHeader audioHeader = audioFile.getAudioHeader();

        if (audioHeader instanceof MP3AudioHeader) {
            MP3AudioHeader mp3AudioHeader = (MP3AudioHeader) audioHeader;
            long audioStartByte = mp3AudioHeader.getMp3StartByte();
            long audioSize = file.length() - audioStartByte;
            long frameCount = mp3AudioHeader.getNumberOfFrames();
            long frameSize = audioSize / frameCount;

            double frameDurationInMs = (mp3AudioHeader.getPreciseTrackLength() / (double) frameCount) * 1000;
            double framesForMs = ms / frameDurationInMs;
            long bytePositionForMs = (long) (audioStartByte + (framesForMs * frameSize));
            bytePosition = bytePositionForMs;
        }

        return bytePosition;

    } catch (Exception e) {
        return bytePosition;
    }

}

推荐答案

它不能那样工作.即使您的MP3文件是恒定比特率编码的,哪个字节位置编码流中的哪一秒也是可变的. (可以肯定的是,VBR编码使它比CBR多了许多 ,但都是一样的.)可靠地获取此信息的唯一方法是对流进行实际解码,直到您将其解码为止.可能不想做.这就是为什么当您跳来跳去时,甚至XMMS之类的专业播放器也无法可靠地更新滑块的原因.

It doesn't work like that. Even if your MP3 file is constant-bit-rate encoded, which byte position encodes which second in the stream is variable. (To be sure, VBR encoding makes it a lot more variable than CBR, but all the same.) The only way to reliably get this information is to actually decode the stream up to that point, which you probably don't want to do. This is why even professional players such as XMMS cannot reliably update the slider when you skip around.

这篇关于MP3:对于任何给定的字节位置,以毫秒为单位的位置获取方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆