音频剪辑没有首次使用HTML5 <audio>标签

时间:2015-08-04 20:34:57

标签: javascript html5-audio progress

这是一个非常令人费解的问题,我已经多次在这里遇到障碍而没有找到解决方案。 That question was getting too complicated正确地获取所有更新和格式,所以让我们从这里开始。

基本问题是从包含某种音频播放器的网页启动音频剪辑。当页面出现时,浏览器不知道剪辑的持续时间,并且第一次通过,无论播放器未能显示播放器在文件中前进的任何UI,即使它以可听方式播放剪辑。一旦玩家完成了剪辑,它也学会了持续时间,并且在随后的重播中,UI确实显示了进度。

这是目前的状态:

1)原始问题假设jQuery jPlayer与问题有关,但后续测试显示它没有。 删除jPlayer,而是使用HTML5音频标记显示完全相同的问题。

2)最初我认为问题可能在于将.vox文件的SoX转换为.wav,但是a go-round on the SoX mailing list使我确信情况并非如此。

3)有人建议(主要是Gyrocode.com)问题可能在于使用.wav文件,但我可以用.ogg和其他格式重现完全相同的问题。

我可以在the samples that have been shown by Gyrocode和我正在做的事情之间看到的唯一区别是我的代码最初放入虚拟源,然后在向用户显示音频播放器之前动态更改它(在模态内部)对话)。

以骨架形式下面是代码。

HTML:

<div class="form-group">
    <label class="col-sm-4 control-label">Play Audio</label> 
    <div class="col-sm-8">
        <div style="box-sizing:content-box;" class="container" id="player-container">
            <audio controls src="NONE" id="audio-player" preload="metadata"></audio>
        </div>
    </div>
</div>  

JS:

/**
* JavaScript functions for populating data on the transcripts page.
*/

var oParams = new Object();
// temporarily hardcoded
oParams.userId="sc1478";
oParams.audioId="";
var oAudioList;

// loads the data table
function showModalTranscribeDialog(id) {
    console.log( 'You clicked on the row for audio id '+id );
    oParams.audioId=id;
    $('#playTranscribeModal').modal('show');
}

function fnLoadAudio() {
    console.log('in fnLoadAudio');
    var url="x/audio/" + oParams.userId + "/";
    console.log("searching " + url);
    oAudioList = $('#audiolist').DataTable({
        "pageLength" : 10,
        "processing" : true,
        "serverSide" : false,
        "cache" : false,
        "ajax" : {
            "url" : url,
            "dataSrc" : "payload.listOfAudio"
        },
        "columns" : [{
                "data" : "audioId",
                "title" : "Audio ID",
                "width" : "6%"
            }, ...  
        ],
        "columnDefs" : [ 
            ...
        ],
    });
    // clicking on row of table brings up modal dialog for playing and
    // transcribing
    $('#audiolist tbody').on('click', 'tr', function () {
    var id = $('td', this).eq(0).text();
    showModalTranscribeDialog(id);
    } );
    console.log('done with fnLoadAudio');
}

...

// load clip into audio player
function fnLoadPlayer() {
    var alerted = false; 
    var media_url_wav='audio/clip/wav/'+oParams.audioId+'/';

    console.log("player will play " + media_url_wav);
    $("#audio-player").attr("src", media_url_wav);
}

$(document).ready(function() {

    console.log('in document ready !!');    
    $('#dynamic').html( '<table cellpadding="0" cellspacing="0" border="0" class="display" id="audiolist"></table>' );
    fnLoadAudio();

    // set the ID of the selected audio in the dialog when the playTranscribe 
    //modal dialog is shown
    $('#playTranscribeModal').on('show.bs.modal', function (e) {
        ...    

        fnLoadPlayer();

    });

    ...   
}); 

以下是代码显示的内容:

页面上有一个JQuery Datatable,它还包含一个模式对话框,当单击该行的某一行以进一步收集用户的数据时,该对话框会弹出。该对话框包含音频播放器。显示对话框并且用户单击播放按钮时播放音频。

文档准备好后,将加载数据表。 ready事件处理程序调用fnLoadAudio(),它填充数据表并为单击一行表时设置单击处理程序。在那种情况下,调用函数showModalTranscribeDialog()。这首先使用行数据来获取要播放的音频的id,并显示对话框。在显示对话框时,另一个事件处理程序使用id来获取音频的正确URL,然后将其设置为对话框中元素的src属性。

这说明的是,在对话框出现之前,音频元素的src属性不会被填充,尽管音频元素一直在对话框中(但是隐藏),还有一些其他的src值

我的理论是,正是这种设置导致问题的src的方式,当音频的src以常规方式在页面上进行硬编码时不会发生。

我的问题是,如果有所描述的页面结构,是否有更好的方法来动态设置音频播放器的源。

2 个答案:

答案 0 :(得分:4)

答案很简单,持续时间不是(通常)元数据的一部分!并且当在播放之前知道持续时间时,它是因为源是作为文件而不是作为流传递的。我的应用使用提供流的API调用。

咄!

某些格式(例如.mp3)可能在元数据中包含持续时间标记,但这不是强制性的perhaps not even a good thing.

我在我的网络应用程序中制作了一个带有两个标签的测试页。

<!DOCTYPE html>
<html>
<head>
<meta charset="ISO-8859-1">
<title>Audio Test Page</title>
</head>
<body>
<h1>Audio Test Page</h1>
<br/>
<audio controls src="audio/clip/wav/103659/" id="audio-test-player" preload="auto"></audio>
<br/>
<audio controls src="audiotest/test.wav" id="audio-test-player2" preload="auto"></audio>
<br/>
</body>
</html>

第一个执行常规应用程序的功能。它进行API调用,将文件作为流返回。它实际上是相同的API。它将文件读作InputStream,然后将其复制到响应的OutputStream中。

第二个加载与我暂时放在webapp中的静态资源相同的文件。

第一个也无法加载持续时间(即使预加载=&#34; auto&#34;)。

第二个加载持续时间(即使预加载=&#34;元数据&#34;)。

似乎当源作为文件传递时,浏览器有机会查看文件的大小并应用一些逻辑来预先确定持续时间。这与soxi实用程序用来猜测持续时间as detailed here

的逻辑相同
$ soxi /var/tmp/test.wav

Input File     : '/var/tmp/test.wav'
Channels       : 1
Sample Rate    : 8000
Precision      : 16-bit
Duration       : 00:00:10.48 = 83840 samples ~ 786 CDDA sectors
Sample Encoding: 16-bit Signed Integer PCM

但是,当源作为流传递时,文件大小未知,并且无法进行此计算。

一种可能的解决方案可能是将计算出的持续时间包含在标准或自定义元数据标签中的元数据中,并将某些玩家的皮肤用于皮肤,但基本问题是期望值。

持续时间通常不是元数据的一部分,浏览器无法通过流式传输来计算。

因此,我们来到了不完全令人满意的,但最终理解了这个烦人的问题的答案已经跨越了

我的用例有点不标准,可能不是声音API的大多数用户试图实现的。

答案 1 :(得分:1)

我并没有完全了解您的无关视图代码中发生的所有情况,但我没有看到您在媒体上收听“播放”事件的任何地方。在我的代码中,我必须在持续时间有效之前等待第一个'播放'事件。

//assuming _audio is a reference to an Audio element
_audio.addEventListener('playing', function() {
  console.log(_audio.getDuration());
}, false);