6 điểm bởi GN⁺ 2025-02-17 | 1 bình luận | Chia sẻ qua WhatsApp
  • Khi lần theo nhiễu trắng trên laptop Linux, phát hiện vấn đề là một tab Firefox vẫn tiếp tục đánh thức audio sink của PulseAudio dù không có âm thanh thực sự nào
  • module-suspend-on-idle được cấu hình để dừng thiết bị âm thanh sau 10 giây, nhưng khi website tạo AudioContext, sink không hạ xuống trạng thái IDLE/SUSPENDED
  • Hiện tượng tương tự xuất hiện với thông báo web của Outlook, thao tác nhấp trên x.com, phát giọng đọc của Google Translate và ứng dụng web Discord; chỉ cần new AudioContext() cũng đủ làm nhiễu bắt đầu
  • Theo đo đạc, khi không có nhiễu, mức dùng CPU của pulseaudio là 0,0%, nhưng khi có nhiễu là 4,7%, còn công suất hệ thống tăng khoảng 1,5W
  • AudioContext.suspend() có thể dừng truy cập phần cứng âm thanh để giảm mức dùng CPU/pin, nhưng Firefox không tự động dừng lãng phí sau một khoảng thời gian như Chrome

Vấn đề audio sink không chịu ngủ

  • Trên laptop mới, ngay cả khi không phát nhạc hay âm thanh, loa vẫn phát ra nhiễu trắng rất nhỏ nhưng gây khó chịu
  • Đã dùng pactl list sinks short để kiểm tra trạng thái PulseAudio trên Linux
    • Trạng thái audio sink được hiển thị là một trong IDLE, SUSPENDED, RUNNING
    • Khi sink ở trạng thái SUSPENDED, loa im lặng
    • Khi ở IDLE hoặc RUNNING, nhiễu trắng có thể xuất hiện dù không có âm thanh phát thực tế
  • Trong /etc/pulse/default.pa/etc/pulse/system.pa, module-suspend-on-idle đã được nạp
    • Theo cấu hình, nếu không hoạt động trong 10 giây thì audio sink phải tự động dừng
    • Tuy nhiên trong một số tình huống, sink không chuyển sang IDLE, nên cũng không thể đạt tới SUSPENDED

Vì sao âm thanh nhàn rỗi lại tiêu tốn điện

  • module-suspend-on-idle tách các sink và source không được kết nối với stream trong một khoảng thời gian nhất định khỏi backend
  • Tác dụng cốt lõi là tiết kiệm điện
    • Nếu PulseAudio gửi dữ liệu rỗng tới sound card ngay cả khi nhàn rỗi, ALSA sẽ dùng nhiều chu kỳ CPU hơn
    • Nếu không có kế hoạch luôn duy trì stream hoạt động, đặt timer thấp sẽ có lợi hơn cho việc tiết kiệm điện

Nguyên nhân được thu hẹp về tab Firefox và website

  • Mỗi khi nghe thấy nhiễu trắng, dùng pactl list sink-inputs để kiểm tra chương trình nào đang sử dụng audio sink
  • Nguyên nhân luôn là Firefox
    • Không có tab nào trong số các tab đang mở cần phát âm thanh thực sự
    • Cũng không có video nào bị tắt tiếng
  • Đã thêm một script nhỏ vào thanh trạng thái i3 để hiển thị dấu đỏ khi audio sink chuyển sang RUNNING
  • Ban đầu có vẻ nguyên nhân là âm báo từ outlook.office.com, được mở dưới dạng tab ghim
    • Khi nhận email, nhiễu trắng bắt đầu
    • Nó không dừng cho đến khi tải lại tab hoặc khởi động lại Firefox
  • Sau đó, hiện tượng tương tự cũng được xác nhận trên các website khác
    • x.com bắt đầu gây nhiễu ngay khi nhấp vào bất cứ chỗ nào
    • Nhiễu cũng xuất hiện khi nghe giọng đọc bản dịch trên translate.google.com
    • Chỉ cần mở ứng dụng web Discord cũng gây ra hiệu ứng tương tự

Kết quả đo CPU và điện năng

  • Khi không có nhiễu trắng, mức dùng CPU của pulseaudio hiển thị là 0,0%
  • Trong cùng môi trường, số đo điện năng nhìn chung nằm trong khoảng 4,2~5,1W
  • Khi có nhiễu trắng, mức dùng CPU của pulseaudio tăng lên 4,7%
  • Khi đó, số đo điện năng nhìn chung nằm trong khoảng 5,8~6,7W
  • Khác biệt này không phải là “không đáng kể”, mà có thể tóm lại là tăng khoảng 1,5W

WebAudio API và AudioContext

  • Trong HTML/JavaScript, có hai cách phát âm thanh: thẻ <audio>WebAudio API
  • Với trường hợp phát âm thanh động như Outlook, WebAudio API được dùng, và để xử lý âm thanh thì trước tiên phải tạo AudioContext
  • Vấn đề là chỉ cần chạy const audioCtx = new AudioContext(); cũng khiến loa phát ra nhiễu trắng
  • Trang thử nghiệm được cung cấp tại https://editor.43z.one/sqare/i
  • AudioContext.suspend() dừng tiến trình thời gian của audio context và tạm dừng truy cập phần cứng âm thanh, qua đó giảm mức dùng CPU/pin
  • AudioContext.resume() khởi động lại tiến trình thời gian của audio context đang bị dừng

Khác biệt giữa Firefox và Chrome

  • Nhiều website tạo AudioContext dù không cần phát âm thanh ngay lập tức, rồi sau đó không suspend
  • Chrome tự động dừng việc lãng phí CPU/pin sau một khoảng thời gian
  • Firefox không tự dừng, mà tiếp tục duy trì trạng thái phát nhiễu trắng
  • Dù website là nguyên nhân trực tiếp, vẫn còn sự bất mãn rằng Firefox không bảo vệ người dùng khỏi kiểu lãng phí tài nguyên này
  • Có nghi ngờ rằng ngay cả khi kết nối tai nghe Bluetooth, sau khi nhấp trên x.com, việc truyền nhiễu trắng cũng bắt đầu và có thể làm lãng phí pin tai nghe

Cách xử lý tạm thời: AudioContext Suspender

  • Để giảm nhẹ vấn đề, một extension đã được tạo nhằm tự động dừng AudioContext, rồi khởi động lại khi website định phát âm thanh
  • Extension này không hoàn hảo
    • Việc khởi động lại mất một chút thời gian
    • Có nhiều đường dẫn để bắt đầu âm thanh, nên không phải lúc nào cũng có thể tiếp tục lại
    • Dù vậy, nó đủ cho mục đích sử dụng
  • Liên kết liên quan
  • Các issue Bugzilla liên quan

1 bình luận

 
GN⁺ 2025-02-17
Ý kiến trên Hacker News
  • Việc này đã được lên kế hoạch và quan trọng, và nếu có thể sẽ được sửa sớm. Nó đã bị trì hoãn khá lâu rồi, và xin lỗi vì đến nay vẫn chưa xử lý được. Đây luôn là cuộc chiến ưu tiên nên khó làm hài lòng mọi người đúng lúc, nhưng trong danh sách ưu tiên cá nhân của tôi thì nó ở vị trí khá cao
    Như bạn có thể hình dung, việc này phức tạp hơn nhiều so với chỉ tạm dừng AudioContext sau một khoảng thời gian im lặng, nhưng dù sao tôi nghĩ là có thể sửa được. Vì các trình duyệt khác đã làm rồi, và cũng có những thỏa hiệp có thể chấp nhận được
    Nguồn: tôi đã triển khai nhiều chức năng quanh phần này trong Firefox và cũng là biên tập viên của chuẩn Web Audio API
    • Mong bạn đừng xem những phê bình kiểu này là nhắm vào cá nhân. Gần đây đã có một maintainer mã nguồn mở coi những phê bình như vậy là sự bức xúc và mọi chuyện bùng nổ khá lớn
      Phần lớn mọi người hiểu hoàn cảnh được nói ở đây. Việc thì nhiều mà thời gian có hạn
      Tôi đã tận mắt thấy các nhà phát triển Firefox nỗ lực vượt kỳ vọng để các trang có lượng dùng lớn hoạt động đúng cho người dùng. Tôi biết khi vấn đề ảnh hưởng đến người dùng thì các bạn có thể đi xa đến đâu, nên mong các bạn tiếp tục cố gắng
    • Tôi muốn trở thành người dùng Firefox tốt hơn, nên muốn thử debug các vấn đề phát hiện được trên máy cục bộ. Cần được chỉ dẫn nên bắt đầu từ đâu
  • Việc một website mở audio context mà không thực sự phát gì có lẽ nhiều khả năng là để phát hiện bot
    Vì cách xử lý âm thanh được triển khai khác nhau giữa các engine trình duyệt và hệ điều hành, nếu phát một âm thanh hoàn toàn không nghe thấy rồi ghi lại qua API thì sẽ tạo ra một chữ ký
    Có thể dùng chữ ký đó để kiểm tra xem trình duyệt có đang giả mạo user agent không, có ở chế độ headless không, hay có thuộc đủ loại trường hợp đặc biệt không phải tình huống người dùng thật đang mua hàng hay không
    https://github.com/fingerprintjs/fingerprintjs/blob/3201a7d6...
    • Có vẻ phía trình duyệt/chuẩn web đã mở rộng API quá bừa bãi, và chưa suy nghĩ đủ về việc thế giới sẽ lạm dụng chúng theo cách này
    • Thực tế trong các plugin dành cho bot đang lưu hành đã có những thứ mô phỏng Audio Context để đánh lừa phát hiện bot. Thật điên rồ
    • Tôi đã nóng lòng chờ ngày Cloudflare đưa thứ này vào để cản trở tự do duyệt web hơn nữa và khiến chúng ta lãng phí thêm chu kỳ CPU
  • Tôi đã phát điên với tiếng white noise này suốt một thời gian dài mà hoàn toàn không tìm ra nguyên nhân
    Tab không hiện biểu tượng đang phát, và tắt tiếng tab cũng không làm tiếng ồn dừng lại
    Tắt tiếng Firefox trong Windows Volume Mixer cũng không làm âm thanh dừng lại
    Sửa: với người dùng desktop thì tiện ích mở rộng này thực ra khá tệ. Việc white noise liên tục bật rồi tắt còn khó chịu hơn nhiều
    • Nếu tắt tiếng Firefox bằng Windows Volume Mixer mà vẫn không dừng, thì tôi nghĩ đây chẳng phải là lỗi ở tầng sâu hơn Firefox sao
    • Tôi đang dùng tiện ích mở rộng đó trên desktop mà không gặp vấn đề gì. Có vẻ tùy vào trang bạn truy cập. Với các trang thường xuyên phát/dừng âm thanh thì có lẽ nên tắt extension
  • Khi đầu ra ở trạng thái idle, tín hiệu SPDIF kỹ thuật số sẽ mất đồng bộ. Khi bắt đầu phát lại thì việc đồng bộ lại không diễn ra tức thì, và sẽ mất khoảng 1 giây âm thanh đầu tiên
    Vì vậy tôi đã tự viết một chương trình không đẩy dữ liệu qua đường truyền nhưng vẫn giữ đầu ra mở, để đầu ra không rơi vào trạng thái idle
    Tuy nhiên trong bối cảnh laptop thì điều này không hợp lý lắm, nên ở đó tiết kiệm năng lượng là hợp lý
    • Khi dùng FiiO K3 DAC với MacBook, chuyện này thật sự gây khó chịu không dứt. Các âm thanh hệ thống như tiếng thông báo gần như không được phát do độ trễ
      Driver Windows có tùy chọn đặt stream thành Always On. Ước gì macOS cũng có
    • Trước đây tôi từng làm điều tương tự với USB DAC. Chỉ là cho play -qn & khởi chạy khi đăng nhập
  • Có vẻ điều này giải thích vấn đề thỉnh thoảng Firefox trên Android khiến điện thoại ngẫu nhiên dùng hết 10GB dữ liệu trong một ngày. Cước di động tăng đến vô lý
    Có lẽ một trang tin tức đang phát âm thanh đồng thời liên tục tải quảng cáo mới, và vì âm thanh nên tab không chuyển sang trạng thái tiết kiệm năng lượng. Các khoản phí dữ liệu ngoài dự kiến cứ tiếp diễn nên cuối cùng tôi phải chuyển sang Chrome
  • Trước đây tôi cũng từng thấy hiện tượng giống hoặc rất tương tự trên macOS. Không chắc là trang web thực sự giữ audio context mở, hay là vấn đề nội bộ của Firefox. Vì nó cũng xảy ra trên các trang như Youtube vốn không dùng Web Audio API
    Tức là không có white noise, nhưng có tiêu thụ điện do âm thanh: https://bugzilla.mozilla.org/show_bug.cgi?id=1821102
    Ngay lúc này trên Mac không phát gì cả mà coreaudiod vẫn dùng 20% CPU. Nó thật sự phá hỏng thời lượng pin, nên tôi đang nghĩ có nên chuyển sang trình duyệt khác cho đến khi được sửa không, nhưng tôi không muốn bỏ Firefox chỉ vì một thứ trông có vẻ nhỏ nhặt như vậy
    Cập nhật: có liên quan nhưng có vẻ là bug khác
  • Đoạn code xử lý việc tạm dừng này trong Chromium nằm ở đây:
    https://source.chromium.org/chromium/chromium/src/+/main:med...
    Về cơ bản, nếu phát hiện khoảng 30 giây im lặng thì nó chuyển từ sink được thiết bị âm thanh của hệ điều hành hỗ trợ sang null sink
    Nhân tiện, vì cách này dùng một đồng hồ khác với thiết bị âm thanh, đã có vài báo cáo rằng khi context về sau được sử dụng thật sự, một số tone nhất định bị méo. Cách né là trang dùng suspend/resume API được nhắc trong bài viết
  • Tôi không biết chi tiết audioContext được triển khai nội bộ ra sao, nhưng có vẻ nó chứa nhiều yếu tố khá thông minh và cố xử lý động. Việc phát âm thông báo trông giống cảm giác dùng D3 để vẽ SVG thay vì img href *.svg
    Tôi tự hỏi liệu có thứ gì như hook Service Worker để đăng ký những việc đơn giản, có thể lặp lại như trình xử lý thông báo vào một API hiệu quả ở tầng thấp hơn không
  • Thực sự có cần nghe thấy gì đó không?
    Trên Firefox 134.0.1 của MacOS thì tôi không nghe thấy gì cả
    • Phía tôi cũng không có tiếng, nhưng khi nhấn nút phát âm thanh trên trang demo của tác giả thì mức tiêu thụ điện tăng khoảng 1W
    • Trên Firefox Android thì nghe thấy một chút white noise
  • Cái này đã sửa được vấn đề trang đầu của https://www.dr.dk/