{"id":39921,"date":"2016-08-31T12:46:34","date_gmt":"2016-08-31T07:16:34","guid":{"rendered":"http:\/\/www.tothenew.com\/blog\/?p=39921"},"modified":"2017-06-06T16:57:00","modified_gmt":"2017-06-06T11:27:00","slug":"load-testing-hls-stream-using-jmeter","status":"publish","type":"post","link":"https:\/\/www.tothenew.com\/blog\/load-testing-hls-stream-using-jmeter\/","title":{"rendered":"Load Testing HLS Stream Using JMeter"},"content":{"rendered":"<p style=\"text-align: center\">\u00a0<img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-39955\" src=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/001banner.png\" alt=\"001banner\" width=\"680\" height=\"611\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/001banner.png 680w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/001banner-300x269.png 300w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/001banner-624x560.png 624w\" sizes=\"(max-width: 680px) 100vw, 680px\" \/><\/p>\n<h2>What is Video Streaming?<\/h2>\n<p>Although highly unlikely, but if you are wondering the meaning of <a href=\"https:\/\/en.wikipedia.org\/wiki\/Streaming_media\">video streaming<\/a>, it simply means that to play the online video, you won\u2019t need to download the video completely. It offers you other advantages like you can jump directly to a section of the video and start playing it from there. As you don\u2019t need to download the file, it saves you bandwidth if you don\u2019t intend to watch the complete video by maintaining only a small buffer of the video.<\/p>\n<h2>What is HLS Stream?<\/h2>\n<p>There are different protocols to serve videos online. The most common one is RTMP (Real Time Messaging Protocol), which is a flash based protocol. The problem with RTMP is that it uses its ports for flash media. By other ports, I mean that your web server uses port 80. But RTMP video will require a port other than 80. So if your firewall allows only port 80 traffic, then the RTMP video will not pass through your firewall. One workaround is that we can use HTTP tunneling and use RTMPT protocol, but it will be a huge performance tradeoff for the server.<\/p>\n<p>Another drawback of RTMP is that since it is a flash based protocol, it will require a flash player embedded in your browser and will not be supported in HTML5.<\/p>\n<p>Okay, it seems like we are convinced that we will not be using RTMP for our videos. So what alternatives do we have? You already guessed that it would be HLS protocol. (Since the post and this section is about HLS only.)<\/p>\n<p>HTTP Live Streaming (HLS), as the name suggests, is an HTTP-based media streaming protocol, by Apple Inc. As it is proprietary of Apple Inc., along with HTML5, it is fully supported by all IOS devices as well (RTMP was not supported by IOS devices). This protocol is adaptive, which means that it will automatically adjust the video quality according to the browser bandwidth. This was not possible (without using a streaming engine) with RTMP.<\/p>\n<h2>What is JMeter?<\/h2>\n<p>JMeter is an open source tool for performance and load testing. It can be used for <a href=\"http:\/\/www.tothenew.com\/blog\/7-things-you-must-know-about-load-testing-using-jmeter\/\" target=\"_blank\">application testing<\/a> as well as video testing. You can set up <a href=\"http:\/\/www.tothenew.com\/blog\/jmeter-master-slave-setup-in-multiple-aws-regions\/\" target=\"_blank\">JMeter as master-slave<\/a> as well. JMeter will be used to test the HLS stream in this blog post. I assume basic understanding and familiarity with JMeter.<\/p>\n<h2>JMeter and HLS Stream<\/h2>\n<p>Before proceeding with the steps of load testing HLS stream with Jmeter, Let\u2019s have a brief look at how HLS stream works.<\/p>\n<p>The HLS Stream splits the video into smaller chunks and creates a playlist for these small chunks. The playlist is downloaded as an m3u8 file, which contains the list of all the chunks in that video. In order to proceed, you need this playlist file. From this file, video chunks will be extracted. The actual video chunks are small ts files.<\/p>\n<h2>Load Testing<\/h2>\n<p><strong>Step 1: Get the m3u8 file URL<\/strong><\/p>\n<p>The m3u8 file, the playlist file for our load testing, will be the starting point for the JMeter script. How do you get URL for this file? You can use developer tools in your browser and look under <strong>Network<\/strong> tab. In the filter provided, as shown in the below image, you can search for <strong>m3u8:<\/strong><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-39953\" src=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/01.DeveloperTools1.png\" alt=\"01.DeveloperTools\" width=\"875\" height=\"347\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/01.DeveloperTools1.png 875w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/01.DeveloperTools1-300x118.png 300w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/01.DeveloperTools1-624x247.png 624w\" sizes=\"(max-width: 875px) 100vw, 875px\" \/><\/p>\n<p>Now, let\u2019s see the contents of this file. We will get this file (curl) from the URL we got above:<\/p>\n<p>[sourcecode language=&#8221;js&#8221;]$ curl &amp;amp;amp;amp;quot;http:\/\/xxx.yyy.com\/p\/1982551\/sp\/198255100\/0_cejlz2mj\/format\/applehttp\/protocol\/http\/f\/a.m3u8&amp;amp;amp;amp;quot;[\/sourcecode]<\/p>\n<p>This command will produce the following output:<\/p>\n<pre>#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=98304,RESOLUTION=128x72\r\n\r\n#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=333824,RESOLUTION=640x360\r\n\r\n#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=479232,RESOLUTION=640x360\r\n\r\n#EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=680960,RESOLUTION=640x360\r\n\r\n<\/pre>\n<p>This file gives us four new playlists. These playlists will be downloaded next, and one of these will be chosen according to the browser bandwidth. You might want to go with the highest resolution and bandwidth since you are going to load test the video.<\/p>\n<p>Now this will be your final playlist URL which you will be using in your JMeter script. Before getting our hands dirty on JMeter, let\u2019s have a look at our chosen playlist file:<\/p>\n<p>[sourcecode language=&#8221;js&#8221;]$ curl \u201chttp:\/\/xxx.yyy.com\/enc\/1982551\/sp\/198255100\/0_cejlz2mj\/flavorId\/0_hjddwmny\/name\/a.mp4\/index.m3u8\u201d[\/sourcecode]<\/p>\n<p>The output of this curl command will look like this:<\/p>\n<pre>#EXTM3U\r\n#EXT-X-TARGETDURATION:10\r\n#EXT-X-ALLOW-CACHE:YES\r\n#EXT-X-PLAYLIST-TYPE:VOD\r\n#EXT-X-KEY:METHOD=AES-128,URI=\"encryption.key\"\r\n#EXT-X-VERSION:3\r\n#EXT-X-MEDIA-SEQUENCE:1\r\n#EXTINF:2.000,\r\nseg-1-v1-a1.ts\r\n#EXTINF:2.000,\r\nseg-2-v1-a1.ts\r\n...\r\n...\r\nseg-11-v1-a1.ts\r\n#EXTINF:6.703,\r\nseg-12-v1-a1.ts\r\n#EXT-X-ENDLIST\r\n<\/pre>\n<p><strong>Step 2: Create HTTP Sampler in JMeter for the playlist URL<\/strong><\/p>\n<p>Now, we start our script by adding a thread group and an HTTP request sampler to our test plan in JMeter:<\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-39923\" src=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/02.JMeter_TestPlan.png\" alt=\"02.JMeter_TestPlan\" width=\"311\" height=\"125\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/02.JMeter_TestPlan.png 311w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/02.JMeter_TestPlan-300x120.png 300w\" sizes=\"(max-width: 311px) 100vw, 311px\" \/><\/p>\n<p>Let\u2019s call this HTTP Request as \u201cPlaylist\u201d. In this playlist, enter the server name and path as shown:<\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-39924\" src=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/03.playlist_HTTPSampler.png\" alt=\"03.playlist_HTTPSampler\" width=\"1086\" height=\"344\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/03.playlist_HTTPSampler.png 1086w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/03.playlist_HTTPSampler-300x95.png 300w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/03.playlist_HTTPSampler-1024x324.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/03.playlist_HTTPSampler-624x197.png 624w\" sizes=\"(max-width: 1086px) 100vw, 1086px\" \/><\/p>\n<p><strong>Step 3: Extract Segment list using Regular Expression Extractor<\/strong><\/p>\n<p>Now, we add a Regular Expression Extractor as the child of Playlist (Add -&gt; Post Processor -&gt; Regular Expression Extractor) and name it \u201cStreamList\u201d. This Regular Expression Extractor will extract the provided pattern and store it in an array variable which will be named under \u201cReference name\u201d as shown below. We will name it &#8220;streams&#8221;:<\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-39925\" src=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/04.RegExtractor.png\" alt=\"04.RegExtractor\" width=\"849\" height=\"293\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/04.RegExtractor.png 849w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/04.RegExtractor-300x103.png 300w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/04.RegExtractor-624x215.png 624w\" sizes=\"(max-width: 849px) 100vw, 849px\" \/><\/p>\n<p><strong>Step 4: Loop over the extracted array<\/strong><\/p>\n<p>In Step 3, we extracted the playlist in the array named \u201cstreams\u201d, next we need to add a ForEach Controller, which will loop through \u201cstreams\u201d variable. Let\u2019s name the controller as streamLoop.<\/p>\n<p>The Input variable name will be your variable name in Step 3 (\u201cstreams\u201d in our case). The values will be fetched one by one in the output variable. Let\u2019s call the output variable as \u201cchunks\u201d:<\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-39926\" src=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/05.ForEachController.png\" alt=\"05.ForEachController\" width=\"724\" height=\"228\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/05.ForEachController.png 724w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/05.ForEachController-300x94.png 300w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/05.ForEachController-624x196.png 624w\" sizes=\"(max-width: 724px) 100vw, 724px\" \/><\/p>\n<p><strong>Step 5: Add another HTTP Request Sampler for TS chunks<\/strong><\/p>\n<p>Add another HTTP Request sampler as the child of ForEach Controller created in Step 4 so that we can loop through all the video chunks extracted from the playlist.<\/p>\n<p>Enter the server name same as in previous HTTP sampler. In the Path, replace \u201cindex.m3u8\u201d (present at the end of the URL) by the variable value ${chunks} as shown in the below image:<\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-39927\" src=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/06.chunks_sampler.png\" alt=\"06.chunks_sampler\" width=\"1081\" height=\"269\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/06.chunks_sampler.png 1081w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/06.chunks_sampler-300x74.png 300w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/06.chunks_sampler-1024x254.png 1024w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/06.chunks_sampler-624x155.png 624w\" sizes=\"(max-width: 1081px) 100vw, 1081px\" \/><\/p>\n<p>And that\u2019s it. You can add the \u201cView Results Tree\u201d listener to verify the requests being sent by JMeter. You will be able to see output like this in the result tree if everything is setup correctly:<\/p>\n<p style=\"text-align: center\"><img decoding=\"async\" loading=\"lazy\" class=\"alignnone size-full wp-image-39963\" src=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/07.result.png\" alt=\"07.result\" width=\"777\" height=\"518\" srcset=\"\/blog\/wp-ttn-blog\/uploads\/2016\/08\/07.result.png 777w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/07.result-300x200.png 300w, \/blog\/wp-ttn-blog\/uploads\/2016\/08\/07.result-624x416.png 624w\" sizes=\"(max-width: 777px) 100vw, 777px\" \/><\/p>\n<h2>References:<\/h2>\n<p>https:\/\/en.wikipedia.org\/wiki\/Streaming_media<\/p>\n<p>https:\/\/www.blazemeter.com\/blog\/how-load-test-http-live-media-streaming-hls-jmeter<\/p>\n<p>https:\/\/support.jwplayer.com\/customer\/portal\/articles\/1430349-about-rtmp-streaming<\/p>\n","protected":false},"excerpt":{"rendered":"<p>\u00a0 What is Video Streaming? Although highly unlikely, but if you are wondering the meaning of video streaming, it simply means that to play the online video, you won\u2019t need to download the video completely. It offers you other advantages like you can jump directly to a section of the video and start playing it [&hellip;]<\/p>\n","protected":false},"author":931,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"iawp_total_views":83},"categories":[1818,2348,1,1816],"tags":[1892,2235,3777,378,696,698,1949,423,2223],"aioseo_notices":[],"_links":{"self":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/39921"}],"collection":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/users\/931"}],"replies":[{"embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/comments?post=39921"}],"version-history":[{"count":0,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/posts\/39921\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/media?parent=39921"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/categories?post=39921"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.tothenew.com\/blog\/wp-json\/wp\/v2\/tags?post=39921"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}