Câu hỏi thường gặp về nội dung âm thanh trên web

Trong vài tháng qua, Web Audio API của WebKit đã trở thành một nền tảng hấp dẫn cho các trò chơi và ứng dụng âm thanh trên web. Khi các nhà phát triển làm quen với công cụ này, tôi nhận thấy những câu hỏi tương tự liên tục xuất hiện. Bản cập nhật nhanh này nhằm giải đáp một số câu hỏi thường gặp để giúp bạn có trải nghiệm tốt hơn với API Âm thanh trên web.

Hỏi: Giúp tôi với, tôi không thể phát ra âm thanh!

Đáp: Nếu bạn mới sử dụng Web Audio API, hãy xem hướng dẫn bắt đầu hoặc công thức của Eric để phát âm thanh dựa trên hoạt động tương tác của người dùng.

Hỏi: Tôi nên có bao nhiêu ngữ cảnh âm thanh?

Đáp: Nhìn chung, bạn nên thêm một AudioContext cho mỗi trang và một ngữ cảnh âm thanh có thể hỗ trợ nhiều nút được kết nối với ngữ cảnh đó. Mặc dù bạn có thể đưa nhiều AudioContext vào một trang, nhưng việc này có thể làm giảm hiệu suất.

Hỏi: Tôi có một AudioBufferSourceNode, tôi vừa phát lại bằng noteOn() và tôi muốn phát lại, nhưng noteOn() không làm gì cả! Giúp tôi với!

Đáp: Sau khi phát xong, nút nguồn sẽ không phát được nữa. Để phát lại bộ đệm cơ bản, bạn nên tạo một AudioBufferSourceNode mới và gọi noteOn().

Mặc dù việc tạo lại nút nguồn có vẻ không hiệu quả, nhưng các nút nguồn được tối ưu hoá rất nhiều cho mẫu này. Ngoài ra, nếu giữ một handle cho AudioBuffer, bạn không cần phải tạo một yêu cầu khác cho thành phần để phát lại cùng một âm thanh. Nếu bạn thấy cần lặp lại mẫu này, hãy đóng gói quá trình phát bằng một hàm trợ giúp đơn giản như playSound(buffer).

Hỏi: Khi phát âm thanh, tại sao bạn cần tạo một nút nguồn mới mỗi lần?

Đáp: Ý tưởng của cấu trúc này là tách biệt thành phần âm thanh khỏi trạng thái phát. Lấy ví dụ về máy hát đĩa, bộ đệm tương tự như bản ghi và nguồn tương tự như đầu phát. Vì nhiều ứng dụng liên quan đến nhiều phiên bản của cùng một vùng đệm phát đồng thời, nên mẫu này là thiết yếu.

Hỏi: Làm cách nào để xử lý âm thanh từ thẻ audiovideo?

Đáp: MediaElementAudioSourceNode đang được phát triển! Khi có, tính năng này sẽ hoạt động như sau (thêm hiệu ứng bộ lọc vào một đoạn phát qua thẻ âm thanh):

<audio src="sounds/sample.wav" controls>
var audioElement = document.querySelector('audio');
var mediaSourceNode = context.createMediaElementSource(audioElement);
mediaSourceNode.connect(filter);
filter.connect(context.destination);

Tính năng này được theo dõi trong crbug này. Xin lưu ý rằng trong chế độ thiết lập này, bạn không cần gọi mediaSourceNode.noteOn(), thẻ âm thanh sẽ kiểm soát quá trình phát.

Hỏi: Khi nào tôi có thể nhận được âm thanh từ Micrô?

Đáp: Phần đầu vào âm thanh của tính năng này sẽ được triển khai trong WebRTC bằng getUserMedia và có sẵn dưới dạng nút nguồn đặc biệt trong API Web Audio. Phương thức này sẽ hoạt động cùng với createMediaElementSource.

Hỏi: Làm cách nào để kiểm tra thời điểm AudioSourceNode phát xong?

Đáp: Hiện tại, bạn phải sử dụng bộ hẹn giờ JavaScript vì Web Audio API không hỗ trợ chức năng này. Đoạn mã sau đây trong hướng dẫn Bắt đầu sử dụng API âm thanh trên web là ví dụ về cách thực hiện việc này:

// Assume source and buffer are previously defined.
source.noteOn(0);
var timer = setTimeout(function() {
    console.log('playback finished');
}, buffer.duration * 1000);

Có một lỗi đang mở khiến API Web âm thanh triển khai lệnh gọi lại chính xác hơn.

Hỏi: Âm thanh tải khiến toàn bộ luồng giao diện người dùng bị khoá và giao diện người dùng của tôi không phản hồi. Trợ giúp!**

Đáp: Sử dụng API decodeAudioData để tải không đồng bộ nhằm tránh chặn luồng chính. Xem ví dụ này.

Hỏi: Có thể sử dụng API Âm thanh trên web để xử lý âm thanh nhanh hơn thời gian thực không?

Đáp: Có, chúng tôi đang tìm giải pháp. Hãy chú ý theo dõi!

Hỏi: Tôi đã tạo một ứng dụng Web Audio API tuyệt vời, nhưng mỗi khi thẻ đang chạy chuyển sang chế độ nền, âm thanh sẽ trở nên kỳ lạ!

Đáp: Điều này có thể là do bạn đang sử dụng setTimeouts. Phương thức này sẽ hoạt động theo cách khác nếu trang chạy ở chế độ nền. Trong tương lai, Web Audio API sẽ có thể gọi lại vào những thời điểm cụ thể bằng cách sử dụng bộ hẹn giờ nội bộ của âm thanh trên web (thuộc tính context.currentTime). Để biết thêm thông tin, vui lòng xem yêu cầu về tính năng này.

Nhìn chung, bạn nên dừng phát khi ứng dụng chuyển sang chế độ nền. Bạn có thể phát hiện thời điểm một trang chuyển sang chế độ nền bằng API Chế độ hiển thị của trang.

Hỏi: Làm cách nào để thay đổi độ cao của âm thanh bằng API Web âm thanh?

Đáp: Thay đổi playbackRate trên nút nguồn.

Hỏi: Tôi có thể thay đổi độ cao mà không thay đổi tốc độ không?

Đáp: API Âm thanh trên web có thể có một PitchNode trong ngữ cảnh âm thanh, nhưng việc này khó triển khai. Điều này là do không có thuật toán chuyển đổi cao độ đơn giản nào trong cộng đồng âm thanh. Các kỹ thuật đã biết tạo ra các hiện tượng giả, đặc biệt là trong trường hợp độ lệch cao độ lớn. Có hai phương pháp để giải quyết vấn đề này:

  • Các thuật toán miền thời gian gây ra các hiện tượng phản hồi phân đoạn lặp lại.
  • Các kỹ thuật trong miền tần số gây ra hiện tượng âm thanh dội lại.

Mặc dù không có nút gốc nào để thực hiện các kỹ thuật này, nhưng bạn có thể thực hiện bằng JavaScriptAudioNode. Đoạn mã này có thể là điểm xuất phát.

Hỏi: Làm cách nào để tạo AudioContext ở tốc độ lấy mẫu mà tôi chọn?

Câu trả lời: Hiện tại, chúng tôi chưa hỗ trợ tính năng này nhưng đang xem xét. Xem yêu cầu về tính năng này.

Nếu có câu hỏi khác, vui lòng đặt câu hỏi trên StackOverflow bằng cách sử dụng thẻ web-audio.