Without using any plug-ins, the front-end native JS changes from the audio source to try to play the audio backwards

I don’t know what the rules are for using bloB binary to store audio on the front end. I can’t find any reference on the web. I just tried it out on my own.

interface

Three <audio> tags, one for recording, one for playing forward and one for playing backward, and two <button> tags for starting and ending a recording.

try

First I convert the binary blob to an unsigned Uint8Array array, and then:

First try

I naively thought I could turn the array upside down, go back to the Blob, and play!

And of course — no way!!

Second attempt

I found that I cut it off from the front of the array, and it still works, but it doesn’t.

I concluded that there was a fixed length in front of the array to indicate that this was an audio file (and mono, or whatever, I don’t know), and then I compared the two audio clips, and what was the common length — 91 (the array was the same before 90), But the common length is only part of the audio header (the non-looping part), which is up to 160 (length 161)

Question 1: Why are the sections from 91 to 97 different?

A: I don’t know

Q2: the same after 164, why do you think this is not the audio head?

A: starting at 161bit [163,65, X, 129], I noticed that this thing was repeated later, and the interval between the next one was equal to X+259, so I ventured to speculate that this was the beginning of the smallest unit representing sound.

Note:

The smallest unit we can invert is [163,65, X, 129…….] At the beginning of the array (where X is the array length), 10 array broadcast time is 0.48 s, but the array of 16 broadcast time ranged from 0.78 s to 0.9 s, so it is not a code block recorded the fixed how many milliseconds (it’s not my definition, the blob audio with the official method to array and then he just like that, There’s nothing I can do)

Third attempt

I then started by taking the code from one [163,65, X, 129] to another [163,65, X, 129] as the smallest unit S with the docks reserved, and then inverting the order of all the smallest units (from S_1,S_2,S_3,…..) while keeping the order of the code within the smallest unit S unchanged S_n become S_n, S_n – 1,… The S_1)

And then of course it turns out — again, no.

And then I put them all backwards to take the five S’s and put them backwards, and there it is! I read myself 123456 became 654321! But that audio bar can’t drag, it’s always at the last second. As shown below, finish the 4s.

Fourth attempt

I can’t bear it! Definitely not, audio bar can’t drag what a trick! Then I inverted the first half of the array and left the second half uninverted. As a result, when I clicked play, the 6 seconds of audio started from 3s and lasted for 3s (0:03). The audio played normally until 6s (because the last 3 seconds were not inverted), so I think there must be something recording the time. So we look down and see some patterns (the output is the position of 65 in X [163,65, X, 129], followed by the next four digits), and my intuition tells me that this increment of two digits is actually recording time!

Then I cycle to each segment of the two changes for increasing, play is from LingMiao, gradually increase until the last second, the code now, some can run backward, not some (8 s after the original audio plays back into 4 s or 5 s is shorter) anyway, the cause is unknown, so write unfinished…

code

<! DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, "> <meta HTTP-equiv =" x-UA-compatible "content=" IE =edge"> <title>Document</title> <script> let recorder function start() { let videoTarget = document.getElementById('audio') navigator.mediaDevices.getUserMedia({audio: true, video: False}). Then ((stream) => {recorder = new MediaRecorder(stream) videotarget. srcObject = stream //s  0 recorder.ondataavailable = (event) => { let blob = event.data let videoTarget2 = document.getElementById('audio2') let videoTarget3 = document.getElementById('audio3') let a = blob.stream().getReader() a.read().then(({ done, Value}) => {let newValue = [] let r = 0 // let b = 0 // let newValue = [] for(i = 0; i < value.length; I++) {if (value = = = 163) [I] {/ / s = 1 means into the state of alert s = 1} else if (s = = = 1 && value [I] = = = 65) {/ / under the condition of alert value [I] = = = 65 means it does start a new piece of audio with the smallest unit b === 5? (r = 162,b = 0) : B ++ // here b===5 can be changed, I set 5 S as a whole inverted, because the duration of each S is too short, an inverted S will produce a bad audio effect //r=162 is to move the pointer to 162, which is the first place that the audio head starts to loop, so we have completed the inversion. } else {//value[I]! == 65 means it's just a coincidence, it's not a surrogate port, // Insert newValue.splice(r, 0, value[I]) // move the pointer back r++} b = 0 // Now we have the array that we got on the third attempt, Newvalue.splice (r, 0, 163) // delete the last element because moving the pointer back would add 163 to the end of the array. Newvalue.pop () // then we would change the last two bits of the smallest unit of sound S to 0 0, 0 60,0 120.... for(i = 0; i < newValue.length; I ++) {if(newValue[I] == 163){s = 1} else if(s == 1 && newValue[I] == 65) {// NewValue [I +3] = parseInt(b * 60/256) newValue[I +4] = b * 60/256 b++ console.log(I, newValue[I +3], NewValue [I +4])} else {s = 0} console.log(newValue) console.log(value) // Change the new array to bloB and assign it to audio Uint8Array(newValue) let blob2 = new Blob([newValue], {type: 'audio/webm; codecs=opus'}) videoTarget2.src = window.URL.createObjectURL(blob2) let blob3 = new Blob([value], {type: 'audio/webm; codecs=opus'}) videoTarget3.src = window.URL.createObjectURL(blob3) }) } recorder.start() }); } function stop() { document.getElementById('audio').pause() recorder.stop() } </script> </head> <body> <audio <audio id="audio" controls autoplay></audio> <audio id=" audiO3" </audio> <input onclick="start()" type="button" value=" start "/> <input onclick="stop()" type="button" Value =" end "/> </body> </ HTML >Copy the code