With the rise of social apps such as WeChat, voice chat has become a must-have feature for many apps, ranging from social apps that use voice chat as their main function to e-commerce apps with voice customer service and store waiter functions. Voice chat has become indispensable. Way.
However, many people feel that web-side voice is far away from us, and these are more the work of local applications. In fact, this is not the case. With the development of Html5, the voice function has gradually become one of the must-have functions on the front-end.
Why should we learn HTML5 voice?1. The Html5 specification is advancing, and mobile phone updates have accelerated operating system updates. The voice function will become one of the main tasks of the front end, just like the current canvas. Front-end implementation of voice function development is faster and saves more manpower (this means saving money for the boss, and saving money for the boss is giving yourself a salary increase)
2. Even if local applications now have voice functions, being familiar with the various pitfalls of front-end voice interaction can make your colleagues have a more harmonious relationship and smoother collaboration instead of fighting each other.
3. Understanding new technologies can prevent interviews, and secondly, you can predict technological trends, so that you will not learn a bunch of dragon-slaying skills or stick to the rules. It is more conducive to keeping your knowledge and professional core competitiveness at the top of the food chain.
4. Most people on the front end have misunderstandings about the voice function. They think that the voice function is just the HTML5 audio tag. In fact, it is really not that simple.
Not so much ink, let’s just develop a small project and everything will be clear. Let’s look at the renderings first.
clipboard.png
The business logic is very simple,
It is exactly the same as our WeChat method. When you press down, the word will be released to end, and the speech will be recorded. When you let go, it will be pressed to end, and the voice will be sent to the other party at the same time.
Let's do it step by step. First, let's complete an html page.
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width, initial-scale=1.0> <meta http-equiv=X-UA -Compatible content=ie=edge> <title>WeChat Voice</title> <link rel=stylesheet href=css/record.css></head><body> <div id=wrap> <header id=header> <div id=left> <i class=material-icons> chevron_left </i> WeChat(184) </div> <div id=mid>Aida·Wang</div > <div id=right> <i class=material-icons> more_horiz </i> </div> </header> <div id=contentWrap> <ul id=chatList> <li class=item_me> <div class=chatContent>Am I the person you love most? <span class=bot></span> <span class=top></span> </div> <div class=avatar > <img src=images/ava1.png </div> </li> <li class=item_you> <div class=avatar> <img src=images/ava2.jpg </div> <div class=chatContent>Run, brother! (Rolling calf) <span class=bot></span> <span class=top></span> </div> </li> <li class=item_me> <div class=chatContent>I won’t say much here Okay, here comes a bunch of code... <span class=bot></span> <span class=top></span> </div> <div class=avatar> <img src=images/ava1.png </div> </li> <li class=item_you> <div class=avatar> <img src=images/ava2.jpg </div> <div class=chatContent>Brother Dabin, why are you so good? ? I feel like the ocean when I see you<span class=bot></span> <span class=top></span> </div> </li> <li class=item_me> <div class=chatContent>Old girl Son, have you fallen in love with me... <span class=bot></span> <span class=top></span> </div> <div class=avatar> <img src=images/ava1.png </div> </li> <li class=item_you> <div class=avatar> <img src=images/ava2.jpg </div> <div class=chatContent>No, I am seasick. , I feel like vomiting when I see you... <span class=bot></span> <span class=top></span> </div> </li> </ul> </div> <footer id=footer> <div id=keyboard> <i class=material-icons> keyboard </i> </div> <div id=sayBtn> <span id=sendBtn class=sendBtn>Press to speak</span> < /div> <div id=icon><i class=material-icons> sentiment_satisfied </i></div> <div id=add><i class=material-icons> add_circle_outline </i></div> </footer> </div></body></html>
css part,
*{ margin: 0; padding: 0;}ul li{ list-style: none;}html,body{ height: 100%; width: 100%; overflow: hidden;}body{ background: #ebebeb;}@font -face { font-family: 'Material Icons'; font-style: normal; font-weight: 400; src: url(../css/iconfont/MaterialIcons-Regular.eot); /* For IE6-8 */ src: local('Material Icons'), local('MaterialIcons-Regular'), url(../css/ iconfont/MaterialIcons-Regular.woff) format('woff2'), url(../css/iconfont/MaterialIcons-Regular.woff2) format('woff'), url(../css/iconfont/MaterialIcons-Regular.ttf) format('truetype'); } .material-icons { font-family: 'Material Icons'; font-weight: normal; font-style: normal; font-size: 32px; /* Preferred icon size */ display: inline-block; /* line-height: 0.01rem; */ text-transform: none; letter-spacing: normal; word-wrap: normal; white-space: nowrap; direction: ltr; /* Support for all WebKit browsers. */ -webkit-font-smoothing: antialiased; /* Support for Safari and Chrome. */ text-rendering: optimizeLegibility; /* Support for Firefox. */ -moz-osx-font-smoothing: grayscale; /* Support for IE. */ font-feature-settings: 'liga'; }#wrap{ display: flex; flex-direction : column; justify-content: space-between; height: 100%;}#header{ height: 46px; line-height: 46px; background: #363539; display: flex; align-items: center; color: #fff; justify-content: space-between;}#header #left{ display: flex; align-items: center; font-size: 14px; width: 100px;}#header #right{ display: flex; align-items: center; width: 100px; justify-content: flex-end;}#header #right i{ padding-right: 6px;}#header #mid{ text-align: center; flex: 1;}#contentWrap{ flex: 1; overflow-y:auto;}.item_me,.item_audio{ display: flex; align-items : flex-start; justify-content:flex-end; padding: 8px;}.item_you{ display: flex; align-items: flex-start; justify-content:flex-start; padding: 8px;}.avatar{ width: 40px; height: 40px;}.avatar img{width: 100%;}.item_me .chatContent{ padding: 10px; background: #a0e75a; border : 1px solid #6fb44d; margin-right: 15px; border-radius: 5px; position: relative;}.chatContent span{width:0; height:0; font-size:0; overflow:hidden; position:absolute;}.item_me .chatContent span.bot{ border-width:8px; border- style:solid dashed dashed; border-color: transparent transparent transparent #6fb44d; right:-17px; top:10px;}.item_me .chatContent span.top{ border-width:8px; border-style:solid dashed dashed; border-color:transparent transparent #a0e75a ; right:-15px; top:10px;} .item_you .chatContent{ padding: 10px; background : #a0e75a; border: 1px solid #6fb44d; margin-left: 15px; border-radius: 5px; position: relative;} .item_you .chatContent span.bot{ border-width:8px; border-style:solid dashed dashed; border-color: transparent #6fb44d transparent transparent ; left:-17px; top:10px;}.item_you .chatContent span.top{ border-width:8px; border-style:solid dashed dashed; border-color:transparent #a0e75a transparent transparent ; left:-15px; top:10px;} #footer{ height: 46px; padding: 0 4px; background: #f4f5f6; border-top: 1px solid #d7d7d8; display : flex; align-items: center; color: #7f8389; justify-content: space-around;}#sayBtn{ flex: 1; display: flex; margin: 0 5px; color:#565656; font-weight: bold;}.sendBtn{ display: block; flex: 1; padding: 8px; background: #f4f5f6; border:1px solid #bec2c1; border-radius: 5px; text-align: center;}.activeBtn{ display: block; flex: 1; padding: 8px; background: #c6c7ca; border:1px solid #bec2c1; border-radius: 5px; text-align: center;}.item_audio .chatContent{ padding: 6px; background: #fff; border: 1px solid #999; border-radius: 5px; margin-right: 15px; position: relative; width:120px; min-height: 20px;}.item_audio .chatContent span.bot{ border-width:8px; border-style:solid dashed dashed; border-color: transparent transparent transparent #999; right:-17px; top:10px;}.item_audio .chatContent span.top{ border-width:8px; border-style:solid dashed dashed; border-color:transparent transparent transparent #fff ; right:-15px; top:10px;} .material-icons_wifi{ transform: rotate(90deg); color: #a5a5a5 ; font-size: 22px;}.redDot{ background: #f45454; border-radius: 50%; width: 8px; height: 8px; margin-right: 10px;}Here I would like to mention two points of attention:
1.html part:
To save trouble, I did not cut the image at pixel level. To save trouble, I directly used svg icons. The specific library I used is
https://material.io/tools/icons/?style=outline
2.css part: use flex layout. I just want to explain the Html5 function, so flex does not write the compatibility writing method. In addition, please pay attention to the writing method of the App header part, which is very commonly used.
Let’s talk about the key js part.
<!DOCTYPE html><html lang=en><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width, initial-scale=1.0> <meta http-equiv=X-UA -Compatible content=ie=edge> <title>WeChat Voice</title> <link rel=stylesheet href=css/record.css> <script> document.addEventListener('DOMContentLoaded', function () { var oSendBtn = document.getElementById('sendBtn'); var soundClips = document.querySelector('.sound-clips'); var mediaRecorder; var oChatList = document.getElementById(' chatList'); navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { navigator.mediaDevices.getUserMedia( // constraints - only audio needed for this app { audio: true }) // Success callback .then(function (stream) { rec(stream); }) // Error callback .catch(function (err) { } ); } else { } function rec(stream) { mediaRecorder = new MediaRecorder(stream); oSendBtn.addEventListener('touchstart ', function (ev) { ev.preventDefault(); this.innerHTML = 'Release to end'; this.classList.add('activeBtn'); mediaRecorder.start(); }, false); oSendBtn.addEventListener('touchend', function (ev) { ev.preventDefault(); this.innerHTML = 'Press to speak' ; this.classList.remove('activeBtn'); mediaRecorder.stop(); }, false); mediaRecorder.ondataavailable = function (e) { var clipContainer = document.createElement('li'); var audio = document.createElement('audio'); clipContainer.classList.add('item_audio'); clipContainer.innerHTML = ` <div class = redDot></div> <div class=chatContent> <i class=material-icons material-icons_wifi>wifi</i> <span class=bot></span> <span class=top></span> </div> <div class=avatar> <img src=images/ava1.png </div>`; audio.setAttribute('controls' , ''); oChatList.appendChild(clipContainer); var audioURL = window.URL.createObjectURL(e.data); audio.src = audioURL; oChatList.addEventListener('touchstart', function (ev) { if (ev.srcElement.parentNode.className!== 'item_audio') return; audio.play(); ev.srcElement.parentNode.removeChild(ev.srcElement.parentNode .children[0]) }, false); }; } }, false); </script></head><body> <div id=wrap> <header id=header> <div id=left> <i class=material-icons> chevron_left </i> WeChat(184) </div> <div id=mid>Aida·Wang</div > <div id=right> <i class=material-icons> more_horiz </i> </div> </header> <div id=contentWrap> <ul id=chatList> <li class=item_me> <div class=chatContent>Am I the person you love most? <span class=bot></span> <span class=top></span> </div> <div class=avatar > <img src=images/ava1.png </div> </li> <li class=item_you> <div class=avatar> <img src=images/ava2.jpg </div> <div class=chatContent>Run, brother! (Rolling calf) <span class=bot></span> <span class=top></span> </div> </li> <li class=item_me> <div class=chatContent>I won’t say much here Okay, here comes a bunch of code... <span class=bot></span> <span class=top></span> </div> <div class=avatar> <img src=images/ava1.png </div> </li> <li class=item_you> <div class=avatar> <img src=images/ava2.jpg </div> <div class=chatContent>Brother Dabin, why are you so good? ? I feel like the ocean when I see you<span class=bot></span> <span class=top></span> </div> </li> <li class=item_me> <div class=chatContent>Old girl Son, have you fallen in love with me... <span class=bot></span> <span class=top></span> </div> <div class=avatar> <img src=images/ava1.png </div> </li> <li class=item_you> <div class=avatar> <img src=images/ava2.jpg </div> <div class=chatContent>No, I am seasick. , I feel like vomiting when I see you... <span class=bot></span> <span class=top></span> </div> </li> </ul> </div> <footer id=footer> <div id=keyboard> <i class=material-icons> keyboard </i> </div> <div id=sayBtn> <span id=sendBtn class=sendBtn>Press to speak</span> < /div> <div id=icon><i class=material-icons> sentiment_satisfied </i></div> <div id=add><i class=material-icons> add_circle_outline </i></div> </footer> </div></body></html>
There are many points to pay attention to when implementing the video recording function here. Let’s talk about them one by one.
The first thing,
navigator.getUserMedia = (navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia); if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) { navigator.mediaDevices.getUserMedia( { audio: true }) // Success callback .then(function (stream) { rec(stream); }) // Error callback .catch(function (err) { } ); } else { }
When you look at some HTML5 interfaces for recording, you see this
Navigator.getUserMedia()
Be careful. This is an old standard and has been abolished. The new one is
navigator.mediaDevices.getUserMedia
The voice aspect in HTML5 multimedia has changed several times, and it is very messy. Some tags have not even been implemented in a browser, and they withered before they bloomed. You don't need to care and there is no need to waste that time. You just need to know what I say. These are enough, because you know that the abandoned past is of no use. If you have time, you might as well play a game of LOL or King of Glory (although I don’t understand the difference between the two, but these two games should be fun) Well, I’ve never played it so I don’t understand).
You don’t need to understand what’s inside. You don’t need to know what promises are and what media streams are. You just need to know this one thing.
The above code is equivalent to turning on the faucet (or pressing the record button of the recorder), then we have to have something to catch the water. We can use a rice cooker (or tape in the case of a recorder) to put it under the faucet and watch it go in. ci (meaning to shoot in our hometown), the following code
mediaRecorder = new MediaRecorder(stream);
The next step is to press the button and everything will be ready. The corresponding recorder means that after recording, press the button to play. However, in order to play in our program, you must not only have a tape, but also a recorder. The recorder is the audio tag. If there is nothing easy to do, we will create a new one. There are no objects in this world that programmers dare not new. If one new object is not enough, there are only two new ones. The rest of the code has no shortcomings other than being scary, it's simply outrageous.
mediaRecorder.ondataavailable = function (e) { var clipContainer = document.createElement('li'); var audio = document.createElement('audio'); clipContainer.classList.add('item_audio'); clipContainer.innerHTML = ` < div class = redDot></div> <div class=chatContent> <i class=material-icons material-icons_wifi>wifi</i> <span class=bot></span> <span class=top></span> </div> <div class=avatar> <img src=images/ava1.png </ div>`; audio.setAttribute('controls', ''); oChatList.appendChild(clipContainer); var audioURL = window.URL.createObjectURL(e.data); audio.src = audioURL; oChatList.addEventListener('touchstart', function (ev) { if (ev.srcElement.parentNode.className!== 'item_audio') return; audio. play(); ev.srcElement.parentNode.removeChild(ev.srcElement.parentNode.children[0]) }, false); };
In fact, it is recorded and broadcasted.
OK, is it very simple? Let me talk about a few points about the whole project:
1. Having a reasonable structure in the cutting diagram is the prerequisite for you to do the functions later. If the structure is well done, it will save trouble later. Think about Zhuge Liang, who built the HTML5 structure before he was just a fledgling. There are three sections.
2. A solid foundation of native js and ES6 can provide you with different ideas. For example, I use event delegation and the ES6 template engine here. Especially for event delegation, it would be troublesome to find nodes if not used. In addition, it would be easy to mess up the code if it is repeated.
3. New knowledge and technology are actually not complicated. In fact, they are very simple. If the new technology is not to make functions better and solve our problems, then why develop new technologies? Because those big guys with big beards are worried about being told by their bosses that their workload is not enough when they have nothing to do? Technology is there to solve problems and make our lives better.
4. This project will not work under IOS 11 or below, because this method is not supported before IOS 11.2, and you need IOS local application developers to provide support, but it is OK under Android. And it is foreseeable that in a few years IOS will be natively supported without providing you with support, so your development efficiency will be much higher. Don't think that these technologies are far away. HTML5 will only be commercially available for about 15 years (how many years will it take for vue, react, and angular to be used on a large scale?). Opportunities are reserved for those who are prepared.
There are still many details and points to pay attention to in the entire project. I hope you can really type it out yourself, because you understand my article and your ability to use this technology are two different things. I wish you all go further and further on the road to the front end (remember to come back often to read See ^_^).
SummarizeThe above is the editor's introduction to using Html5 multimedia to implement the WeChat voice function. I hope it will be helpful to you. If you have any questions, please leave me a message and the editor will reply to you in time. I would also like to thank everyone for your support of the VeVb martial arts website!
If you think this article is helpful to you, you are welcome to reprint it, please indicate the source, thank you!