{"id":12117,"date":"2020-09-30T22:30:01","date_gmt":"2020-09-30T20:30:01","guid":{"rendered":"https:\/\/blog.mi.hdm-stuttgart.de\/?p=12117"},"modified":"2023-06-18T18:08:49","modified_gmt":"2023-06-18T16:08:49","slug":"generating-audio-from-an-article-with-amazon-polly","status":"publish","type":"post","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2020\/09\/30\/generating-audio-from-an-article-with-amazon-polly\/","title":{"rendered":"Generating audio from an article with Amazon Polly"},"content":{"rendered":"\n<p><strong>Author:<\/strong> Silas Krause (sk295)<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Project<\/h2>\n\n\n\n<p>Reading multiple and detailed articles can become a little bit tiring. Listening to the same content, on the other hand, is more comfortable, can be done while driving, and is less straining for the eyes.<br>Therefore I decided to use this lecture to create a service that converts an article to an audio file using a Text-to-Speech service.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Technical Architecture<\/h2>\n\n\n\n<p>The input for the application is quite simple. The user only needs to provide a URL to the article. Then the main application fetches the contents of that URL and cuts out the unwanted markup. Then an audio file needs to be created. I chose the Amazon Polly TTS API and S3 as a file storage solution to try out Amazon Web Services.<br>To reduce multiple creations of the same article and load time, I intended to add a database that checks if there is already an audio file.<br>To interact with this application, I also needed a frontend that has an input field and dynamically renders the elements once the API endpoints send a response.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"970\" height=\"948\" data-attachment-id=\"12119\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2020\/09\/30\/generating-audio-from-an-article-with-amazon-polly\/technical-architecture-b2a\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/technical-architecture-b2a.png\" data-orig-size=\"970,948\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"technical-architecture-b2a\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/technical-architecture-b2a.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/technical-architecture-b2a.png\" alt=\"\" class=\"wp-image-12119\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/technical-architecture-b2a.png 970w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/technical-architecture-b2a-300x293.png 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/technical-architecture-b2a-768x751.png 768w\" sizes=\"auto, (max-width: 970px) 100vw, 970px\" \/><\/figure>\n\n\n\n<p>I built the app using NodeJS with the express because even though I do not have a lot of experience building backend applications, I know JavaScript well, and therefore I am familiar with node.<br>I decided to create three routes for my application. The index should serve the frontend. Additionally, I need two API endpoints, the first one to scrape the content from the URL, and the second one to generate the audio file.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><br>Getting the content<\/h2>\n\n\n\n<p>Initially, I thought I could simply fetch the HTML from the source. I quickly discovered that some pages render the content on the client-side or have some kind of confirmation screen. That is why I needed a way to prerender the page. The best solution I found was&nbsp;<a href=\"https:\/\/pptr.dev\/\">Puppeteer<\/a>. Puppeteer is a Headless Chrome Node.js API that runs Chromium headless and enables access to the rendered DOM. To reduce the load time, I blocked all third-party JavaScript.<br>Pruning the response to exclude everything but the content turned out to be a tedious task because every website structures their content differently. I ended up using&nbsp;<a href=\"https:\/\/www.npmjs.com\/package\/unfluff\">unfluff<\/a>, which is fine for most cases.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><br>TTS<\/h2>\n\n\n\n<p>After the extraction, the text can be sent to the Polly API. At first, I was using the&nbsp;<code class=\"\" data-line=\"\">synthesizeSpeech<\/code>&nbsp;method from the SDK. Aside from the parameters, this method accepts a callback function that can handle the response audio stream. That buffer can be stored in a file on the disk. While looking for a way to upload the audio file to S3 I found that there is a much simpler solution, which also eliminates the 3000 character limit of the&nbsp;<code class=\"\" data-line=\"\">synthesizeSpeech<\/code>&nbsp;method. The Polly SDK also has an option to start a task using the method&nbsp;<code class=\"\" data-line=\"\">startSpeechSynthesisTask<\/code>. This method excepts an additional parameter called &#8216;OutputS3BucketName&#8217;. After the task is completed. The output file is placed into the mentioned S3 bucket.<br>I really enjoyed seeing how this integration of different platform services simplifies the development.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"807\" data-attachment-id=\"12120\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2020\/09\/30\/generating-audio-from-an-article-with-amazon-polly\/polly-sdk\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/polly-sdk.png\" data-orig-size=\"1614,1272\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"polly-sdk\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/polly-sdk-1024x807.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/polly-sdk-1024x807.png\" alt=\"\" class=\"wp-image-12120\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/polly-sdk-1024x807.png 1024w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/polly-sdk-300x236.png 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/polly-sdk-768x605.png 768w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/polly-sdk-1536x1211.png 1536w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/polly-sdk.png 1614w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>In hindsight, a real consumer application might want to synthesize small snippets and stream them subsequently. That would almost eliminate the wait time, since generating an audio file and loading it can take up a lot of time for impatient users. However, I did not choose this path because I intended to create a cache with my database.<\/p>\n\n\n\n<p>The Response object from the&nbsp;<code class=\"\" data-line=\"\">startSpeechSynthesisTask<\/code>&nbsp;method contains a link to the file, but there are two issues.<br>The first problem is that S3 files are not public by default. You need to complete three different steps to make them publicly available.<br>At first, you need to unblock all public access in the permissions. Then you need to enable public access for &#8216;list objects&#8217; for everyone. After that, a pocket policy needs to be created. The policy generator luckily makes that quite easy.<\/p>\n\n\n\n<p>Even when public access is enabled, the asset cannot be loaded immediately because the generation takes a couple of seconds. I needed to notify and update the frontend. Eventually, I solved this by starting an interval once the audio is requested. The interval checks if the task has been completed and renders an audio element after it is completed.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"450\" data-attachment-id=\"12122\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2020\/09\/30\/generating-audio-from-an-article-with-amazon-polly\/useeffect-b2a\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/useEffect-b2a.jpg\" data-orig-size=\"1048,461\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"useEffect-b2a\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/useEffect-b2a-1024x450.jpg\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/useEffect-b2a-1024x450.jpg\" alt=\"\" class=\"wp-image-12122\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/useEffect-b2a-1024x450.jpg 1024w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/useEffect-b2a-300x132.jpg 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/useEffect-b2a-768x338.jpg 768w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/useEffect-b2a.jpg 1048w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<p>The authentification for AWS had to be done using the Cognito service by creating an identity pool.<\/p>\n\n\n\n<p><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Deployment<\/h2>\n\n\n\n<p>After the application was running successfully on my local machine, I had to deploy it. I chose the Platform-as-a-Service Platform on the IBM Cloud because I wanted to try out Cloud Foundry and I thought my simple express application was a good use case for this abstraction layer. I could have solved some parts of the app with a cloud function, but I do not need the control level of a virtual machine. Because Cloud Foundry requires a lot less configuration than a VM, it should be easy to deploy. <br>That is what I though.<br>I quickly ran into restrictions anyway. Except for the things I had to figure out due to my lack of knowledge of this platform, I had to spend a lot of time troubleshooting. <br>The biggest issue I faced was because of Puppeteer. At install time, the puppeteer package includes three versions of Chromium for Mac OS, Linux and Windows, which are all 150-250 MB large. The size exceeds the free tier limit and I had to upgrade. After that, I could not get Puppeteer running on the server, because the Ubuntu instance does not include all the debian packages that are necessary for running Chromium. <br>This really set me back. There is no way to install packages via&nbsp;<code class=\"\" data-line=\"\">sudo apt-get<\/code>&nbsp;on PaaS and doing anything manually would eliminate the benefits of the simple deployment. I really thought I had reached the limits of Platform-as-a-Service until I discovered that you can use multiple buildpacks with cloud foundry. Even if they are not included on the IBM Cloud, by adding the Github repo.<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code class=\"\" data-line=\"\">buildpacks: \n    - https:\/\/github.com\/cloudfoundry\/apt-buildpack\n    - nodejs_buildpack<\/code><\/pre>\n\n\n\n<p>This allows you to add an&nbsp;<code class=\"\" data-line=\"\">apt.yml<\/code>&nbsp;file to specify the packages you want to install.<br>Afterward, I was able to run my application.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\"><br>Tests<\/h2>\n\n\n\n<p>For tests, I chose to use mocha and chai. Except for a few modifications for the experimental modules I am using, this integration was straightforward. It uncovered a few error cases I was not considering before.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"294\" data-attachment-id=\"12123\" data-permalink=\"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2020\/09\/30\/generating-audio-from-an-article-with-amazon-polly\/article2audio-logs\/\" data-orig-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/article2audio-logs.png\" data-orig-size=\"1443,415\" data-comments-opened=\"1\" data-image-meta=\"{&quot;aperture&quot;:&quot;0&quot;,&quot;credit&quot;:&quot;&quot;,&quot;camera&quot;:&quot;&quot;,&quot;caption&quot;:&quot;&quot;,&quot;created_timestamp&quot;:&quot;0&quot;,&quot;copyright&quot;:&quot;&quot;,&quot;focal_length&quot;:&quot;0&quot;,&quot;iso&quot;:&quot;0&quot;,&quot;shutter_speed&quot;:&quot;0&quot;,&quot;title&quot;:&quot;&quot;,&quot;orientation&quot;:&quot;0&quot;}\" data-image-title=\"article2audio-logs\" data-image-description=\"\" data-image-caption=\"\" data-large-file=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/article2audio-logs-1024x294.png\" src=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/article2audio-logs-1024x294.png\" alt=\"\" class=\"wp-image-12123\" srcset=\"https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/article2audio-logs-1024x294.png 1024w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/article2audio-logs-300x86.png 300w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/article2audio-logs-768x221.png 768w, https:\/\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2020\/09\/article2audio-logs.png 1443w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\"><br>Conclusion<\/h2>\n\n\n\n<p>To sum up I can say that I learned a lot during this project, especially because a lot of things were completely new to me. But now I feel more confident to work with those tools and I want to continue to work on this project.<br>I can also recommend using cloud foundry. If you know how to deal with the restrictions and know your true environment conditions, it is pretty flexible and enjoyable to use.<\/p>\n\n\n\n<p>Repo:&nbsp;<a href=\"https:\/\/github.com\/krsilas\/article2audio\">https:\/\/github.com\/krsilas\/article2audio<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"<p>Author: Silas Krause (sk295) Project Reading multiple and detailed articles can become a little bit tiring. Listening to the same content, on the other hand, is more comfortable, can be done while driving, and is less straining for the eyes.Therefore I decided to use this lecture to create a service that converts an article to [&hellip;]<\/p>\n","protected":false},"author":989,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[1,652,660,120,22],"tags":[],"ppma_author":[834],"class_list":["post-12117","post","type-post","status-publish","format-standard","hentry","category-allgemein","category-artificial-intelligence","category-chatgpt-and-language-models","category-cloud-technologies","category-student-projects"],"aioseo_notices":[],"jetpack_featured_media_url":"","jetpack-related-posts":[{"id":4122,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2018\/08\/27\/building-a-serverless-web-service-for-music-fingerprinting\/","url_meta":{"origin":12117,"position":0},"title":"Building a Serverless Web Service For Music Fingerprinting","author":"Alexis Luengas","date":"27. August 2018","format":false,"excerpt":"Building serverless architectures is hard. At least it was to me in my first attempt to design a loosely coupled system that should, in the long term, mean a good bye to my all-time aversion towards system maintenance. Music information retrieval is also hard. It is when you attempt to\u2026","rel":"","context":"In &quot;Cloud Technologies&quot;","block_context":{"text":"Cloud Technologies","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/cloud-technologies\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2018\/08\/Architecture-Diagram-300x190.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]},{"id":27565,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2025\/02\/28\/scaling-an-ai-transcription-model-as-a-service\/","url_meta":{"origin":12117,"position":1},"title":"Scaling an AI Transcription Model as a Service","author":"ns144","date":"28. February 2025","format":false,"excerpt":"Ton-Texter is a Software as a service solution that delivers state of the art transcription performance. In this blog post, we will explore how we have improved its scalability to handle high demand.","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/02\/Featured_Image01.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/02\/Featured_Image01.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/02\/Featured_Image01.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/02\/Featured_Image01.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/02\/Featured_Image01.jpg?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2025\/02\/Featured_Image01.jpg?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":28282,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2026\/02\/22\/building-a-cloud-native-web-application-for-case-based-file-sharing-on-aws\/","url_meta":{"origin":12117,"position":2},"title":"Developing a cloud-native web application for case-based file sharing on AWS","author":"Philipp Treupel","date":"22. February 2026","format":false,"excerpt":"Motivation Professional file sharing is a significant challenge in sectors such as healthcare, insurance, and consulting. Practitioners routinely need to exchange sensitive documents with clients, yet existing solutions such as Google Drive and OneDrive can quickly become disorganized when managing multiple cases. Users struggle with scattered links, having to manually\u2026","rel":"","context":"In &quot;Cloud Technologies&quot;","block_context":{"text":"Cloud Technologies","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/cloud-technologies\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/02\/user-journey-essencis-en.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/02\/user-journey-essencis-en.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/02\/user-journey-essencis-en.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/02\/user-journey-essencis-en.png?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/02\/user-journey-essencis-en.png?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2026\/02\/user-journey-essencis-en.png?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":22151,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2022\/02\/22\/designing-and-implementing-a-scalable-web-application\/","url_meta":{"origin":12117,"position":3},"title":"Designing the framework for a scalable CI\/CD supported web application","author":"Danial Eshete","date":"22. February 2022","format":false,"excerpt":"Documentation of our approaches to the project, our experiences and finally the lessons we learned. The development team approaches the project with little knowledge of cloud services and infrastructure. Furthermore, no one has significant experience with containers and\/or containerized applications. However, the team is well experienced in web development and\u2026","rel":"","context":"In &quot;Allgemein&quot;","block_context":{"text":"Allgemein","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/allgemein\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/02\/Design_Desktop_Logged_In-3-150x150.jpg?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/02\/Design_Desktop_Logged_In-3-150x150.jpg?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/02\/Design_Desktop_Logged_In-3-150x150.jpg?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/02\/Design_Desktop_Logged_In-3-150x150.jpg?resize=700%2C400&ssl=1 2x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/02\/Design_Desktop_Logged_In-3-150x150.jpg?resize=1050%2C600&ssl=1 3x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2022\/02\/Design_Desktop_Logged_In-3-150x150.jpg?resize=1400%2C800&ssl=1 4x"},"classes":[]},{"id":1832,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2017\/02\/27\/continuous-integration-with-travis-ci-and-amazon-webservices\/","url_meta":{"origin":12117,"position":4},"title":"Continuous Integration with Travis CI and Amazon Webservices","author":"st067","date":"27. February 2017","format":false,"excerpt":"Introduction In the the course Software Engineering and Management and Interactive Media at Stuttgart Media University, we launched an interactive web application called Emoji College. www.emoji.college The following blog entry is a brief description of what is going on in this project. The main focus relies on the implementation of\u2026","rel":"","context":"In &quot;DevOps&quot;","block_context":{"text":"DevOps","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/scalable-systems\/devops\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/02\/Bildschirmfoto-2017-02-22-um-14.26.13.png?resize=350%2C200&ssl=1","width":350,"height":200,"srcset":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/02\/Bildschirmfoto-2017-02-22-um-14.26.13.png?resize=350%2C200&ssl=1 1x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/02\/Bildschirmfoto-2017-02-22-um-14.26.13.png?resize=525%2C300&ssl=1 1.5x, https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2017\/02\/Bildschirmfoto-2017-02-22-um-14.26.13.png?resize=700%2C400&ssl=1 2x"},"classes":[]},{"id":12178,"url":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/2021\/02\/24\/web-audio-api-tips-for-performance\/","url_meta":{"origin":12117,"position":5},"title":"Web Audio API &#8211; Tips for Performance","author":"Johanna Kuch","date":"24. February 2021","format":false,"excerpt":"This post is about specific performance issues of the Web Audio API, especially its AudioNodes. It also briefly explains what this API was developed for and what you can do with it. Finally, it mentions a few tips and tricks to improve the performance of the Web Audio API. Image\u2026","rel":"","context":"In &quot;Interactive Media&quot;","block_context":{"text":"Interactive Media","link":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/category\/interactive-media\/"},"img":{"alt_text":"","src":"https:\/\/i0.wp.com\/blog.mi.hdm-stuttgart.de\/wp-content\/uploads\/2021\/02\/grafik-6.png?resize=350%2C200&ssl=1","width":350,"height":200},"classes":[]}],"jetpack_sharing_enabled":true,"authors":[{"term_id":834,"user_id":989,"is_guest":0,"slug":"sk295","display_name":"sk295","avatar_url":"https:\/\/secure.gravatar.com\/avatar\/cd0999e01953e876fa9245bd9a61ff0e0953a2956dd87d3aa573a5cd41ba04ef?s=96&d=mm&r=g","0":null,"1":"","2":"","3":"","4":"","5":"","6":"","7":"","8":""}],"_links":{"self":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/12117","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/users\/989"}],"replies":[{"embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/comments?post=12117"}],"version-history":[{"count":3,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/12117\/revisions"}],"predecessor-version":[{"id":12133,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/posts\/12117\/revisions\/12133"}],"wp:attachment":[{"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/media?parent=12117"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/categories?post=12117"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/tags?post=12117"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/blog.mi.hdm-stuttgart.de\/index.php\/wp-json\/wp\/v2\/ppma_author?post=12117"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}