A few lines of code crash Chrome: HTML5 MP3 recording is upgraded from ScriptProcessorNode to AudioWorkletNode

Keywords: STATUS_ACCESS_VIOLATION AudioContext AudioWorkletNode audioWorklet addModule resume suspended createScriptProcessor
crash Chrome test page: test page address

cause of the incident

My GitHub open source front-end H5 recording library a few years ago: https://github.com/xiangyuecn/Recorder , provides mp3 wav ogg webm amr format support, has rich audio visualization, variable speed and pitch processing, audio stream playback, ASR voice Supporting functions such as identification; with powerful real-time processing support, it can be used in various web applications; recently, I plan to try to use new browser features to upgrade and follow the development of the previous era.

I don't remember which version of Chrome started, when the correct AudioContextmethod createScriptProcessoris called, it will print a method outdated reminder in the console: [Deprecation] The ScriptProcessorNode is deprecated. Use AudioWorkletNode instead..

log reminder

ScriptProcessorAlthough it is marked as obsolete, all modern browsers including early browsers are well supported and have not been officially removed on any browser. Chrome's outdated reminders have caused frequent Some people asked if they should use AudioWorkletit instead. The current conclusion is that it is not necessary, because in terms of the scene of obtaining recording data, there is no difference in performance between the two on the PC side, but on the contrary, it has ScriptProcessormore performance advantages on the mobile side. This is of course a later story.

In fact, I wanted to upgrade AudioWorkletthe support provided a long time ago. After simply going through the document, the expected increase in the amount of code will not be very large (in the end, 2KB was actually added after the actual compression. Check out the 100 lines of code here ), but drag It was only a while ago that I wrote the code.

core code

Phenomenon recurrence

In the process of writing a good test at the beginning, I found that as long as the interactive operation is fast enough, the Chrome (version: 97) browser often crashes inexplicably (a phenomenon that has never been seen before), and the old version of Chrome80 will also crash, the error code: , STATUS_ACCESS_VIOLATIONmore The old 66 and 70 did not crash (thanks to the " Making a Chrome Portable Version for Multi-Version Coexistence " written earlier is very convenient for testing), and FireFox will not crash either.

After repeated testing, the problem was located: suspendedin the state AudioContext, when audioWorklet.addModule+ 构造AudioWorkletNodewas not completed, the call was made at the same time , and the browser crashed at the moment when it was resumerestored to the state. runningIn fact, the root cause is that the page is created without user interaction, and AudioContextthe state at this time is likely to be suspended(the purpose is that the browser prohibits bypassing automatic sound playback without user operation).

I have integrated these test codes into a test file, click here to test , and it is very easy to reproduce in Chrome.

Reproduce test page

crashed

pit filling

Once you know the problem, the solution is simple:

  • Method 1: wait until there is a user operation before AudioContextcreating, and at this time it can be guaranteed that it must be in runningthe state;
  • Method 2: Call the method directly AudioContext, resumeand runningthere will be no crash after waiting.

Since this is an open source library, I cannot decide whether the developer will wait for the user to operate, so the second method is based on universal applicability.

After calling AudioContext.resume, what it returns is an initialization performed Promisein finallythe block (regardless reject, the small probability of crash in the small probability can be ignored) AudioWorklet, that is, to put the original initialization code in one layer.

pit filling code

In addition, under AudioContext.audioWorklet.addModulethe local file://protocol, Chrome does not support loading Blob Url (FireFox does not have this problem), and it is also Worker, which WebWorkerdoes not have this problem; finally, it is data urlcompatible with Chrome:data:text/javascript;base64,......

Final Results

AudioWorkletThe pits have been filled, and the tests that should be tested have been tested, and a new version using recordings has been released with joy . After the release, I fiddled with it on my mobile phone, hey, why did the recording seem to be a few seconds short. . .

Repeated timing tests on the PC and mobile terminals, and finally issued a statement: Due to 375 callbacks per second inside the audioWorklet, there may be performance problems on the mobile terminal, which may cause the callback to be lost and the recording to be shortened. The PC terminal has no impact, and it is not recommended to enable audioWorklet for the time being.

Therefore, another version was updated, and it was simply restored. The library ScriptProcessoris still the main force by default, and it can Recorder.ConnectEnableWorklet=truebe used forcibly through the settings AudioWorklet.

Facing the future, if any browser is officially removed in the future ScriptProcessor, Recorder will be automatically enabled AudioWorklet, so the code written now will have great significance for the future, although it is a bit tasteless at present (I feel that AudioWorkletthe support is still written early, and it is a bit vain feeling), but the significance is still great.

For the complete AudioWorkletimplementation code, please move to read: line L157-L281 of recorder-core.js .

【End】

Guess you like

Origin blog.csdn.net/xiangyuecn/article/details/123392860