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 đã nổi lên 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 tính năng này, tôi nghe thấy những câu hỏi tương tự xuất hiện nhiều lần. Bản cập nhật nhanh này nhằm mục đích giải đáp một số câu hỏi thường gặp hơn để mang lại trải nghiệm dễ chịu hơn cho bạn khi sử dụng Web Audio API.

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 làm quen với 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 lượt tương tác của người dùng.

Hỏi: Tôi nên có bao nhiêu Audio Context?

Đáp: Thông thường, 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ể thêm nhiều AudioContext vào một trang, nhưng điều này có thể ảnh hưởng đến hiệu suất.

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

Đáp: Sau khi phát xong, một nút nguồn sẽ không thể phát thêm. Để 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ó thể 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 đối tượng xử lý cho AudioBuffer, bạn không cần phải đưa ra 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 mình 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: Tại sao bạn cần tạo một nút nguồn mới mỗi khi phát lại âm thanh?

Đáp: Ý tưởng của cấu trúc này là tách rời tài sản âm thanh khỏi trạng thái phát. Lấy ví dụ về máy phát nhạc, vùng đệ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à cần thiết.

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

Đáp: MediaElementAudioSourceNode đang được phát triển! Khi có sẵn, bộ lọc này sẽ hoạt động theo cách sau đây (thêm hiệu ứng bộ lọc vào một mẫu đang 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 một nút nguồn đặc biệt trong Web Audio API. Tính năng 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 Web Audio API là một ví dụ về cách hoạt động của API 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 chưa được khắc phục khiến Web Audio API triển khai một lệnh gọi lại chính xác hơn.

H: Việc tải âm thanh 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. Tôi cần 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. Hãy xem ví dụ này.

Hỏi: Có thể dùng Web Audio API để xử lý âm thanh nhanh hơn thời gian thực không?

Đáp: Có, chúng tôi đang nỗ lực tìm ra 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 bất cứ khi nào thẻ mà ứng dụng đang chạy chuyển sang chế độ nền, âm thanh sẽ trở nên rất lạ!

Đáp: Điều này có thể là do bạn đang sử dụng setTimeouts. Các chỉ số này sẽ hoạt động khác nhau nếu trang ở 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 Page Visibility API.

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

Đá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: Web Audio API có thể có PitchNode trong ngữ cảnh âm thanh, nhưng khó triển khai. Điều này là do cộng đồng âm thanh không có thuật toán dịch chuyển cao độ đơn giản. Các kỹ thuật đã biết tạo ra các hiện tượng giả tạo, đặc biệt là trong trường hợp độ dịch chuyển cao độ lớn. Có hai loại phương pháp để giải quyết vấn đề này:

  • Thuật toán miền thời gian, gây ra hiện tượng lặp lại các phân đoạn có âm vang.
  • Các kỹ thuật miền tần số gây ra hiện tượng âm thanh vang vọng.

Mặc dù không có nút gốc để 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ể đóng vai trò là điểm xuất phát.

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

Đáp: Hiện tại, chúng tôi chưa hỗ trợ tính năng này, nhưng đang tìm cách hỗ trợ. Xem yêu cầu về tính năng này.

Nếu có thêm câu hỏi, bạn có thể đặt câu hỏi trên StackOverflow bằng thẻ web-audio.