{"id":2513,"date":"2018-04-04T22:08:20","date_gmt":"2018-04-04T22:08:20","guid":{"rendered":"https:\/\/www.gmass.co\/blog\/?p=2513"},"modified":"2018-04-05T03:17:43","modified_gmt":"2018-04-05T03:17:43","slug":"record-audio-mobile-web-page-ios-android","status":"publish","type":"post","link":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/","title":{"rendered":"How to record audio from a mobile web page on iOS and Android"},"content":{"rendered":"<p>People have been walking around with microphones in their pockets for years but only recently\u00a0has mobile browser support reached the level required to build a fully cross-platform, feature-rich, browser-based audio recorder. GMass&#8217;s sister product is <a href=\"http:\/\/www.wordzen.com\">Wordzen<\/a>, also an extension for Gmail, but with a completely different purpose &#8212; to write all of your emails for you. In the coming days, Wordzen will begin working inside the Gmail app on your mobile phone, and in order to achieve that, we had to figure out how to record audio from within the web browser on both iOS (iPhone) and Android.<\/p>\n<p>In this post, I&#8217;m going to detail the\u00a0key components of\u00a0our audio recorder and uploaded application. Keep reading, or <a href=\"https:\/\/www.gmass.co\/blog\/wp-content\/uploads\/2018\/03\/wzrecorder.zip\">download a simple demo<\/a>\u00a0now.\u00a0<img loading=\"lazy\" decoding=\"async\" class=\"wp-image-2515 alignright\" src=\"https:\/\/www.gmass.co\/blog\/wp-content\/uploads\/2018\/03\/wzrecorder-250x300.png\" alt=\"\" width=\"341\" height=\"409\" srcset=\"https:\/\/www.gmass.co\/blog\/wp-content\/uploads\/2018\/03\/wzrecorder-250x300.png 250w, https:\/\/www.gmass.co\/blog\/wp-content\/uploads\/2018\/03\/wzrecorder.png 584w\" sizes=\"auto, (max-width: 341px) 100vw, 341px\" \/><\/p>\n<p>The application needs to record audio, show visual feedback, allow playback, and finally, the audio needs to be uploadable to my server for transcribing.<\/p>\n<p>One of the newer APIs available is the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/MediaRecorder\">MediaRecorder API<\/a>. My first attempt at building this application started with this class. I implemented the entire application and it worked great on my desktop. It was easy to capture audio and the data was already compressed into .ogg format and ready to ship to my server. Then I tried it on iOS. It turns out that the MediaRecorder API is not supported and wouldn&#8217;t meet my needs. After\u00a0I stopped\u00a0cursing Apple, I began again from scratch.<\/p>\n<p>After searching unsuccessfully for a demo that worked on all platforms, I was about to give up but I did find multiple demos that worked on\u00a0individual platforms and so I set to combining what I&#8217;d learned into a single\u00a0class that would work on all platforms. Even after finding examples that worked on my iPhone, I still found my demo didn&#8217;t work because of the security built into iOS that requires that microphone actions can only be triggered via a click. That was the last piece of the puzzle that allowed me to construct a working demo and it revolves around three steps:<\/p>\n<ol>\n<li>Capture the microphone so we can begin recording<\/li>\n<li>Accumulate captured audio data into a series of byte array chunks<\/li>\n<li>Combine the chunks into one large array and massage\u00a0the array into the format of a .wav file<\/li>\n<\/ol>\n<h2>Step 1: Capture the microphone<\/h2>\n<p>Capturing the microphone revolves around creating an audio context and then asking the user for permission to use it. There are several <a href=\"https:\/\/stackoverflow.com\/questions\/6599815\/what-is-the-difference-between-a-shim-and-a-polyfill\">shims <\/a>involved to make this work in each platform so we have to look for what&#8217;s supported\u00a0to get the right instances:<\/p>\n<pre style=\"padding-left: 30px;\">audioCtx = new (window.AudioContext || window.webkitAudioContext)();\r\nif (audioCtx.createJavaScriptNode) {\r\n    audioNode = audioCtx.createJavaScriptNode(bufferSize, 1, 1);\r\n} else if (audioCtx.createScriptProcessor) {\r\n    audioNode = audioCtx.createScriptProcessor(bufferSize, 1, 1);\r\n} else {\r\n    throw 'WebAudio not supported!';\r\n}\r\naudioNode.connect(audioCtx.destination);\r\n\r\n<\/pre>\n<p>Once we&#8217;ve done the setup, we can then ask the browser to prompt the user for access to the microphone. The result of this call is a <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Promise\">promise <\/a>that we can use to trigger a callback\u00a0when it successfully completes:<\/p>\n<pre style=\"padding-left: 30px;\">navigator.mediaDevices.getUserMedia({audio: true})\r\n .then(onMicrophoneCaptured)\r\n .catch(onMicrophoneError);<\/pre>\n<p>Once the microphone has been captured, we can register to receive events about audio data coming in by listening to the <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/ScriptProcessorNode\/onaudioprocess\">onAudioProcess <\/a>event:<\/p>\n<pre style=\"padding-left: 30px;\">audioInput = audioCtx.createMediaStreamSource(microphone);\r\naudioInput.connect(audioNode);\r\naudioNode.onaudioprocess = onAudioProcess;<\/pre>\n<h2>Step 2: Accumulate captured audio<\/h2>\n<p>Although the audio process event returns multi-channel data, for our purposes, we only need one channel of audio data. This also\u00a0creates a smaller file that will make uploads faster. When data arrives. We can do this by simply getting\u00a0one channel&#8217;s data and adding it to our list of recorded data. This is also a good time to notify anybody listening that we&#8217;re still recording so we can show the current duration or other visualization:<\/p>\n<pre style=\"padding-left: 30px;\">recordedData.push(new Float32Array(e.inputBuffer.getChannelData(0)));\r\nself.duration = new Date().getTime() - self.startDate.getTime();\r\nconfig.onRecording &amp;&amp; config.onRecording(self.duration);<\/pre>\n<h2>Step 3: Massage the array into the format of a .wav file<\/h2>\n<p>Now that we have a large array of audio data &#8220;chunks&#8221;, we need to combine those chunks into a single array and generate a .wav file. Although we could do this synchronously, a\u00a0long recording could hang the user&#8217;s browser. To avoid this, we&#8217;ll offload the heavy lifting work to a <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Web_Workers_API\/Using_web_workers\">Web Worker<\/a>\u00a0that will return a <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/DataView\">DataView <\/a>that we can use to construct a <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Blob\">Blob <\/a>which can be played or uploaded.<\/p>\n<p>The first step of the .wav generation process is combining the chunks of data into a single <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Float64Array\">Float64Array<\/a>\u00a0which simply creating a large enough buffer and then setting the chunks into it, advancing the offset by the size of each chunk:<\/p>\n<pre style=\"padding-left: 30px;\">var result = new Float64Array(count);\r\nvar offset = 0;\r\nvar lng = channelBuffer.length;\r\n\r\nfor (var i = 0; i &lt; lng; i++) {\r\n\u00a0 \u00a0 var buffer = channelBuffer[i];\r\n\u00a0 \u00a0 result.set(buffer, offset);\r\n\u00a0 \u00a0 offset += buffer.length;\r\n }<\/pre>\n<p>Now that we have that complete list of bytes in one array, we can write the .wav file starting with the header and followed by the audio data bytes. To do this, I referred to the <a href=\"https:\/\/en.wikipedia.org\/wiki\/WAV#Specification\">.wav file format specification<\/a>. Because the data we&#8217;ve recorded is floating point and in the range of -0.5 to +0.5, we need to scale the values up to 16-bit signed integers. We can do that by multiplying each value of recorded data by 2^16 &#8211; 1 or 32,767 or 0x8000 &#8211; 1 or 0x7FFF:<\/p>\n<pre style=\"padding-left: 30px;\">for (var i = 0; i &lt; dataLength; i++) {\r\n\u00a0 \u00a0 view.setInt16(index, data[i] * 0x7FFF, true);\r\n\u00a0 \u00a0 index += 2;\r\n }<\/pre>\n<p>Now that we have all the data in a DataView, we can convert the view into a Blob:<\/p>\n<pre style=\"padding-left: 30px;\">blob = new Blob([view], { type: 'audio\/wav' });<\/pre>\n<p>And finally, we can play this blob in an &lt;audio&gt; tag:<\/p>\n<pre style=\"padding-left: 30px;\">document.getElementById('player').src = URL.createObjectURL(blob);<\/pre>\n<p>or pass it to the excellent <a href=\"https:\/\/wavesurfer-js.org\/\">wavesufer plugin<\/a> to visualize it or play it:<\/p>\n<pre style=\"padding-left: 30px;\">wavesurfer = WaveSurfer.create({\r\n\u00a0 \u00a0 container: '#waveform',\r\n\u00a0 \u00a0 waveColor: '#007BFF',\r\n\u00a0 \u00a0 progressColor: '#03A8F3'\r\n });\r\nwavesurfer.loadBlob(blob);<\/pre>\n<h2>Step 4:\u00a0Add an Oscilloscope (optional)<\/h2>\n<p>It&#8217;s always nice to give the user a bit of feedback and we can do that by converting the audio data into a waveform that they can see while they&#8217;re speaking:<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-2518\" src=\"https:\/\/www.gmass.co\/blog\/wp-content\/uploads\/2018\/03\/oscilloscope-300x54.png\" alt=\"\" width=\"300\" height=\"54\" srcset=\"https:\/\/www.gmass.co\/blog\/wp-content\/uploads\/2018\/03\/oscilloscope-300x54.png 300w, https:\/\/www.gmass.co\/blog\/wp-content\/uploads\/2018\/03\/oscilloscope.png 562w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><br \/>\nThis visualization is simply a line drawn over a series of points. We can get those points from our data and scale them to fit the width and height of a <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/HTML\/Element\/canvas\">Canvas <\/a>element. The audio context class allows us to connect an <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/AnalyserNode\">analyzer <\/a>and extract <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/AnalyserNode\/getByteTimeDomainData\">byte time data<\/a> from it:<\/p>\n<pre style=\"padding-left: 30px;\">var analyser = audioCtx.createAnalyser();\r\nanalyser.fftSize = 2048;\r\nvar bufferLength = analyser.frequencyBinCount;\r\nvar dataArray = new Uint8Array(bufferLength);\r\nsource.connect(analyser);\r\nanalyser.getByteTimeDomainData(dataArray);\r\n<\/pre>\n<p>The byte time data is an array of signed byte values ranging from -128 to +127. By scaling these values to the height of the canvas, we can <a href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/CanvasRenderingContext2D\/stroke\">stroke <\/a>a path to create a wave form.<\/p>\n<pre style=\"padding-left: 30px;\">for (var i = 0; i &lt; bufferLength; i++) {\r\n\u00a0 \u00a0 var v = dataArray[i] \/ 128.0;\r\n\u00a0 \u00a0 var y = v * height \/ 2;\r\n\u00a0 \u00a0 i == 0 ? canvasCtx.moveTo(x, y) : canvasCtx.lineTo(x, y);\r\n\u00a0 \u00a0 x += sliceWidth;\r\n}\r\ncanvasCtx.lineTo(canvas.width, canvas.height\/2);\r\ncanvasCtx.stroke();<\/pre>\n","protected":false},"excerpt":{"rendered":"<p>People have been walking around with microphones in their pockets for years but only recently\u00a0has mobile browser support reached the level required to build a fully cross-platform, feature-rich,\u2026<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[3462],"tags":[],"class_list":["post-2513","post","type-post","status-publish","format-standard","hentry","category-developers"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v28.3 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\r\n<title>How to record audio from a mobile web page on iOS and Android<\/title>\r\n<meta name=\"description\" content=\"Building a web page that can record audio on both the iPhone (iOS) and Android isn&#039;t easy. In this article I&#039;ll show you how I did it.\" \/>\r\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\r\n<link rel=\"canonical\" href=\"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/\" \/>\r\n<meta property=\"og:locale\" content=\"en_US\" \/>\r\n<meta property=\"og:type\" content=\"article\" \/>\r\n<meta property=\"og:title\" content=\"How to record audio from a mobile web page on iOS and Android\" \/>\r\n<meta property=\"og:description\" content=\"Building a web page that can record audio on both the iPhone (iOS) and Android isn&#039;t easy. In this article I&#039;ll show you how I did it.\" \/>\r\n<meta property=\"og:url\" content=\"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/\" \/>\r\n<meta property=\"og:site_name\" content=\"GMass Blog\" \/>\r\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/GmailMailMerge\/\" \/>\r\n<meta property=\"article:published_time\" content=\"2018-04-04T22:08:20+00:00\" \/>\r\n<meta property=\"article:modified_time\" content=\"2018-04-05T03:17:43+00:00\" \/>\r\n<meta property=\"og:image\" content=\"https:\/\/www.gmass.co\/blog\/wp-content\/uploads\/2018\/03\/wzrecorder-250x300.png\" \/>\r\n<meta name=\"author\" content=\"Ajay Goel\" \/>\r\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\r\n<meta name=\"twitter:creator\" content=\"@PartTimeSnob\" \/>\r\n<meta name=\"twitter:site\" content=\"@GMassForGmail\" \/>\r\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ajay Goel\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\r\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/record-audio-mobile-web-page-ios-android\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/record-audio-mobile-web-page-ios-android\\\/\"},\"author\":{\"name\":\"Ajay Goel\",\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/#\\\/schema\\\/person\\\/b5fa74f8765b860701158fd77162fff8\"},\"headline\":\"How to record audio from a mobile web page on iOS and Android\",\"datePublished\":\"2018-04-04T22:08:20+00:00\",\"dateModified\":\"2018-04-05T03:17:43+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/record-audio-mobile-web-page-ios-android\\\/\"},\"wordCount\":970,\"commentCount\":23,\"image\":{\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/record-audio-mobile-web-page-ios-android\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/wp-content\\\/uploads\\\/2018\\\/03\\\/wzrecorder-250x300.png\",\"articleSection\":[\"Developers\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.gmass.co\\\/blog\\\/record-audio-mobile-web-page-ios-android\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/record-audio-mobile-web-page-ios-android\\\/\",\"url\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/record-audio-mobile-web-page-ios-android\\\/\",\"name\":\"How to record audio from a mobile web page on iOS and Android\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/record-audio-mobile-web-page-ios-android\\\/#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/record-audio-mobile-web-page-ios-android\\\/#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/wp-content\\\/uploads\\\/2018\\\/03\\\/wzrecorder-250x300.png\",\"datePublished\":\"2018-04-04T22:08:20+00:00\",\"dateModified\":\"2018-04-05T03:17:43+00:00\",\"author\":{\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/#\\\/schema\\\/person\\\/b5fa74f8765b860701158fd77162fff8\"},\"description\":\"Building a web page that can record audio on both the iPhone (iOS) and Android isn't easy. In this article I'll show you how I did it.\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/record-audio-mobile-web-page-ios-android\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.gmass.co\\\/blog\\\/record-audio-mobile-web-page-ios-android\\\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/record-audio-mobile-web-page-ios-android\\\/#primaryimage\",\"url\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/wp-content\\\/uploads\\\/2018\\\/03\\\/wzrecorder-250x300.png\",\"contentUrl\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/wp-content\\\/uploads\\\/2018\\\/03\\\/wzrecorder-250x300.png\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/record-audio-mobile-web-page-ios-android\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"How to record audio from a mobile web page on iOS and Android\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/#website\",\"url\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/\",\"name\":\"GMass Blog\",\"description\":\"Tips and tricks for sending mail merge and mass email campaigns directly from Gmail\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/#\\\/schema\\\/person\\\/b5fa74f8765b860701158fd77162fff8\",\"name\":\"Ajay Goel\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f3a70af05bbabe47925150d5a1320540e801b78055a74da20658fc97cd0706a2?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f3a70af05bbabe47925150d5a1320540e801b78055a74da20658fc97cd0706a2?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f3a70af05bbabe47925150d5a1320540e801b78055a74da20658fc97cd0706a2?s=96&d=mm&r=g\",\"caption\":\"Ajay Goel\"},\"description\":\"Ajay is the founder of GMass and has been developing email sending software for 20 years.\",\"sameAs\":[\"https:\\\/\\\/twitter.com\\\/PartTimeSnob\",\"https:\\\/\\\/x.com\\\/PartTimeSnob\"],\"url\":\"https:\\\/\\\/www.gmass.co\\\/blog\\\/author\\\/ajay-goel\\\/\"}]}<\/script>\r\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"How to record audio from a mobile web page on iOS and Android","description":"Building a web page that can record audio on both the iPhone (iOS) and Android isn't easy. In this article I'll show you how I did it.","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/","og_locale":"en_US","og_type":"article","og_title":"How to record audio from a mobile web page on iOS and Android","og_description":"Building a web page that can record audio on both the iPhone (iOS) and Android isn't easy. In this article I'll show you how I did it.","og_url":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/","og_site_name":"GMass Blog","article_publisher":"https:\/\/www.facebook.com\/GmailMailMerge\/","article_published_time":"2018-04-04T22:08:20+00:00","article_modified_time":"2018-04-05T03:17:43+00:00","og_image":[{"url":"https:\/\/www.gmass.co\/blog\/wp-content\/uploads\/2018\/03\/wzrecorder-250x300.png","type":"","width":"","height":""}],"author":"Ajay Goel","twitter_card":"summary_large_image","twitter_creator":"@PartTimeSnob","twitter_site":"@GMassForGmail","twitter_misc":{"Written by":"Ajay Goel","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/#article","isPartOf":{"@id":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/"},"author":{"name":"Ajay Goel","@id":"https:\/\/www.gmass.co\/blog\/#\/schema\/person\/b5fa74f8765b860701158fd77162fff8"},"headline":"How to record audio from a mobile web page on iOS and Android","datePublished":"2018-04-04T22:08:20+00:00","dateModified":"2018-04-05T03:17:43+00:00","mainEntityOfPage":{"@id":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/"},"wordCount":970,"commentCount":23,"image":{"@id":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/#primaryimage"},"thumbnailUrl":"https:\/\/www.gmass.co\/blog\/wp-content\/uploads\/2018\/03\/wzrecorder-250x300.png","articleSection":["Developers"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/","url":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/","name":"How to record audio from a mobile web page on iOS and Android","isPartOf":{"@id":"https:\/\/www.gmass.co\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/#primaryimage"},"image":{"@id":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/#primaryimage"},"thumbnailUrl":"https:\/\/www.gmass.co\/blog\/wp-content\/uploads\/2018\/03\/wzrecorder-250x300.png","datePublished":"2018-04-04T22:08:20+00:00","dateModified":"2018-04-05T03:17:43+00:00","author":{"@id":"https:\/\/www.gmass.co\/blog\/#\/schema\/person\/b5fa74f8765b860701158fd77162fff8"},"description":"Building a web page that can record audio on both the iPhone (iOS) and Android isn't easy. In this article I'll show you how I did it.","breadcrumb":{"@id":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/#primaryimage","url":"https:\/\/www.gmass.co\/blog\/wp-content\/uploads\/2018\/03\/wzrecorder-250x300.png","contentUrl":"https:\/\/www.gmass.co\/blog\/wp-content\/uploads\/2018\/03\/wzrecorder-250x300.png"},{"@type":"BreadcrumbList","@id":"https:\/\/www.gmass.co\/blog\/record-audio-mobile-web-page-ios-android\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.gmass.co\/blog\/"},{"@type":"ListItem","position":2,"name":"How to record audio from a mobile web page on iOS and Android"}]},{"@type":"WebSite","@id":"https:\/\/www.gmass.co\/blog\/#website","url":"https:\/\/www.gmass.co\/blog\/","name":"GMass Blog","description":"Tips and tricks for sending mail merge and mass email campaigns directly from Gmail","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.gmass.co\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/www.gmass.co\/blog\/#\/schema\/person\/b5fa74f8765b860701158fd77162fff8","name":"Ajay Goel","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f3a70af05bbabe47925150d5a1320540e801b78055a74da20658fc97cd0706a2?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f3a70af05bbabe47925150d5a1320540e801b78055a74da20658fc97cd0706a2?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f3a70af05bbabe47925150d5a1320540e801b78055a74da20658fc97cd0706a2?s=96&d=mm&r=g","caption":"Ajay Goel"},"description":"Ajay is the founder of GMass and has been developing email sending software for 20 years.","sameAs":["https:\/\/twitter.com\/PartTimeSnob","https:\/\/x.com\/PartTimeSnob"],"url":"https:\/\/www.gmass.co\/blog\/author\/ajay-goel\/"}]}},"_links":{"self":[{"href":"https:\/\/www.gmass.co\/blog\/wp-json\/wp\/v2\/posts\/2513","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.gmass.co\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.gmass.co\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.gmass.co\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/www.gmass.co\/blog\/wp-json\/wp\/v2\/comments?post=2513"}],"version-history":[{"count":5,"href":"https:\/\/www.gmass.co\/blog\/wp-json\/wp\/v2\/posts\/2513\/revisions"}],"predecessor-version":[{"id":2633,"href":"https:\/\/www.gmass.co\/blog\/wp-json\/wp\/v2\/posts\/2513\/revisions\/2633"}],"wp:attachment":[{"href":"https:\/\/www.gmass.co\/blog\/wp-json\/wp\/v2\/media?parent=2513"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.gmass.co\/blog\/wp-json\/wp\/v2\/categories?post=2513"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.gmass.co\/blog\/wp-json\/wp\/v2\/tags?post=2513"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}