Vòng lặp âm thanh HTML5


80

Gần đây, tôi đã chơi với âm thanh HTML5 và mặc dù tôi có thể giúp nó phát âm thanh mà nó chỉ phát một lần. Bất kể tôi thử làm gì (đặt thuộc tính, trình xử lý sự kiện, v.v.), tôi dường như không thể làm cho nó lặp lại.

Đây là mã cơ bản tôi đang sử dụng:

//myAudio is declared at a global scope, so it doesn't get garbage collected.
myAudio = new Audio('someSound.ogg');
myAudio.loop = true;
myAudio.play();

Tôi đang thử nghiệm bằng Chrome (6.0.466.0 dev) và Firefox (4 beta 1), cả hai đều có vẻ vui khi bỏ qua yêu cầu lặp lại của tôi. Có ý kiến ​​gì không?

CẬP NHẬT : Thuộc tính vòng lặp hiện được hỗ trợ trong tất cả các trình duyệt chính.


1
Không chắc chắn về Chrome, nhưng Firefox không hỗ trợ lặp lại.
luiscubal

1
Chỉ bắt đầu khi nó kết thúc: myAudio.addEventListener ("đã kết thúc", function (e) {myAudio.play ();}, false);
mattbasta,

@Brandon Tôi tự hỏi tại sao điều này không hoạt động? Sự khác biệt duy nhất giữa mã này và câu trả lời được chấp nhận là trong câu trả lời được chấp nhận, nó đặt currentTimethành 0 trước khi gọi play. Điều đó có cần thiết không?
mgiuca

2
@Brandon Có, hãy xem bình luận thứ hai của kingjeffrey về câu trả lời của chính anh ấy. Bạn cần phải thiết lập currentTime.
mgiuca

Điều này hoạt động tốt (ít nhất là hôm nay)
dvlden

Câu trả lời:


118

Trong khi loopđược chỉ định, nó không được triển khai trongbất kỳ trình duyệt nào tôi biết Firefox [cảm ơn Anurag đã chỉ ra điều này] . Đây là một cách lặp thay thế sẽ hoạt động trong các trình duyệt hỗ trợ HTML5:

var myAudio = new Audio('someSound.ogg'); 
myAudio.addEventListener('ended', function() {
    this.currentTime = 0;
    this.play();
}, false);
myAudio.play();

1
Hừm ... thú vị. Tôi đã không gặp nhiều may mắn với phương pháp này trước đây nhưng tôi đã không đặt thời gian hiện tại. Khi tôi cố gắng này, tuy nhiên tôi nhận được: "Lỗi chưa gặp: INDEX_SIZE_ERR: DOM ngoại lệ 1" trên dòng "this.currentTime = 0"
Toji

1
@Toji Đây là tài liệu về lỗi INDEX_SIZR_ERR . Nó có nghĩa là phần đầu của bài hát nằm ngoài phạm vi mà trình duyệt có thể tìm kiếm. Điều này đôi khi xảy ra nếu trình duyệt cho rằng nó đang phát trực tuyến phương tiện hoặc nếu máy chủ thiếu một số khả năng nhất định (tôi quên mất khả năng cụ thể này là gì, nhưng tôi sẽ cố gắng theo dõi nó). Bạn cũng có thể sử dụng this.startTimeđể quay lại thời gian có sẵn sớm nhất.
kingjeffrey

@Toji Lý do .currentTimelà cần thiết liên quan đến cách thông số xử lý phần cuối của bài hát. Các trình duyệt phải tạm dừng bài hát. Vì vậy, khởi động lại vở kịch sẽ làm như vậy ở cuối bài hát. Đầu phát phải được đặt lại.
kingjeffrey

@Toji Đây là một suy nghĩ khác nếu bạn không thể bắt đầu .currentTimelàm việc. Bên trong hàm gọi lại, bạn chỉ cần khai báo lại myAudiovới cùng một tệp và phát lại. Khai báo lại nó cũng sẽ đặt lại playhead về đầu bài hát.
kingjeffrey

đặt nó thành this.startTime cho tôi lỗi tương tự, mặc dù bây giờ tôi bắt đầu tự hỏi liệu đó có phải là sự cố máy chủ hay không. Tôi đang cung cấp các tệp tĩnh từ một máy chủ django cục bộ (đây không phải là tính năng mạnh mẽ nhất của django). Ghép nối điều đó với thực tế là Anurag có hiệu quả và tôi nghĩ có lẽ chỉ có tôi. Tôi sẽ đùa giỡn với nó một chút nữa và cho bạn biết kết quả.
Toji

61

Để thêm một số lời khuyên khác kết hợp các đề xuất của @kingjeffrey và @CMS: Bạn có thể sử dụng loopnó ở những nơi có sẵn và quay lại trình xử lý sự kiện của kingjeffrey khi không có. Có một lý do chính đáng khiến bạn muốn sử dụng loopvà không viết trình xử lý sự kiện của riêng mình: Như đã thảo luận trong báo cáo lỗi của Mozilla , mặc dù loophiện tại không lặp lại liền mạch (không có khoảng trống) trong bất kỳ trình duyệt nào mà tôi biết, điều đó chắc chắn là có thể và có khả năng trở thành tiêu chuẩn trong tương lai. Trình xử lý sự kiện của riêng bạn sẽ không bao giờ liền mạch trong bất kỳ trình duyệt nào (vì nó phải chạy vòng qua vòng lặp sự kiện JavaScript). Do đó, tốt nhất bạn nên sử dụng loopnếu có thể thay vì viết sự kiện của riêng bạn. Như CMS đã chỉ ra trong một bình luận về câu trả lời của Anurag,looploop biến - nếu nó được hỗ trợ, nó sẽ là boolean (false), nếu không nó sẽ không được xác định, vì nó hiện đang có trong Firefox.

Kết hợp chúng lại với nhau:

myAudio = new Audio('someSound.ogg'); 
if (typeof myAudio.loop == 'boolean')
{
    myAudio.loop = true;
}
else
{
    myAudio.addEventListener('ended', function() {
        this.currentTime = 0;
        this.play();
    }, false);
}
myAudio.play();

Cám ơn. điều này đã hoạt động hoàn hảo cho Opera, Firefox, Chrome ... vậy làm cách nào chúng ta có thể thêm nhiều âm thanh (mp3) hơn cho Safari .... ??? thêm biến hơn có lẽ nguyên nhân lặp for Chrome (mà hỗ trợ ogg và mp3) ...

@pixelass Tôi không hoàn toàn chắc chắn về cách thực hiện điều đó trong mã. Trong HTML, bạn sẽ lồng các thẻ <audio> vào bên trong một thẻ khác và trình duyệt sẽ chọn thẻ ngoài cùng phù hợp. Tôi không biết liệu bạn có thể thực hiện việc lồng trong đối tượng Âm thanh có lập trình hay không. Nhưng bạn chắc chắn có thể tự mình lập trình: hãy xem phương thức Audio.canPlayType.
mgiuca

tôi biết về phương pháp html. Tôi có thể thử với phương thức Audio.canPlayType. ngay bây giờ tôi đang sử dụng 2 biến, vì vậy trong chrome 2 tệp sẽ được phát. điều này thực ra không quá quan trọng vì tôi chỉ thực hiện một số vòng lặp sóng biển. ... nhưng chỉ cần thêm 2 nguồn sẽ đẹp hơn rất nhiều ,. pixelass.com nếu bạn quan tâm.

19

Mã của bạn phù hợp với tôi trên Chrome (5.0.375) và Safari (5.0). Không lặp lại trên Firefox (3.6).

Xem ví dụ.

var song = new Audio("file");
song.loop = true;
document.body.appendChild(song);​

+1 Rất tuyệt. Tôi không biết loopđã được triển khai trong webkit.
kingjeffrey

10
+1, bạn cũng có thể phát hiện nếu loopđược hỗ trợ, ví dụ như bằng cách:typeof new Audio().loop == 'boolean';
Christian C. Salvadó

@CMS Tránh sử dụng ==và sử dụng ===, đó là một toán tử tốt hơn cho người mới bắt đầu và hiệu suất tốt hơn.
Hydroper

Cái này có tương thích với Firefox 80 không?
Mostafiz Rahman

4
var audio = new Audio("http://rho.nu/pub/Game%20Of%20Thrones%20-%20Main%20Theme%20-%20Soundtrack.mp3");

audio.addEventListener('canplaythrough', function() {
    this.currentTime = this.duration - 10;
    this.loop = true;
    this.play();
});

Chỉ cần đặt loop = true trong canplaythrough eventlistener.

http://jsbin.com/ciforiwano/1/edit?html,css,js,output


4

Cách đơn giản nhất là:

bgSound = new Audio("sounds/background.mp3");
bgSound.loop = true;
bgSound.play();

2

Hãy thử sử dụng jQuery cho trình nghe sự kiện, sau đó nó sẽ hoạt động trong Firefox.

myAudio = new Audio('someSound.ogg');

$(myAudio).bind('ended', function()  {
    myAudio.currentTime = 0;
    myAudio.play();
});

myAudio.play();

Đại loại vậy.


1

Tôi đã làm theo cách này,

<audio controls="controls" loop="loop">
<source src="someSound.ogg" type="audio/ogg" />
</audio>

và nó trông như thế này

nhập mô tả hình ảnh ở đây


0

Điều này hoạt động và việc chuyển đổi các phương pháp ở trên dễ dàng hơn rất nhiều:

sử dụng nội tuyến: onended="if($(this).attr('data-loop')){ this.currentTime = 0; this.play(); }"

Bật vòng lặp bằng cách $(audio_element).attr('data-loop','1'); Tắt vòng lặp bằng$(audio_element).removeAttr('data-loop');


0

Bạn có thể thử một setInterval, nếu bạn biết chính xác độ dài của âm thanh. Bạn có thể để setInterval phát âm thanh mỗi x giây. X là độ dài âm thanh của bạn.


Điều này không cung cấp câu trả lời cho câu hỏi. Để phê bình hoặc yêu cầu làm rõ từ tác giả, hãy để lại nhận xét bên dưới bài đăng của họ - bạn luôn có thể nhận xét về bài đăng của chính mình và khi bạn có đủ uy tín, bạn sẽ có thể nhận xét về bất kỳ bài đăng nào .
Alex Char

4
@AlexChar Tôi không đồng ý. Đây ít nhất là một nỗ lực để trả lời câu hỏi. Nó có thể được hưởng lợi từ một số mở rộng để hiển thị chính xác mã có thể trông như thế nào và nó có lẽ không phải là cách tốt nhất để giải quyết vấn đề, nhưng nó không phải là "không phải là câu trả lời".
Anthony Grist

Làm như vậy sẽ gặp rắc rối kinh nghiệm.
Hydroper
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.