<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	 xmlns:media="http://search.yahoo.com/mrss/" >

<channel>
	<title>Marco Sussitz &#8211; Bitmovin</title>
	<atom:link href="https://bitmovin.com/author/enzo/feed" rel="self" type="application/rss+xml" />
	<link>https://bitmovin.com</link>
	<description>Bitmovin provides adaptive streaming infrastructure for video publishers and integrators. Fastest cloud encoding and HTML5 Player. Play Video Anywhere.</description>
	<lastBuildDate>Mon, 09 Jan 2023 11:57:30 +0000</lastBuildDate>
	<language>en-GB</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	

<image>
	<url>https://bitmovin.com/wp-content/uploads/2023/11/bitmovin_favicon.svg</url>
	<title>Marco Sussitz &#8211; Bitmovin</title>
	<link>https://bitmovin.com</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>Creating a Live Streaming Setup with Android Devices and Bitmovin</title>
		<link>https://bitmovin.com/creating-live-stream-android-bitmovin%ef%bf%bc</link>
		
		<dc:creator><![CDATA[Marco Sussitz]]></dc:creator>
		<pubDate>Tue, 20 Dec 2022 11:27:55 +0000</pubDate>
				<category><![CDATA[Developers]]></category>
		<category><![CDATA[Android]]></category>
		<category><![CDATA[live streaming]]></category>
		<guid isPermaLink="false">https://bitmovin.com/?p=247692</guid>

					<description><![CDATA[<p>It is that time of the quarter again at Bitmovin, Hackathon time. Our Hackathon includes two days of hacking solutions together before presenting the results to the wider business. Every programmer loves it and even more when your team is winning.&#160; During this Hackathon, we decided to step out of our backend-comfort zone and tinker...</p>
<p>The post <a rel="nofollow" href="https://bitmovin.com/creating-live-stream-android-bitmovin%ef%bf%bc">Creating a Live Streaming Setup with Android Devices and Bitmovin</a> appeared first on <a rel="nofollow" href="https://bitmovin.com">Bitmovin</a>.</p>
]]></description>
										<content:encoded><![CDATA[
<p>It is that time of the quarter again at Bitmovin, Hackathon time. Our Hackathon includes two days of hacking solutions together before presenting the results to the wider business. Every programmer loves it and even more when your team is winning.&nbsp; During this Hackathon, we decided to step out of our backend-comfort zone and tinker a bit with UI.</p>



<p>To be more specific, we tried to write an android app that would serve as an <a href="https://bitmovin.com/docs/encoding/tutorials/create-a-live-encoding-from-an-rtmp-stream" target="_blank" rel="noreferrer noopener">RTMP input source for a live stream</a>.</p>



<p>Setting up an RTMP input can be lengthy, especially when there is no computer with FFmpeg at hand. And syndetic input can be boring at times. So why not use a live feed from your mobile device for this? My go-to tool to create an RTMP stream is FFmpeg so let&#8217;s try to use this in android. We quickly realized that that was a futile endeavor, especially in two days. So we did what any software developer would do and looked for a library that had been written by somebody smarter than us. We tried a few libraries like the Larix Broadcaster SDK or some small GitHub repositories like the<a href="https://github.com/ant-media/LiveVideoBroadcaster" target="_blank" rel="noreferrer noopener nofollow"> LiveVideoBroadcaster</a> but weren’t able to get any of these to work in the limited time we had. Finally, a bit more searching revealed the grail we had been looking for; we unearthed <a href="https://github.com/pedroSG94/rtmp-rtsp-stream-client-java" target="_blank" rel="noreferrer noopener nofollow">this library</a> and managed to get something running.</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">How to use it</h2>



<p>The library creates a very handy OpenGLView that lets you show the camera in your activity. If you&#8217;d like to follow along with the steps we took, then to start, simply add it to your XML config like this:</p>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="xml" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">&lt;com.pedro.rtplibrary.view.OpenGlView
    android:layout_width="0dp"
    android:layout_height="0dp"
    app:layout_constraintBottom_toBottomOf="parent"
    app:layout_constraintEnd_toEndOf="parent"
    app:layout_constraintStart_toStartOf="parent"
    app:layout_constraintTop_toTopOf="parent"
    android:id="@+id/surfaceView"
    app:keepAspectRatio="true"
    app:aspectRatioMode="fill"
    app:AAEnabled="false"
    app:numFilters="2"
    app:isFlipHorizontal="false"
    app:isFlipVertical="false"
    /></pre>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<p>The corresponding code will need an OpenGlView object as well as a RtmpCamera object. Let&#8217;s go ahead and create those:</p>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">private RtmpCamera2 rtmpCamera;
private OpenGlView openGlView;</pre>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Those elements also need some values assigned, and we used the onCreate method for that:</p>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">this.openGlView = findViewById(R.id.surfaceView);
this.rtmpCamera = new RtmpCamera2(openGlView, this);
this.openGlView.getHolder().addCallback(this);</pre>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Starting an RTMP stream</h2>



<p>As all of the necessary configurations were complete, we just have to start the RTMP stream. To do that, the only thing we need to add to the code below (how to obtain that will be shown later).</p>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">@Override
public void startStreaming() {
   runOnUiThread(() -> {
       if (!rtmpCamera.isStreaming()) {
           if (rtmpCamera.isRecording()
                   || rtmpCamera.prepareAudio() &amp;&amp;                      rtmpCamera.prepareVideo()) {
               rtmpCamera.startStream("URL to you live stream");
               setStateStreamIsRunning();
           } else {
               this.toastError( "Error preparing stream, This device cant do it");
           }
       } else {
           rtmpCamera.stopStream();
       }
   });
}</pre>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<p>We used a separate thread and a callback for that. That is why there is a runOnUiThread, but if you start the RTMP stream from your activity, you will not need that.</p>



<p>The RTMP URL can be set here <code data-enlighter-language="java" class="EnlighterJSRAW">rtmpCamera.startStream("URL to you live stream");</code></p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<h2 class="wp-block-heading">Setting up the live stream encoder</h2>



<p>For our encoder, we used the simple API<a href="https://bitmovin.com/docs/encoding/articles/simple-encoding-api-live" target="_blank" rel="noreferrer noopener"> https://bitmovin.com/docs/encoding/articles/simple-encoding-api-live</a>, so we needed minimal configuration to get the live stream up and running. We used the CDN <a href="https://bitmovin.com/docs/encoding/articles/bitmovin-cdn-output" target="_blank" rel="noreferrer noopener">https://bitmovin.com/docs/encoding/articles/bitmovin-cdn-output</a> output as well because it would work out of the box.</p>



<p></p>



<p>To get this going, the first thing to set up is the input:</p>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">private SimpleEncodingLiveJobResponse setUpLiveStream() {
   SimpleEncodingLiveJobInput input = new SimpleEncodingLiveJobInput();
   input.setInputType(SimpleEncodingLiveJobInputType.RTMP);
   SimpleEncodingLiveJobRequest job = new SimpleEncodingLiveJobRequest();
   SimpleEncodingLiveJobCdnOutput outputUrl = givenCdnOutputWithFullHDResolution();</pre>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Next is the output. In the spirit of the hackathon, we used a CND because of the minimal configuration, which you can set up like this:</p>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">private SimpleEncodingLiveJobCdnOutput givenCdnOutputWithFullHDResolution() {
   SimpleEncodingLiveJobCdnOutput output = new SimpleEncodingLiveJobCdnOutput();
   output.setMaxResolution(SimpleEncodingLiveMaxResolution.FULL_HD);
   return output;
}</pre>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Now only some minor configurations are left.</p>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">   job.setInput(input);
   job.addOutputsItem(outputUrl);
   job.setCloudRegion(SimpleEncodingLiveCloudRegion.EUROPE);
   job.setName("Android app live stream");
   return bitmovinApi.encoding.simple.jobs.live.create(job);
}</pre>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<p></p>



<h2 class="wp-block-heading">Finishing touches</h2>



<p>A live stream takes a bit of time to be ready. in the essence of time, we swiftly did a very ugly “busy waiting” loop to wait until the live stream was done with the setup. To improve this, we have left it as an exercise for the reader.</p>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">public boolean setupLiveStreamAndWaitForRunningState(Callback cb) {
   this.stopped = false;
   this.encodingId = null;
   SimpleEncodingLiveJobResponse jobResponse = setUpLiveStream();
   try {
       while (!readyForIngestOrFailed(jobResponse) &amp;&amp; !stopped) {

           Thread.sleep(300);
           jobResponse = bitmovinApi.encoding.simple.jobs.live.get(jobResponse.getId());
           if (jobResponse.getEncodingId() != null &amp;&amp; this.encodingId == null) {
               this.encodingId = jobResponse.getEncodingId();
           }
           cb.reportStatus(jobResponse.getStatus().toString());
       }
   } catch (Exception e) {
       cb.toastError(e.getMessage());
   }
   if (this.stopped || this.encodingId == null || this.encodingId.isEmpty())
   {
       return false;
   }
   cb.startStreaming();
   this.rtmpUrl = String.format("rtmp://%s/live/%s", jobResponse.getEncoderIp(), jobResponse.getStreamKey());
   return true;
}</pre>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<p>To retrieve the RTMP URL that needs to be inserted into the code, get it by using:</p>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<pre class="EnlighterJSRAW" data-enlighter-language="java" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">this.rtmpUrl = 
String.format("rtmp://%s/live/%s", jobResponse.getEncoderIp(), 
jobResponse.getStreamKey());</pre>



<div style="height:5px" aria-hidden="true" class="wp-block-spacer"></div>



<p>We had to run this in a separate thread because you cannot have HTTP requests in the UI thread in android, and it would not be a good user experience anyway.</p>



<p>Once the hard part was done, we spent the second day of the hackathon refining the app and making the UI better and even got some much-appreciated help from one of the Bitmovin UX designers.</p>



<p></p>



<p></p>



<h2 class="wp-block-heading">Wrapping up</h2>



<p>As the hackathon drew to a close, the competition was fierce, with great projects submitted by other teams. However, in the end, all of the efforts paid off, as our team won first place!&nbsp;</p>



<p>Here are a couple of images of how the live stream worked on an Android phone:</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-image aligncenter size-full"><img fetchpriority="high" decoding="async" width="230" height="512" src="https://bitmovin.com/wp-content/uploads/2022/12/Hackathon-Android-Application-Image-to-Start-Live-Stream.png" alt="live streaming android - Bitmovin" class="wp-image-247706" srcset="https://b3148424.smushcdn.com/3148424/wp-content/uploads/2022/12/Hackathon-Android-Application-Image-to-Start-Live-Stream-135x300.png?lossy=2&amp;strip=1&amp;webp=1 135w, https://b3148424.smushcdn.com/3148424/wp-content/uploads/2022/12/Hackathon-Android-Application-Image-to-Start-Live-Stream.png?lossy=2&amp;strip=1&amp;webp=1 230w" sizes="(max-width: 230px) 100vw, 230px" /></figure>



<p class="has-text-align-center">Visual of stream interface pre-live</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<figure class="wp-block-image aligncenter size-full"><img decoding="async" width="230" height="512" src="https://bitmovin.com/wp-content/uploads/2022/12/Hackathon-Android-Application-Image-Live-Stream-Started.png" alt="live streaming android - Bitmovin" class="wp-image-247707" srcset="https://b3148424.smushcdn.com/3148424/wp-content/uploads/2022/12/Hackathon-Android-Application-Image-Live-Stream-Started-135x300.png?lossy=2&amp;strip=1&amp;webp=1 135w, https://b3148424.smushcdn.com/3148424/wp-content/uploads/2022/12/Hackathon-Android-Application-Image-Live-Stream-Started.png?lossy=2&amp;strip=1&amp;webp=1 230w" sizes="(max-width: 230px) 100vw, 230px" /></figure>



<p class="has-text-align-center">Visual of active live stream</p>



<div style="height:10px" aria-hidden="true" class="wp-block-spacer"></div>



<p>Additionally, if this project was interesting to you and you’re currently looking to test your streaming application across Android, iOS, or any other platform/device, check out our <a href="https://bitmovin.com/dashboard/signup" target="_blank" rel="noreferrer noopener">30-day free trial</a> where you can test the Bitmovin Live and VOD Encoder, Player or any of our other SaaS solutions completely free with no commitment.</p>



<p></p>
<p>The post <a rel="nofollow" href="https://bitmovin.com/creating-live-stream-android-bitmovin%ef%bf%bc">Creating a Live Streaming Setup with Android Devices and Bitmovin</a> appeared first on <a rel="nofollow" href="https://bitmovin.com">Bitmovin</a>.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Introducing Bitmovin&#8217;s Simple Encoding API</title>
		<link>https://bitmovin.com/simple-encoding-api</link>
		
		<dc:creator><![CDATA[Marco Sussitz]]></dc:creator>
		<pubDate>Mon, 17 Jan 2022 09:57:12 +0000</pubDate>
				<category><![CDATA[Product Updates]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[video encoding]]></category>
		<guid isPermaLink="false">https://bitmovin.com/?p=212336</guid>

					<description><![CDATA[<p>If one looks at video and audio encodings like H.264, H.265, VP9, AV1 and all of the things that are associated with it, it can be very easy to get lost. There are millions of possible configurations and figuring out the right one can be a difficult task. The Bitmovin API makes it possible to...</p>
<p>The post <a rel="nofollow" href="https://bitmovin.com/simple-encoding-api">Introducing Bitmovin&#8217;s Simple Encoding API</a> appeared first on <a rel="nofollow" href="https://bitmovin.com">Bitmovin</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><span style="font-weight: 400;">If one looks at video and audio encodings like H.264, H.265, VP9, AV1 and all of the things that are associated with it, it can be very easy to get lost. There are millions of possible configurations and figuring out the right one can be a difficult task.</span><br />
<span style="font-weight: 400;">The Bitmovin API makes it possible to granularly tinker with your video settings and cover a vast array of use cases. This alone can become a daunting task, as <a href="https://bitmovin.com/docs/encoding/getting-started/java">setting up even a simple encoding</a> can take a lot </span><span style="font-weight: 400;">of time</span><span style="font-weight: 400;">. That is why we&#8217;ve set out to make taking your first encoding step easier. </span><br />
<span style="font-weight: 400;">Bitmovin&#8217;s new Simple Encoding API uses our <a href="https://bitmovin.com/per-title-encoding/">Per-Title technology </a></span><span style="font-weight: 400;">to deliver the best video experience to you with little to no configuration necessary. </span><span style="font-weight: 400;">Using the Simple Encoding API will set up a complete (and automated) encoding job for you by making use of our base API. The encoding will use an H264 codec for video inputs and an AAC stereo for audio.</span><br />
<strong>*UPDATE &#8211; Feb 8, 2022* </strong>With the release of Encoder version <a href="https://bitmovin.com/docs/encoding/releases/encoder/encoder-2-109-0">2.109.0</a>, the Bitmovin Simple Encoding API now supports AV1 encoding, in addition to the default H264! Click below to try it out in Postman and check the documentation tab there for more details.</p>
<figure class="wp-block-image"><a href="https://god.gw.postman.com/run-collection/18670786-99cd0bd7-4579-4d40-89b7-663dff3aa82d?action=collection%2Ffork&amp;collection-url=entityId%3D18670786-99cd0bd7-4579-4d40-89b7-663dff3aa82d%26entityType%3Dcollection%26workspaceId%3D4b3f8ccb-66c0-4379-8cff-e282c9804e03" rel="nofollow noopener" target="_blank"><img decoding="async" src="https://run.pstmn.io/button.svg" alt="Run in Postman" /></a></figure>
<h2><span style="font-weight: 400;">How to use the Simple Encoding API</span></h2>
<p><span style="font-weight: 400;">The Simple Encoding API will help you to create an encoding that will fit a vast array of use cases with <a href="https://bitmovin.com/docs/encoding/api-reference/all#/Encoding/PostSimpleEncodingVodJob.">only a single endpoint</a>. </span><span style="font-weight: 400;">You can either use any of Bitmovin&#8217;s <a href="https://bitmovin.com/docs/encoding/sdks">SDKs</a> or directly call the endpoints with tools like <em>Postman. </em>For additional information on how to add the API key to the request can be found here: <a href="https://bitmovin.com/docs/encoding/tutorials/get-started-with-the-bitmovin-api">https://bitmovin.com/docs/encoding/tutorials/get-started-with-the-bitmovin-api</a>. </span><br />
<span style="font-weight: 400;">With a single endpoint in mind, the only things that you need to set up are the inputs and the outputs. </span><br />
<span style="font-weight: 400;">The first thing you will need is input. The most common input types are supported: </span><span style="font-weight: 400;">S3, GCS, Azure Blob Storage, Akamai NetStorage, HTTP(S), and (S)FTP.</span><br />
<span style="font-weight: 400;">You can choose between four different input types: audio, video, subtitles, and closed captions. If you don’t specifically state an input type for a file, it will be assumed to contain a video track and an optional audio track.</span><br />
<span style="font-weight: 400;">Multiple audio and subtitles/closed captions inputs can be used but only one video input is possible. </span><span style="font-weight: 400;">Specifying a language is mandatory for </span><span style="font-weight: 400;">subtitles and closed captions; as a best practice, we also recommend specifying the language for audio inputs.</span></p>
<h3><span style="font-weight: 400;">Simple Encoding Output</span></h3>
<p><span style="font-weight: 400;">Let’s define an input. </span></p>
<pre><span style="font-weight: 400;">"inputs":[</span>
   {
    "url": "https://ftp.halifax.rwth-aachen.de/blender/demo/movies/ToS/ToS-4k-1920.mov"
   }
]</pre>
<p><span style="font-weight: 400;">Next, we are going to define an output. The Simple Encoding API supports S3, GCS, Azure Blob Storage, and Akamai NetStorage as output, further <a href="https://bitmovin.com/docs/encoding/api-reference/all#/Encoding/PostSimpleEncodingVodJob">details can be found in our documentation</a>. One thing to consider is if the created files need to be private or public. If the files are public the output has to be able to support that.</span><br />
<span style="font-weight: 400;">Next, let’s set up a private S3 output.</span></p>
<pre>"outputs": [
        {
            "url": "s3://your/output/path",
            "credentials": {
                "accessKey": "accessKey",
                "secretKey": "secretKey"
            }
        }
    ]</pre>
<p><span style="font-weight: 400;">Now you only need to choose a name for your encoding job and put the inputs and the outputs into one JSON. It will look somewhat like this:</span></p>
<pre>{
    "name": "simple_encoding_name",
    "inputs": <span style="font-weight: 400;">[</span>
<span style="font-weight: 400;">        {</span>
<span style="font-weight: 400;">            "url": "https://ftp.halifax.rwth-aachen.de/blender/demo/movies/ToS/ToS-4k-1920.mov"</span>
<span style="font-weight: 400;">        }</span>
<span style="font-weight: 400;">    ]</span>,
    "outputs": [
        {
            "url": "your/output/path",
            "credentials": {
                "accessKey": "accessKey",
                "secretKey": "secretKey"
            }
        }
    ],
}</pre>
<p><span style="font-weight: 400;">With the JSON completed the last thing to do is to send it to the API via this endpoint.</span></p>
<pre>POST https://api.bitmovin.com/v1/encoding/simple/jobs/vod</pre>
<p><span style="font-weight: 400;">The response will look like this</span></p>
<pre>{
    "id": "854a2a86-9028-4e33-863b-d602a6bac24b",
    "status": "CREATED",
    "encodingId": null,
    "inputs": [
        {
            "url": "https://ftp.halifax.rwth-aachen.de/blender/demo/movies/ToS/ToS-4k-1920.mov"
        }
    ],
    "outputs": [
        {
            "url": "your/output/path",
        }
    ],
    "createdAt": 2022-01-17T14:26:54Z,
    "modifiedAt": 2022-01-17T14:26:54Z,
    "name": "simple_encoding_name"
}</pre>
<p><span style="font-weight: 400;">Now that the start call is fully set up, the last thing to do is wait for the encoding to finish.</span><br />
<span style="font-weight: 400;">The endpoint will show the current status of your encoding</span></p>
<pre>GET /encoding/simple/jobs/ vod/{simple_encoding_job_id}
{
    "id": "854a2a86-9028-4e33-863b-d602a6bac24b",
    "status": "FINISHED",
    "encodingId": "5b71dcf1-5f92-4534-b530-47706003e7a4",
<span style="font-weight: 400;">    </span>"inputs": [
        {
            "url": "https://ftp.halifax.rwth-aachen.de/blender/demo/movies/ToS/ToS-4k-1920.mov"
        }
    ],
    "outputs": [
        {
            "url": "your/output/path",
            "makePublic": true
        }
    ],
    "name": "simple_encoding_name"
}</pre>
<p><span style="font-weight: 400;">Once the status is set to “finished” the encoding is done.</span><br />
<span style="font-weight: 400;">The Simple Encoding API can be accessed by <a href="https://bitmovin.com/docs/encoding/sdks">our SDKs as well</a></span><span style="font-weight: 400;">.</span></p>
<h3><span style="font-weight: 400;">Simple Encoding API output</span></h3>
<p><span style="font-weight: 400;">Once the simple encoding has finished, it will write the output to your specified</span><span style="font-weight: 400;"> location. The encoding will create <a href="https://bitmovin.com/docs/encoding/api-reference/sections/encodings#/Encoding/PostEncodingEncodingsMuxingsFmp4ByEncodingId">segmented video files </a></span><span style="font-weight: 400;">as well as <a href="https://bitmovin.com/docs/encoding/api-reference/sections/manifests#/Encoding/PostEncodingManifestsHls">HLS</a> and <a href="https://bitmovin.com/docs/encoding/api-reference/sections/manifests#/Encoding/PostEncodingManifestsDash">DASH</a> manifests. The encoding will furthermore create </span><span style="font-weight: 400;"><a href="https://bitmovin.com/docs/encoding/api-reference/sections/encodings#/Encoding/PostEncodingEncodingsStreamsThumbnailsByEncodingIdAndStreamId">thumbnails</a>,</span><span style="font-weight: 400;"> <a href="https://bitmovin.com/docs/encoding/api-reference/sections/encodings#/Encoding/PostEncodingEncodingsStreamsSpritesByEncodingIdAndStreamId">sprites</a>, <a href="https://bitmovin.com/docs/encoding/api-reference/sections/configurations#/Encoding/PostEncodingConfigurationsSubtitlesWebVtt">subtitles</a>, closed captions, and audio if your input contains them.</span><br />
<img decoding="async" class="alignnone wp-image-217310 size-full" src="https://bitmovin.com/wp-content/uploads/2022/01/Simple-Encoding-API_Encoding-Decision-Tree_v2-2.png" alt="live streaming android - Bitmovin" width="720" height="1130"><br />
<span style="font-weight: 400;">We know that starting your video encoding can be hard, thus we aimed to keep this API as simple as possible while still providing you with everything you might need for your workflow. We will continue to improve our Simple Encoding API, so if you have any suggestions for improvements or how we can make it more suitable for your use case, please </span><a href="https://bitmovin.com/contact-bitmovin"><span style="font-weight: 400;">let us know</span></a><span style="font-weight: 400;">!</span></p>
<h2>How to Troubleshoot the Simple Encoding API &amp; FAQs</h2>
<h3>Error Messages</h3>
<p><span style="font-weight: 400;"><strong>“No API key found in request&#8221;</strong></span><br />
<span style="font-weight: 400;">API requests must be authenticated using your API key.  This is found in the dashboard under your name (top right/Account settings).  This is placed as the X-Api-Key in the header of your POST request.  We suggest using a tool such as POSTMAN to create the POST request during testing </span><br />
<strong>Could not determine the scheme</strong><br />
Output URLs follow the standard URL structure provided by the storage providers.   These are written above as “your/output/path” however must also include the scheme identifier:   for google this is gcs://&lt;bucket-name&gt;/folder,  for amazon this is s3://&lt;bucket-name&gt;/folder,  for ftp ftp://__ etc.    Failure to put the &lt;something&gt;:// will result in this error message.</p>
<h3>Questions</h3>
<p><span style="font-weight: 400;"><strong>I want to the Simple Encoding API,  but I don’t have an API key:</strong> </span><br />
<span style="font-weight: 400;">The easiest way is to sign up for a trial via the bitmovin homepage bitmovin.com /  <a href="https://bitmovin.com/dashboard/signup">Try for free</a> (top right)</span><br />
<span style="font-weight: 400;"><strong>I have submitted the POST request,  the response says “SUCCESS” but nothing is appearing in the dashboard:</strong> </span><br />
<span style="font-weight: 400;">There may be something wrong in credentials or file locations. </span></p>
<ol>
<li><span style="font-weight: 400;">Copy the “id”  found in the first line of the response</span></li>
<li><span style="font-weight: 400;">Query it with GET /encoding/simple/jobs/vod/{simple_encoding_job_id}  </span><span style="font-weight: 400;">(where simple_encoding_job_id is the id you just copied)</span></li>
<li><span style="font-weight: 400;">This will provide more thorough details of the simple-encoding-job.</span></li>
</ol>
<p><span style="font-weight: 400;"><strong>What’s the difference between simple_encoding_job_id (referenced above) and Encoding ID (in the dashboard)? </strong> </span><br />
<span style="font-weight: 400;">Once a simple-encode-id-job is successfully submitted an encodeId will be assigned.  You can find the encodeId for a particular simple_encoding_job_id via GET /encoding/simple/jobs/vod/{simple_encoding_job_id} and looking for encodeId in the response.</span><br />
<span style="font-weight: 400;"><strong>How to add different input types to the Simple Encoding request?</strong> </span><br />
<span style="font-weight: 400;">You can view all input types and how to use them in our documentation here: <a href="https://bitmovin.com/docs/encoding/articles/simple-encoding-api">https://bitmovin.com/docs/encoding/articles/simple-encoding-api</a></span><br />
Try out our new Simple Encoding API for yourself by <a href="https://bitmovin.com/dashboard/signup">signing up for a trial today</a>.</p>
<h2><strong>Video technology guides and articles</strong></h2>
<ul>
<li>Back to Basics: Guide to the <a href="https://bitmovin.com/html5-video-tag-guide/">HTML5 Video Tag </a></li>
<li><a href="https://bitmovin.com/vod-platforms/">What is a VoD Platform?</a> A comprehensive guide to Video on Demand (VOD)</li>
<li><a href="https://bitmovin.com/top-5-video-technology-trends/">Video Technology [2022]</a>: Top 5 video technology trends</li>
<li><a href="https://bitmovin.com/vp9-vs-hevc-h265/">HEVC vs VP9</a>: Modern codecs comparison</li>
<li>What is the <a href="https://bitmovin.com/av1/">AV1 Codec</a>?</li>
<li>Video Compression: <a href="https://bitmovin.com/encoding-definition-bitrates/">Encoding Definition and Adaptive Bitrate</a></li>
<li>What is <a href="https://bitmovin.com/adaptive-streaming/">adaptive bitrate streaming</a></li>
<li><a href="https://bitmovin.com/mkv-vs-mp4/">MP4 vs MKV</a>: Battle of the Video Formats</li>
<li><a href="https://bitmovin.com/video-streaming-models-svod-avod-tvod/">AVOD vs SVOD</a>; the “fall” of SVOD and Rise of AVOD &amp; TVOD (Video Tech Trends)</li>
<li><a href="https://bitmovin.com/dynamic-adaptive-streaming-http-mpeg-dash/">MPEG-DASH</a> (Dynamic Adaptive Streaming over HTTP)</li>
<li><a href="https://bitmovin.com/container-formats-fun-1/">Container Formats</a>: The 4 most common container formats and why they matter to you.</li>
<li><a href="https://bitmovin.com/qoe-why-quality-video-matters/">Quality of Experience</a> (QoE) in Video Technology [2022 Guide]</li>
</ul>
<p>The post <a rel="nofollow" href="https://bitmovin.com/simple-encoding-api">Introducing Bitmovin&#8217;s Simple Encoding API</a> appeared first on <a rel="nofollow" href="https://bitmovin.com">Bitmovin</a>.</p>
]]></content:encoded>
					
		
		<enclosure url="https://ftp.halifax.rwth-aachen.de/blender/demo/movies/ToS/ToS-4k-1920.mov" length="738876331" type="video/quicktime" />
<enclosure url="https://ftp.halifax.rwth-aachen.de/blender/demo/movies/ToS/ToS-4k-1920.mov" length="738876331" type="video/quicktime" />
<enclosure url="https://ftp.halifax.rwth-aachen.de/blender/demo/movies/ToS/ToS-4k-1920.mov" length="738876331" type="video/quicktime" />
<enclosure url="https://ftp.halifax.rwth-aachen.de/blender/demo/movies/ToS/ToS-4k-1920.mov" length="738876331" type="video/quicktime" />

			</item>
		<item>
		<title>Bitmovin’s Intern Series: Analyzing Docker images for optimal sizes</title>
		<link>https://bitmovin.com/docker-images-layers</link>
					<comments>https://bitmovin.com/docker-images-layers#comments</comments>
		
		<dc:creator><![CDATA[Marco Sussitz]]></dc:creator>
		<pubDate>Mon, 21 Sep 2020 08:00:05 +0000</pubDate>
				<category><![CDATA[Developers]]></category>
		<guid isPermaLink="false">https://bitmovin.com/?p=127237</guid>

					<description><![CDATA[<p>On a mission to slim down Docker images As an engineer, one thing that you should know when working with Docker images is that they can result in large files/folders. Docker has an established set of best practices that you can apply to reduce the size of your images. However, there are still some additional...</p>
<p>The post <a rel="nofollow" href="https://bitmovin.com/docker-images-layers">Bitmovin’s Intern Series: Analyzing Docker images for optimal sizes</a> appeared first on <a rel="nofollow" href="https://bitmovin.com">Bitmovin</a>.</p>
]]></description>
										<content:encoded><![CDATA[<h2><img loading="lazy" decoding="async" class="aligncenter size-large wp-image-127259" src="https://bitmovin.com/wp-content/uploads/2020/09/Blog_Analzing-Docker-1-1024x512.jpg" alt="live streaming android - Bitmovin" width="1024" height="512" srcset="https://b3148424.smushcdn.com/3148424/wp-content/uploads/2020/09/Blog_Analzing-Docker-1-300x150.jpg?lossy=2&amp;strip=1&amp;webp=1 300w, https://b3148424.smushcdn.com/3148424/wp-content/uploads/2020/09/Blog_Analzing-Docker-1.jpg?size=384x192&amp;lossy=2&amp;strip=1&amp;webp=1 384w, https://b3148424.smushcdn.com/3148424/wp-content/uploads/2020/09/Blog_Analzing-Docker-1-768x384.jpg?lossy=2&amp;strip=1&amp;webp=1 768w, https://b3148424.smushcdn.com/3148424/wp-content/uploads/2020/09/Blog_Analzing-Docker-1-1024x512.jpg?lossy=2&amp;strip=1&amp;webp=1 1024w, https://b3148424.smushcdn.com/3148424/wp-content/uploads/2020/09/Blog_Analzing-Docker-1.jpg?lossy=2&amp;strip=1&amp;webp=1 1080w" sizes="(max-width: 1024px) 100vw, 1024px" /></h2>
<h2><span style="font-weight: 400;">On a mission to slim down Docker images</span></h2>
<p><span style="font-weight: 400;">As an engineer, one thing that you should know when working with Docker images is that they can result in large files/folders. Docker has an established set of best practices that you can apply to reduce the size of your images. However, there are still some additional steps that you can take to further reduce the size of them. Using lightweight Docker images has many advantages over larger ones; ranging from bandwidth and storage decreases to performance and security improvements. Unfortunately, optimizing size without compromising functionality is much easier said than done. Today, we’ll review the steps necessary to achieve this goal.</span></p>
<h2><span style="font-weight: 400;">How to reduce docker image sizes</span></h2>
<p><span style="font-weight: 400;">The first step is to follow Docker’s </span><a href="https://docs.docker.com/develop/develop-images/dockerfile_best-practices/" rel="nofollow noopener" target="_blank"><span style="font-weight: 400;">best practices</span></a><span style="font-weight: 400;">, most importantly, only include what you will need to run your application in your image. Multi-stage builds will help keep dependencies only needed during the build stage out of the final image. In many cases, switching to a smaller base image,</span><span style="font-weight: 400;"> like </span><a href="https://alpinelinux.org" rel="nofollow noopener" target="_blank"><span style="font-weight: 400;">Alpine</span></a><span style="font-weight: 400;">, will reduce the overall image size dramatically. However, depending on your application&#8217;s needs it might be necessary to install additional dependencies so everything will work as expected. The higher complexity that your Dockerfile is and the more dependencies that you add, the harder it can get to distinguish between what your image contains and what’s essential for your application to work properly. </span><br />
<span style="font-weight: 400;">Therefore, the most logical step is to review the contents of your images to find out which dependencies take up the most space. A nice tool that’ll help simplify this task is </span><a href="https://github.com/wagoodman/dive" rel="nofollow noopener" target="_blank"><span style="font-weight: 400;">Dive</span></a><span style="font-weight: 400;">, a UI based analysis tool that lists all of the files in a Docker container, and the layer they belong to. Given that </span><span style="font-weight: 400;">manually scrolling through thousands of files is still too much labour, we built a tool that extracts the file paths, sizes, and the layer for any Docker image. However, before we jump into details about this tool, we’ll take a look at Docker images internals first.</span></p>
<h2><span style="font-weight: 400;">How do Docker images work?</span></h2>
<p><span style="font-weight: 400;">Docker uses a </span><a href="https://docs.docker.com/storage/storagedriver/" rel="nofollow noopener" target="_blank"><span style="font-weight: 400;">Union Mount File system</span></a><span style="font-weight: 400;"> to efficiently store images. The Union Mount File allows you to merge multiple File Systems into one. In Docker, a layer translates roughly into a single file system. There are various Union Mount File systems available, for example, ‘</span><a href="https://docs.docker.com/storage/storagedriver/aufs-driver/" rel="nofollow noopener" target="_blank"><span style="font-weight: 400;">auf</span></a><span style="font-weight: 400;">’ and ‘</span><a href="https://docs.docker.com/storage/storagedriver/overlayfs-driver/" rel="nofollow noopener" target="_blank"><span style="font-weight: 400;">overlay</span></a><span style="font-weight: 400;">’ each with their own advantages and disadvantages.</span><br />
<span style="font-weight: 400;">The diagram below indicates a typical layout of an image. The various layers are mounted on top of each other and are </span><i><span style="font-weight: 400;">read-only</span></i><span style="font-weight: 400;">. The topmost thin read/write layer collects any changes made to the running image.</span><br />
<figure id="attachment_127256" aria-describedby="caption-attachment-127256" style="width: 675px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="wp-image-127256 size-full" src="https://bitmovin.com/wp-content/uploads/2020/09/Docker-Image_Basic-Layout-1.jpg" alt="Docker Images _ Basic Layout_Illustrated" width="675" height="469" /><figcaption id="caption-attachment-127256" class="wp-caption-text">Typical layout of a docker image file</figcaption></figure><br />
<span style="font-weight: 400;">But where are these layers located on your machine? The </span><a href="https://docs.docker.com/engine/reference/commandline/info/" rel="nofollow noopener" target="_blank"><i><span style="font-weight: 400;">docker info</span></i></a><span style="font-weight: 400;"> command, answers this question. Among many other things, it shows which storage driver your system uses and where the files are located. </span><br />
<figure id="attachment_127257" aria-describedby="caption-attachment-127257" style="width: 422px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="wp-image-127257 size-full" src="https://bitmovin.com/wp-content/uploads/2020/09/Docker-Image_Storage-info-output-1_Code-Snippet-1.png" alt="Docker Images _Storage info output 1_Code Snippet" width="422" height="140" /><figcaption id="caption-attachment-127257" class="wp-caption-text">Docker storage info output 1</figcaption></figure><br />
<figure id="attachment_127258" aria-describedby="caption-attachment-127258" style="width: 512px" class="wp-caption aligncenter"><img loading="lazy" decoding="async" class="wp-image-127258 size-full" src="https://bitmovin.com/wp-content/uploads/2020/09/Docker-Image_Storage-info-output-2_Code-Snippet-1.jpg" alt="Docker Images _ Storage info output 2_Code Snippet" width="512" height="239" /><figcaption id="caption-attachment-127258" class="wp-caption-text">Docker storage info output 2</figcaption></figure><br />
<span style="font-weight: 400;">Before the release of Docker v1.10 finding the contents of layers on disk would have been easy because the directory names corresponded directly to the ones that the </span><i><span style="font-weight: 400;">docker history</span></i><span style="font-weight: 400;"> command returned. That means for our use case it would have been enough to parse the output of the history command and run an </span><i><span style="font-weight: 400;">ls</span></i><span style="font-weight: 400;"> for each layer. Unfortunately, we are no longer on v1.09.</span></p>
<h2><span style="font-weight: 400;">What changed after Docker v1.10</span></h2>
<p><span style="font-weight: 400;">The original and somewhat simple method had its own set of problems, the biggest one being that it was impossible to detect if an image’s contents had been tampered with. Therefore, with  v1.10, a digest derived from the content was added to identify layers. This digest changes if and when the layer content is modified, making it possible to detect any changes.</span><br />
<span style="font-weight: 400;">Another update added in v1.10 is that layers can now be shared between images that are built on different machines, further increasing storage efficiency. However, a consequence of the updates is that directory names are now disconnected from the image ID displayed by the </span><i><span style="font-weight: 400;">docker history</span></i><span style="font-weight: 400;"> command. Making our analysis (and potential implementation) much harder.</span><br />
<span style="font-weight: 400;">For additional information about Docker images please view the following blog post: </span><a href="https://windsock.io/explaining-docker-image-ids/" rel="nofollow noopener" target="_blank"><span style="font-weight: 400;">Explaining Docker Image IDs</span></a></p>
<h2><span style="font-weight: 400;">Modern problems require modern solutions</span></h2>
<p><span style="font-weight: 400;">Docker maintains manifest files for each image so it’ll know which directories need to be mounted in which order to get the desired image. With these handy files, we can connect the content of a directory to a layer. However, to directly access the </span><i><span style="font-weight: 400;">root dir</span></i><span style="font-weight: 400;"> would be terribly inconvenient, because we would need to implement special handling for the various Union Mount Systems. Fortunately, a Docker command exists that does all of the heavy lifting for you.</span></p>
<blockquote><p><i><span style="font-weight: 400;">&gt; </span></i><a href="https://docs.docker.com/engine/reference/commandline/save/" rel="nofollow noopener" target="_blank"><i><span style="font-weight: 400;">docker save</span></i></a><i><span style="font-weight: 400;"> &lt;image_id&gt;</span></i></p></blockquote>
<p><span style="font-weight: 400;">This command will generate a </span><i><span style="font-weight: 400;">tar file</span></i><span style="font-weight: 400;"> that contains all of the layers of an image and two manifest files that carry all of the information necessary to connect the various directories to their respective layers.</span></p>
<h3><span style="font-weight: 400;">Tar Files</span></h3>
<p><span style="font-weight: 400;">The first manifest file, </span><i><span style="font-weight: 400;">manifest.json</span></i><span style="font-weight: 400;">, contains the location of the various layers and the name of the other manifest file (&lt;Image_id&gt;.json).</span><br />
<img loading="lazy" decoding="async" class="aligncenter size-full wp-image-127262" src="https://bitmovin.com/wp-content/uploads/2020/09/Docker-Images-_-Manifest-Tar-Files_manifest.json_Code-Snippet.jpg" alt="Docker Images _ Manifest Tar Files_manifest.json_Code Snippet" width="512" height="81" srcset="https://b3148424.smushcdn.com/3148424/wp-content/uploads/2020/09/Docker-Images-_-Manifest-Tar-Files_manifest.json_Code-Snippet-300x47.png?lossy=2&amp;strip=1&amp;webp=1 300w, https://b3148424.smushcdn.com/3148424/wp-content/uploads/2020/09/Docker-Images-_-Manifest-Tar-Files_manifest.json_Code-Snippet.jpg?size=384x61&amp;lossy=2&amp;strip=1&amp;webp=1 384w, https://b3148424.smushcdn.com/3148424/wp-content/uploads/2020/09/Docker-Images-_-Manifest-Tar-Files_manifest.json_Code-Snippet.jpg?lossy=2&amp;strip=1&amp;webp=1 512w" sizes="(max-width: 512px) 100vw, 512px" /><br />
<span style="font-weight: 400;">The second file carries additional information like the architecture, the </span><i><span style="font-weight: 400;">entrypoint</span></i><span style="font-weight: 400;">, the layers included, and whether it’s an </span><i><span style="font-weight: 400;">empty_layer</span></i><span style="font-weight: 400;"> or not.</span><br />
<img loading="lazy" decoding="async" class="aligncenter size-full wp-image-127263" src="https://bitmovin.com/wp-content/uploads/2020/09/Docker-Images-Manifest-File_Layers_Code-Snippet.jpg" alt="Docker Images - Manifest File_Layers_Code Snippet" width="512" height="213" srcset="https://b3148424.smushcdn.com/3148424/wp-content/uploads/2020/09/Docker-Images-Manifest-File_Layers_Code-Snippet-300x125.png?lossy=2&amp;strip=1&amp;webp=1 300w, https://b3148424.smushcdn.com/3148424/wp-content/uploads/2020/09/Docker-Images-Manifest-File_Layers_Code-Snippet.jpg?size=384x160&amp;lossy=2&amp;strip=1&amp;webp=1 384w, https://b3148424.smushcdn.com/3148424/wp-content/uploads/2020/09/Docker-Images-Manifest-File_Layers_Code-Snippet.jpg?lossy=2&amp;strip=1&amp;webp=1 512w" sizes="(max-width: 512px) 100vw, 512px" /><br />
<span style="font-weight: 400;">If we ignore empty layers in the &lt;Image_id&gt;.json file, both files will show the same number of layers. We can then join them by iterating over the &lt;Image_id&gt;.json file and selecting the </span><i><span style="font-weight: 400;">created_by</span></i><span style="font-weight: 400;"> field, while concurrently iterating over the manifest.json to pick the location of the layer. This method combines the content of a layer with the command that created it.</span><br />
<span style="font-weight: 400;">You can find the Python script we created that performs all of these steps and generates a CSV with all of the </span><a href="https://github.com/bitmovin/analyze-docker" rel="nofollow noopener" target="_blank"><span style="font-weight: 400;">collected data here</span></a><span style="font-weight: 400;">.</span></p>
<h2><span style="font-weight: 400;">Summary</span></h2>
<p><span style="font-weight: 400;">We explained why it’s important to reduce the image size of your applications and showed which best practices exist. The CSV file created by our tool allows you to filter and sort the contents of your images easily and will (hopefully) find the excessive dependencies in your workflow and can be safely removed.</span></p>
<p>The post <a rel="nofollow" href="https://bitmovin.com/docker-images-layers">Bitmovin’s Intern Series: Analyzing Docker images for optimal sizes</a> appeared first on <a rel="nofollow" href="https://bitmovin.com">Bitmovin</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://bitmovin.com/docker-images-layers/feed</wfw:commentRss>
			<slash:comments>1</slash:comments>
		
		
			</item>
	</channel>
</rss>
