【问题标题】:How to get the duration of mp3 file without playing or storing them如何在不播放或存储的情况下获取 mp3 文件的持续时间
【发布时间】:2014-02-07 02:29:22
【问题描述】:

我正在构建一个 wp8 应用程序,它可以在列表框中逐行播放诗歌。

假设我有 20 行诗,在列表框中显示为 20 项。我有 20 个 mp3 文件(每行一个),我使用 BackgroundAudioPlayer 播放单个文件并选择列表框中的每个项目(诗歌)。在播放这些mp3文件的过程中,有1-3秒的延迟,于是我找到了这些mp3文件的完整版(20个文件合并为一个),逐行朗读。

我正在使用 BackgroundAudioPlayer 播放这个 mp3 文件。作为一个文件播放,我无法选择列表框中的每个项目,因为我不知道播放一个 mp3 文件的行号。

现在我想要的是在几秒钟内存储 20 个文件的持续时间,而不是存储和播放。这些文件位于链接中 (http:123.com/1.mp3, /2.mp3, ...)

我使用了带有绝对路径的 AudioTrack,然后使用了持续时间属性,但它总是返回零。如何在不播放的情况下获取 mp3 文件的时长?

已编辑: 在后台代理中我做了以下:

protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState)
{
switch (playState)
{
case PlayState.TrackReady:
TrackDuration tr = DataSource.Connection.Table<TrackDuration>().SingleOrDefault();
if (tr.IsGetTrackDuration)
{
if (player.Track != null)
{
player.Position = TimeSpan.FromSeconds(player.Track.Duration.TotalSeconds);
Recitation r = DataSource.Connection.Query<Recitation>("select * from Recitation where ID = " + player.Track.Title).SingleOrDefault();
r.AyaDuration = player.Track.Duration.TotalSeconds;
DataSource.saveRecitionDownloaded(r);
PlayNextTrack(player);
}
}
break;
}
NotifyComplete();
}

protected override void OnUserAction(BackgroundAudioPlayer player, AudioTrack track, UserAction action, object param)
{
switch (action)
{
case UserAction.Play:
   PlayTrack(player);
break;
case UserAction.Seek:
if (null!=player.Track)
player.Position = (TimeSpan)param;
break;
}
NotifyComplete();
}

private void PlayNextTrack(BackgroundAudioPlayer player)
{
 if (++currentTrackNumber >= audioTrack.Count)
   return;
 PlayTrack(player);
}

private void PlayTrack(BackgroundAudioPlayer player)
{
//If No Track then load Track
 if (audioTrack.Count == 0)
 {
     //Load Tracks and Add them into Track Play List
 }
if ((player.Track == null) || (player.Track.Title != audioTrack[currentTrackNumber].Title))
    player.Track = audioTrack[currentTrackNumber];

if ((player.Track != null) && (player.PlayerState != PlayState.Playing))
    player.Play();
}

问题是它播放了一些我不想要的文件。 (tr.IsGetTrackDuration) 总是正确的,但我不知道为什么它会播放一些?

【问题讨论】:

  • 您是否有理由不想存储(下载)每个单独的文件?如果存储空间有问题,您可以在播放完成后删除每个曲目。
  • 不知道你是否理解我的情况,比起下载20个mp3文件,我更喜欢只下载1个文件。我会从 20 个文件中获取持续时间,并在到达特定位置时突出显示每一行。我会定时来管理这个。
  • 不,我完全理解。我要问的是为什么你反对单独下载每个文件?这是您能够读取音轨长度的唯一方法。
  • 你的意思是,我下载20个文件,存储,获取时长,然后删除?,不播放可以获取时长吗?最后下载单个 mp3 文件。
  • 这是一个棘手的情况,不是吗?我会亲自下载单个文件,因为我猜它们不是很大。然后,我将序列化轨道 Uri 的 List。完成一首曲目后,您将从列表中获取下一个 Uri 并播放它。

标签: c# windows-phone-8


【解决方案1】:

MusicProperties 类有一个持续时间的属性

 MusicProperties musicProperties = await file.Properties.GetMusicPropertiesAsync();
 outputText.AppendLine("Duration: " + musicProperties.Duration);

【讨论】:

  • 这不起作用,因为文件位于远程服务器上。
  • 不幸的是(目前)它不能像msdn.microsoft.com/en-us/library/windowsphone/develop/… 所说的那样工作 - Windows Phone 8 这个 API 没有实现,如果调用它会抛出异常。
  • 因为它需要存储 mp3,而 OP 不想这样做。
【解决方案2】:

好的,我有一个想法。在 AudioPlayer 类下,有一个 TrackReady 事件,默认设置为播放曲目。如果您只是想获得持续时间,请将 bool 设置为 true,而不是默认播放,如果您确实希望播放曲目(当您想要播放完整的 mp3 时),则设置为 false。

bool 值必须在设置轨道之前在主应用程序中设置,然后在每次调用 OnPlayStateChanged 时读取 AudioPlayer。

protected override void OnPlayStateChanged(BackgroundAudioPlayer player, AudioTrack track, PlayState playState)
{
    //read GettingDuration value here

    try
    {
        switch (playState)
        {
            case PlayState.TrackReady:
                if (GettingDuration)
                {
                //store duration somehow and get the next track in line
                }
                else
                {
                    player.Play();
                }

                break;
        }
    }
}

【讨论】:

  • 我编辑了我的问题,我不想播放 mp3 文件,它会存储持续时间,但它会播放我的一些音轨。
猜你喜欢
  • 1970-01-01
  • 2022-01-04
  • 2011-01-06
  • 1970-01-01
  • 2011-12-18
  • 1970-01-01
  • 2012-06-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多