{"id":28225,"date":"2022-07-26T09:16:32","date_gmt":"2022-07-26T09:16:32","guid":{"rendered":"http:\/\/video-transcription-using-cloudinary"},"modified":"2022-07-26T09:16:32","modified_gmt":"2022-07-26T09:16:32","slug":"video-transcription-using-cloudinary","status":"publish","type":"post","link":"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/","title":{"rendered":"Video Transcription Using Cloudinary"},"content":{"rendered":"<div class=\"wp-block-cloudinary-markdown \"><p>Accessibility is one of the most important parts of the modern web. That is why we are using transcriptions to enhance the usability of video files online. Transcriptions are one of the most accessible ways to deliver video content as it caters to the challenges of a wide variety of web users. In this post, we\u2019ll look at how to add transcriptions to videos rendered in a Nextjs application with Cloudinary.<\/p>\n<p>In the end, we\u2019ll create a web application that uses the Cloudinary API to transcribe a user-uploaded video and returns a downloadable URL of the transcribed video.<\/p>\n<p>The Cloudinary API uses a Google-Speech-AI add-on to generate a subtitle file for the uploaded video, and then we will add a transformation that overlays this subtitle on the given video.<\/p>\n<h2>Prerequisites<\/h2>\n<p>To follow along with this tutorial, you will need to have,\n\u2014 A free Cloudinary account.\n\u2014 Experience with JavaScript and React.js\n\u2014 Next.js is not a requirement, but it\u2019s good to have.<\/p>\n<h2>Sandbox<\/h2>\n<p>If you\u2019d like to get a headstart by looking at the finished demo, I\u2019ve got it set up here on Codesandbox for you!<\/p>\n<p>We completed this project in this sandbox.<\/p>\n<blockquote>\n<p>To test successfully with this demo, ensure that you upload a video size &lt;1MB<\/p>\n<\/blockquote>\n<\/div>\n  \n  <div class=\"wp-block-cloudinary-code-sandbox \">\n    <iframe\n      src=\"https:\/\/codesandbox.io\/embed\/elegant-fast-k2dsft?theme=dark&amp;codemirror=1&amp;highlights=&amp;editorsize=50&amp;fontsize=14&amp;expanddevtools=0&amp;hidedevtools=0&amp;eslint=0&amp;forcerefresh=0&amp;hidenavigation=0&amp;initialpath=%2F&amp;module=&amp;moduleview=0&amp;previewwindow=&amp;view=&amp;runonclick=1\"\n      height=\"500\"\n      style=\"width: 100%;\"\n      title=\"Video Transcription with Cloudinary &amp; Next.js\"\n      loading=\"lazy\"\n      allow=\"accelerometer; ambient-light-sensor; camera; encrypted-media; geolocation; gyroscope; hid; microphone; midi; payment; usb; vr; xr-spatial-tracking\"\n      sandbox=\"allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts\"\n    ><\/iframe>\n  <\/div>\n\n  <div class=\"wp-block-cloudinary-markdown \"><p>Fork and run it to quickly get started.<\/p>\n<p><a href=\"https:\/\/codesandbox.io\/embed\/dawn-fast-qt9enh?fontsize=14&amp;hidenavigation=1&amp;theme=dark\">https:\/\/codesandbox.io\/embed\/dawn-fast-qt9enh?fontsize=14&amp;hidenavigation=1&amp;theme=dark<\/a><\/p>\n<h2>Setup and Installations<\/h2>\n<p>First, we will create a Next.js boilerplate with the following command:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">npx create-next-app video-transcription\n<\/code><\/span><\/pre>\n<p>Let\u2019s navigate to the root folder and install Netlify-CLI with the following command:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">cd video-transcription\n<\/code><\/span><\/pre>\n<p>Next, install the following packages:<\/p>\n<ul>\n<li>\n<p><strong>Cloudinary<\/strong> \u2014 a NodeJS SDK to interact with the Cloudinary APIs<\/p>\n<\/li>\n<li>\n<p><strong>File saver<\/strong> \u2014 to help us save our transcribed video<\/p>\n<\/li>\n<li>\n<p><strong>Axios<\/strong> \u2014 to carry out HTTP requests.<\/p>\n<\/li>\n<li>\n<p><strong>Dotenv<\/strong> \u2014 to store our API keys safely.<\/p>\n<\/li>\n<\/ul>\n<p>The following command will install all the above packages<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">npm i cloudinary file-saver axios dotenv\n<\/code><\/span><\/pre>\n<h2>Setup Cloudinary transcription Add-on<\/h2>\n<p>To enable the transcription feature on Cloudinary, we need to follow the process shown below:<\/p>\n<p>Navigate to the <strong>Add-ons<\/strong> tab on your Cloudinary account and select the <strong>Google AI Video Transcription<\/strong> add-on.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_2E53E31A00FF445ED2F7D150ACA625F82B06B8300A79B7F7FE37E2A99B2A68A3_1658117313780_process12.png\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1164\" height=\"768\"\/><\/p>\n<p>Next, select the free plan that offers 120 monthly units. For a more broad project, you should probably select a paid plan with more units, but this will be sufficient for our demo.<\/p>\n<p><img decoding=\"async\" src=\"https:\/\/cloudinary-marketing-res.cloudinary.com\/image\/upload\/c_limit,w_2000\/f_auto\/q_auto\/media_jams\/s_2E53E31A00FF445ED2F7D150ACA625F82B06B8300A79B7F7FE37E2A99B2A68A3_1658117306350_process3.png\" alt=\"\" loading=\"lazy\" class=\"c-transformed-asset\"  width=\"1189\" height=\"701\"\/><\/p>\n<p>Navigate back into the project folder and start the development server with the command below:<\/p>\n<pre class=\"js-syntax-highlighted\"><span><code class=\"hljs shcb-wrap-lines\">npm run dev\n<\/code><\/span><\/pre>\n<p>The above command starts a development server at <a href=\"http:\/\/localost:3000\">http:\/\/localost:3000<\/a>. You can check that port on the browser to see our demo app running. Next, create a <code>transacribe.js<\/code>  file in our <code>pages\/api<\/code> folder. Then we add the following snippet to it:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-1\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">const<\/span> multiparty = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">\"multiparty\"<\/span>);\n<span class=\"hljs-keyword\">const<\/span> Cloudinary = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">\"cloudinary\"<\/span>).v2;\n<span class=\"hljs-keyword\">const<\/span> pth = <span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">\"path\"<\/span>);\n<span class=\"hljs-built_in\">require<\/span>(<span class=\"hljs-string\">\"dotenv\"<\/span>).config();\n\n<span class=\"hljs-keyword\">const<\/span> uploadVideo = <span class=\"hljs-keyword\">async<\/span> (req, res) =&gt; {\n  <span class=\"hljs-keyword\">const<\/span> form = <span class=\"hljs-keyword\">new<\/span> multiparty.Form();\n  <span class=\"hljs-keyword\">const<\/span> data = <span class=\"hljs-keyword\">await<\/span> <span class=\"hljs-keyword\">new<\/span> <span class=\"hljs-built_in\">Promise<\/span>(<span class=\"hljs-function\">(<span class=\"hljs-params\">resolve, reject<\/span>) =&gt;<\/span> {\n    form.parse(req, <span class=\"hljs-keyword\">async<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\">err, fields, files<\/span>) <\/span>{\n      <span class=\"hljs-keyword\">if<\/span> (err) reject({ err });\n      <span class=\"hljs-keyword\">const<\/span> path = files.video&#91;<span class=\"hljs-number\">0<\/span>].path;\n      <span class=\"hljs-keyword\">const<\/span> filename = pth.parse(files.video&#91;<span class=\"hljs-number\">0<\/span>].originalFilename).name;\n\n     <span class=\"hljs-comment\">\/\/ config Cloudinary<\/span>\n     \n     <span class=\"hljs-comment\">\/\/ rest of the code here<\/span>\n      } <span class=\"hljs-keyword\">catch<\/span> (error) {\n        <span class=\"hljs-built_in\">console<\/span>.log(error);\n      }\n    });\n  });\n\n  res.status(<span class=\"hljs-number\">200<\/span>).json({ <span class=\"hljs-attr\">success<\/span>: <span class=\"hljs-literal\">true<\/span>, data });\n};\n\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> uploadVideo;\n\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-1\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>Here, we define a <code>uploadVideo()<\/code> function that first accepts the video file coming from the client. Next, we parse the video<\/p>\n<p>In the snippet above, we:<\/p>\n<ul>\n<li>Import <code>Cloudinary<\/code> and other necessary packages.<\/li>\n<li>Create an <code>uploadVideo()<\/code> function to receive the video file from the client<\/li>\n<li>Parse the request data with multiparty to retrieve the video\u2019s <code>path<\/code> and <code>filename<\/code>.<\/li>\n<\/ul>\n<p>Next, we need to upload the retrieved video file to Cloudinary and transcribe using the Cloudinary Video Transcription Add-on we added.<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-2\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-comment\">\/\/src\/pages\/api\/transcribe.js<\/span>\n<span class=\"hljs-keyword\">try<\/span> {\nCloudinary.config({\n  <span class=\"hljs-attr\">cloud_name<\/span>: process.env.CLOUD_NAME,\n  <span class=\"hljs-attr\">api_key<\/span>: process.env.API_KEY,\n  <span class=\"hljs-attr\">api_secret<\/span>: process.env.API_SECRET,\n  <span class=\"hljs-attr\">secure<\/span>: <span class=\"hljs-literal\">true<\/span>\n});\n\n<span class=\"hljs-keyword\">const<\/span> VideoTranscribe = Cloudinary.uploader.upload(\n  path,\n  {\n    <span class=\"hljs-attr\">resource_type<\/span>: <span class=\"hljs-string\">\"video\"<\/span>,\n    <span class=\"hljs-attr\">public_id<\/span>: <span class=\"hljs-string\">`videos\/<span class=\"hljs-subst\">${filename}<\/span>`<\/span>,\n    <span class=\"hljs-attr\">raw_convert<\/span>: <span class=\"hljs-string\">\"google_speech:srt\"<\/span>\n  },\n  <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> (<span class=\"hljs-params\">error, result<\/span>) <\/span>{\n    <span class=\"hljs-keyword\">if<\/span> (result) {\n      <span class=\"hljs-keyword\">return<\/span> result;\n    }\n    <span class=\"hljs-keyword\">return<\/span> error;\n  }\n);\n\n<span class=\"hljs-keyword\">let<\/span> { public_id } = <span class=\"hljs-keyword\">await<\/span> VideoTranscribe;\n\n<span class=\"hljs-keyword\">const<\/span> transcribedVideo = Cloudinary.url(<span class=\"hljs-string\">`<span class=\"hljs-subst\">${public_id}<\/span>`<\/span>, {\n  <span class=\"hljs-attr\">resource_type<\/span>: <span class=\"hljs-string\">\"video\"<\/span>,\n  <span class=\"hljs-attr\">fallback_content<\/span>: <span class=\"hljs-string\">\"Your browser does not support HTML5 video tags\"<\/span>,\n  <span class=\"hljs-attr\">transformation<\/span>: &#91;\n    {\n      <span class=\"hljs-attr\">overlay<\/span>: {\n        <span class=\"hljs-attr\">resource_type<\/span>: <span class=\"hljs-string\">\"subtitles\"<\/span>,\n        <span class=\"hljs-attr\">public_id<\/span>: <span class=\"hljs-string\">`<span class=\"hljs-subst\">${public_id}<\/span>.srt`<\/span>\n      }\n    }\n  ]\n});\nresolve({ transcribedVideo });\n} <span class=\"hljs-keyword\">catch<\/span> (error) {\n<span class=\"hljs-built_in\">console<\/span>.log(error);\n}\n\nIn the snippet above, we <span class=\"hljs-keyword\">set<\/span> up a Cloudinary instance to enable communications between our Next.js project and our Cloudinary account. Next, we upload the video to Cloudinary, transcribe it and return the result (the transcribed video). Lastly, we destructure the `public_id` of the transcribed video and use it to fetch the transcribed video. Afterwards, we simply add a Cloudinary transformation that overlays the subtitle on the video thereby achieving a complete video transcription functionality for the originally uploaded video.\n\n&gt; **Note**: The Cloudinary Video Transcription feature can only be triggered during an `upload` or `update` call. \n&gt; Also, each 15s video you transcribe takes 1 unit from your allocated 120 units in the free plan.\n\nWith this, we are finished with our transcription logic.\n\nNext, let's implement the frontend aspect of this application. For this part, we will be creating a JSX form with an input field of type *file*, and a submit button.\nNavigate to the `index.js` file in the `pages` folder and add the following code:\n\n```js\n\/\/ pages\/index.js\nimport Head from 'next\/head'\nimport axios from 'axios'\nimport { useState } <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'react'<\/span>\n<span class=\"hljs-keyword\">import<\/span> {saveAs} <span class=\"hljs-keyword\">from<\/span> <span class=\"hljs-string\">'file-saver'<\/span>\n<span class=\"hljs-keyword\">export<\/span> <span class=\"hljs-keyword\">default<\/span> <span class=\"hljs-function\"><span class=\"hljs-keyword\">function<\/span> <span class=\"hljs-title\">Home<\/span>(<span class=\"hljs-params\"><\/span>) <\/span>{\n  <span class=\"hljs-keyword\">const<\/span> &#91;selected, setSelected] = useState(<span class=\"hljs-literal\">null<\/span>)\n  <span class=\"hljs-keyword\">const<\/span> &#91;videoUrl, setVideoUrl] = useState(<span class=\"hljs-string\">''<\/span>)\n  <span class=\"hljs-keyword\">const<\/span> &#91;downloaded, setDownloaded] = useState(<span class=\"hljs-literal\">false<\/span>)\n  \n  <span class=\"hljs-keyword\">const<\/span> handleChange = <span class=\"hljs-function\">(<span class=\"hljs-params\">e<\/span>) =&gt;<\/span> {\n    <span class=\"hljs-keyword\">if<\/span> (e.target.files &amp;&amp; e.target.files&#91;<span class=\"hljs-number\">0<\/span>]) {\n      <span class=\"hljs-keyword\">const<\/span> i = e.target.files&#91;<span class=\"hljs-number\">0<\/span>];\n      <span class=\"hljs-keyword\">let<\/span> reader = <span class=\"hljs-keyword\">new<\/span> FileReader()\n      reader.onload = <span class=\"hljs-function\"><span class=\"hljs-params\">()<\/span> =&gt;<\/span> {\n        <span class=\"hljs-keyword\">let<\/span> base64String = reader.result\n        setSelected(base64String)\n      }\n      reader.readAsDataURL(i)\n    }\n  }\n  \n  <span class=\"hljs-keyword\">const<\/span> handleSubmit = <span class=\"hljs-keyword\">async<\/span>(e) =&gt; {\n    e.preventDefault()\n    <span class=\"hljs-keyword\">try<\/span> {\n      <span class=\"hljs-keyword\">const<\/span> body = <span class=\"hljs-built_in\">JSON<\/span>.stringify(selected)\n      <span class=\"hljs-keyword\">const<\/span> config = {\n        <span class=\"hljs-attr\">headers<\/span>: {\n          <span class=\"hljs-string\">\"Content-Type\"<\/span>: <span class=\"hljs-string\">\"application\/json\"<\/span>\n        }\n      };\n      <span class=\"hljs-keyword\">const<\/span> response = <span class=\"hljs-keyword\">await<\/span> axios.post(<span class=\"hljs-string\">'\/transcribe'<\/span>, body, config)\n      <span class=\"hljs-keyword\">const<\/span> { data } = <span class=\"hljs-keyword\">await<\/span> response.data\n      setVideoUrl(data)\n    } <span class=\"hljs-keyword\">catch<\/span> (error) {\n      <span class=\"hljs-built_in\">console<\/span>.error(error);\n    }\n  }\n  <span class=\"hljs-comment\">\/\/ return statement return ()<\/span>\n}\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-2\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>In the snippet above, we\u2019ve set up the <code>handleChange()<\/code> and <code>handleSubmit()<\/code> functions to handle the interaction and submission of our form. Ideally, you can click on the <strong>Choose file<\/strong> button to select a video from your local filesystem, and the <strong>Upload video<\/strong> button to submit the selected video to our Next.js <code>\/transcribe<\/code> API route for transcription.<\/p>\n<p>Next, let\u2019s set up the return statement of our <code>index.js<\/code> file to render the JSX form for choosing and uploading videos for transcription:<\/p>\n<pre class=\"js-syntax-highlighted\" aria-describedby=\"shcb-language-3\" data-shcb-language-name=\"JavaScript\" data-shcb-language-slug=\"javascript\"><span><code class=\"hljs language-javascript shcb-wrap-lines\"><span class=\"hljs-keyword\">return<\/span> (\n<span class=\"xml\"><span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">title<\/span>&gt;<\/span>Create Next App<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">title<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">meta<\/span> <span class=\"hljs-attr\">name<\/span>=<span class=\"hljs-string\">\"description\"<\/span> <span class=\"hljs-attr\">content<\/span>=<span class=\"hljs-string\">\"Generated by create next app\"<\/span> \/&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">link<\/span> <span class=\"hljs-attr\">rel<\/span>=<span class=\"hljs-string\">\"icon\"<\/span> <span class=\"hljs-attr\">href<\/span>=<span class=\"hljs-string\">\"\/favicon.ico\"<\/span> \/&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">Head<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">header<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n    Video transcription with Cloudinary\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">h1<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">header<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">form<\/span> <span class=\"hljs-attr\">onSubmit<\/span>=<span class=\"hljs-string\">{handleSubmit}<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">span<\/span>&gt;<\/span>Choose your video file<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">span<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">input<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">\"file\"<\/span> <span class=\"hljs-attr\">onChange<\/span>=<span class=\"hljs-string\">{handleChange}<\/span> <span class=\"hljs-attr\">required<\/span> \/&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">label<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">'submit'<\/span>&gt;<\/span>Upload<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n      <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">form<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">section<\/span> <span class=\"hljs-attr\">id<\/span>=<span class=\"hljs-string\">\"video-output\"<\/span>&gt;<\/span>\n      {\n        videoUrl? \n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span> &gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">video<\/span> <span class=\"hljs-attr\">controls<\/span> <span class=\"hljs-attr\">width<\/span>=<span class=\"hljs-string\">{480}<\/span>&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">source<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{<\/span>`${<span class=\"hljs-attr\">videoUrl<\/span>}<span class=\"hljs-attr\">.webm<\/span>`} <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">'video\/webm'<\/span>\/&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">source<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{<\/span>`${<span class=\"hljs-attr\">videoUrl<\/span>}<span class=\"hljs-attr\">.mp4<\/span>`} <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">'video\/mp4'<\/span>\/&gt;<\/span>\n              <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">source<\/span> <span class=\"hljs-attr\">src<\/span>=<span class=\"hljs-string\">{<\/span>`${<span class=\"hljs-attr\">videoUrl<\/span>}<span class=\"hljs-attr\">.ogv<\/span>`} <span class=\"hljs-attr\">type<\/span>=<span class=\"hljs-string\">'video\/ogg'<\/span>\/&gt;<\/span>\n            <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">video<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span>\n          <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">button<\/span> \n          <span class=\"hljs-attr\">onClick<\/span>=<span class=\"hljs-string\">{()<\/span> =&gt;<\/span> { \n          saveAs(videoUrl, \"transcribed-video\"); \n          setDownloaded(true)}}\n          disabled={downloaded? true: false}&gt;\n            {downloaded? 'Downloaded': 'Download'}\n          <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">button<\/span>&gt;<\/span>\n        <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span> : \n        <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">p<\/span>&gt;<\/span>Please Upload a Video file to be Transcribed<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">p<\/span>&gt;<\/span>\n      }\n    <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">section<\/span>&gt;<\/span>\n  <span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">main<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">div<\/span>&gt;<\/span><\/span>\n)\n<\/code><\/span><small class=\"shcb-language\" id=\"shcb-language-3\"><span class=\"shcb-language__label\">Code language:<\/span> <span class=\"shcb-language__name\">JavaScript<\/span> <span class=\"shcb-language__paren\">(<\/span><span class=\"shcb-language__slug\">javascript<\/span><span class=\"shcb-language__paren\">)<\/span><\/small><\/pre>\n<p>And with that, we should be able to upload and transcribe videos. As a bonus, I\u2019ve added a couple more functionalities to allow you to download the transcribed video for local use. If you enjoyed this, be sure to come back for more as I look forward to all the things you\u2019ll do with this feature.<\/p>\n<\/div>","protected":false},"excerpt":{"rendered":"","protected":false},"author":41,"featured_media":28226,"comment_status":"","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"_cloudinary_featured_overwrite":false,"footnotes":""},"categories":[1],"tags":[134,212,403,371],"class_list":["post-28225","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-uncategorized","tag-guest-post","tag-next-js","tag-transcriptions","tag-under-review"],"acf":[],"yoast_head":"<!-- This site is optimized with the Yoast SEO Premium plugin v25.6 (Yoast SEO v26.9) - https:\/\/yoast.com\/product\/yoast-seo-premium-wordpress\/ -->\n<title>Video Transcription Using Cloudinary<\/title>\n<meta name=\"description\" content=\"Accessibility is one of the most important parts of the modern web. Transcriptions allows us to deliver more accessible video content to the web as it caters to the challenges of a wide variety of users. In this post, we&#039;ll look at a few ways to add transcriptions to videos rendered in a Next.js application with Cloudinary video transcriptions.\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Video Transcription Using Cloudinary\" \/>\n<meta property=\"og:description\" content=\"Accessibility is one of the most important parts of the modern web. Transcriptions allows us to deliver more accessible video content to the web as it caters to the challenges of a wide variety of users. In this post, we&#039;ll look at a few ways to add transcriptions to videos rendered in a Next.js application with Cloudinary video transcriptions.\" \/>\n<meta property=\"og:url\" content=\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/\" \/>\n<meta property=\"og:site_name\" content=\"Cloudinary Blog\" \/>\n<meta property=\"article:published_time\" content=\"2022-07-26T09:16:32+00:00\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:image\" content=\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923963\/Web_Assets\/blog\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca.jpg?_i=AA\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"NewsArticle\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#article\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/\"},\"author\":{\"name\":\"\",\"@id\":\"\"},\"headline\":\"Video Transcription Using Cloudinary\",\"datePublished\":\"2022-07-26T09:16:32+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/\"},\"wordCount\":4,\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923963\/Web_Assets\/blog\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca.jpg?_i=AA\",\"keywords\":[\"Guest Post\",\"Next.js\",\"Transcriptions\",\"Under Review\"],\"inLanguage\":\"en-US\",\"copyrightYear\":\"2022\",\"copyrightHolder\":{\"@id\":\"https:\/\/cloudinary.com\/#organization\"}},{\"@type\":\"WebPage\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/\",\"url\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/\",\"name\":\"Video Transcription Using Cloudinary\",\"isPartOf\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923963\/Web_Assets\/blog\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca.jpg?_i=AA\",\"datePublished\":\"2022-07-26T09:16:32+00:00\",\"description\":\"Accessibility is one of the most important parts of the modern web. Transcriptions allows us to deliver more accessible video content to the web as it caters to the challenges of a wide variety of users. In this post, we'll look at a few ways to add transcriptions to videos rendered in a Next.js application with Cloudinary video transcriptions.\",\"breadcrumb\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#primaryimage\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923963\/Web_Assets\/blog\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca.jpg?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923963\/Web_Assets\/blog\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca.jpg?_i=AA\",\"width\":5616,\"height\":3744},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/cloudinary.com\/blog\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Video Transcription Using Cloudinary\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#website\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"name\":\"Cloudinary Blog\",\"description\":\"\",\"publisher\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/cloudinary.com\/blog\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#organization\",\"name\":\"Cloudinary Blog\",\"url\":\"https:\/\/cloudinary.com\/blog\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\",\"url\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"contentUrl\":\"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA\",\"width\":312,\"height\":60,\"caption\":\"Cloudinary Blog\"},\"image\":{\"@id\":\"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/\"}},{\"@type\":\"Person\",\"@id\":\"\"}]}<\/script>\n<!-- \/ Yoast SEO Premium plugin. -->","yoast_head_json":{"title":"Video Transcription Using Cloudinary","description":"Accessibility is one of the most important parts of the modern web. Transcriptions allows us to deliver more accessible video content to the web as it caters to the challenges of a wide variety of users. In this post, we'll look at a few ways to add transcriptions to videos rendered in a Next.js application with Cloudinary video transcriptions.","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:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/","og_locale":"en_US","og_type":"article","og_title":"Video Transcription Using Cloudinary","og_description":"Accessibility is one of the most important parts of the modern web. Transcriptions allows us to deliver more accessible video content to the web as it caters to the challenges of a wide variety of users. In this post, we'll look at a few ways to add transcriptions to videos rendered in a Next.js application with Cloudinary video transcriptions.","og_url":"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/","og_site_name":"Cloudinary Blog","article_published_time":"2022-07-26T09:16:32+00:00","twitter_card":"summary_large_image","twitter_image":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923963\/Web_Assets\/blog\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca.jpg?_i=AA","schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"NewsArticle","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#article","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/"},"author":{"name":"","@id":""},"headline":"Video Transcription Using Cloudinary","datePublished":"2022-07-26T09:16:32+00:00","mainEntityOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/"},"wordCount":4,"publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923963\/Web_Assets\/blog\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca.jpg?_i=AA","keywords":["Guest Post","Next.js","Transcriptions","Under Review"],"inLanguage":"en-US","copyrightYear":"2022","copyrightHolder":{"@id":"https:\/\/cloudinary.com\/#organization"}},{"@type":"WebPage","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/","url":"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/","name":"Video Transcription Using Cloudinary","isPartOf":{"@id":"https:\/\/cloudinary.com\/blog\/#website"},"primaryImageOfPage":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#primaryimage"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#primaryimage"},"thumbnailUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923963\/Web_Assets\/blog\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca.jpg?_i=AA","datePublished":"2022-07-26T09:16:32+00:00","description":"Accessibility is one of the most important parts of the modern web. Transcriptions allows us to deliver more accessible video content to the web as it caters to the challenges of a wide variety of users. In this post, we'll look at a few ways to add transcriptions to videos rendered in a Next.js application with Cloudinary video transcriptions.","breadcrumb":{"@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#primaryimage","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923963\/Web_Assets\/blog\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca.jpg?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923963\/Web_Assets\/blog\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca.jpg?_i=AA","width":5616,"height":3744},{"@type":"BreadcrumbList","@id":"https:\/\/cloudinary.com\/blog\/guest_post\/video-transcription-using-cloudinary\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/cloudinary.com\/blog\/"},{"@type":"ListItem","position":2,"name":"Video Transcription Using Cloudinary"}]},{"@type":"WebSite","@id":"https:\/\/cloudinary.com\/blog\/#website","url":"https:\/\/cloudinary.com\/blog\/","name":"Cloudinary Blog","description":"","publisher":{"@id":"https:\/\/cloudinary.com\/blog\/#organization"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/cloudinary.com\/blog\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/cloudinary.com\/blog\/#organization","name":"Cloudinary Blog","url":"https:\/\/cloudinary.com\/blog\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/","url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","contentUrl":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1649718331\/Web_Assets\/blog\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877\/cloudinary_logo_for_white_bg_1937437aa7_19374666c7_193742f877.png?_i=AA","width":312,"height":60,"caption":"Cloudinary Blog"},"image":{"@id":"https:\/\/cloudinary.com\/blog\/#\/schema\/logo\/image\/"}},{"@type":"Person","@id":""}]}},"jetpack_featured_media_url":"https:\/\/res.cloudinary.com\/cloudinary-marketing\/images\/f_auto,q_auto\/v1681923963\/Web_Assets\/blog\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca\/77393d6937981ec545753d424197ff5f9f08fad4-5616x3744-1_28226fd9ca.jpg?_i=AA","_links":{"self":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28225","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/users\/41"}],"replies":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/comments?post=28225"}],"version-history":[{"count":0,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/posts\/28225\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media\/28226"}],"wp:attachment":[{"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/media?parent=28225"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/categories?post=28225"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/cloudinary.com\/blog\/wp-json\/wp\/v2\/tags?post=28225"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}