text: (window.webpackJsonp=window.webpackJsonp||[]).push([[296],{668:function(e,t,a){"use strict";a.r(t);var s=a(42),r=Object(s.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"example-hls-media-stream"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#example-hls-media-stream"}},[e._v("#")]),e._v(" Example-HLS-Media-Stream "),a("seo")],1),e._v(" "),a("p",[a("a",{attrs:{href:"https://github.com/oatpp/example-hls-media-stream",target:"_blank",rel:"noopener noreferrer"}},[e._v("Github Repository"),a("OutboundLink")],1)]),e._v(" "),a("p",[e._v("Example project how-to build HLS-streaming server using oat++ Async-API.\n"),a("em",[e._v("Live stream tested with Safari-Browser and VLC-player.")])]),e._v(" "),a("h2",{attrs:{id:"overview"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#overview"}},[e._v("#")]),e._v(" Overview")]),e._v(" "),a("p",[e._v("Server generates infinite .m3u8 playlist from the pre-generated\n"),a("code",[e._v("playlist_live.m3u8")]),e._v(" file in the "),a("code",[e._v("video")]),e._v(" folder."),a("br"),e._v("\nFile "),a("code",[e._v("video/playlist_live.m3u8")]),e._v(" together with video chunks is generated using "),a("code",[e._v("ffmpeg")]),e._v(".")]),e._v(" "),a("p",[e._v("Server is built using oat++ Async-Api and has following endpoints:")]),e._v(" "),a("ul",[a("li",[a("code",[e._v('("GET", "/", Root)')]),e._v(" - Starting html-page aka index.html")]),e._v(" "),a("li",[a("code",[e._v('("GET", "video/*", Video)')]),e._v(" - Embedded video html-page")]),e._v(" "),a("li",[a("code",[e._v('("GET", "media/live", Live)')]),e._v(" - Infinite HLS playlist for live-stream describing video chunks")]),e._v(" "),a("li",[a("code",[e._v('("GET", "media/*", Static)')]),e._v(" - Endpoint serving media files with range requests support")])]),e._v(" "),a("h3",{attrs:{id:"project-layout"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#project-layout"}},[e._v("#")]),e._v(" Project layout")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("\n|- CMakeLists.txt                       // projects CMakeLists.txt\n|- src/                                 // source folder\n|- test/                                // test folder\n|- utility/install-oatpp-modules.sh     // utility script to install required oatpp-modules.\n|\n|- video/                               // media files and playlists here\n     |- generate_pls.sh                 // example how to use ```ffmpeg``` to generate initial playlist and video chunks\n     |- playlist_live.m3u8              // playlist used to generate infinite playlist for http-live-streaming\n\n")])])]),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("- src/\n    |\n    |- controller/              // Folder containing UserController where all endpoints are declared\n    |- hls/                     // Playlist generator is here\n    |- Utils.hpp                // Utils\n    |- AppComponent.hpp         // Service config\n    |- App.cpp                  // main() is here\n    \n")])])]),a("hr"),e._v(" "),a("h3",{attrs:{id:"build-and-run"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#build-and-run"}},[e._v("#")]),e._v(" Build and Run")]),e._v(" "),a("h4",{attrs:{id:"using-cmake"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#using-cmake"}},[e._v("#")]),e._v(" Using CMake")]),e._v(" "),a("p",[a("strong",[e._v("Requires")])]),e._v(" "),a("ul",[a("li",[a("code",[e._v("oatpp")]),e._v(" module installed. You may run "),a("code",[e._v("utility/install-oatpp-modules.sh")]),e._v("\nscript to install required oatpp modules.")])]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("$ mkdir build && cd build\n$ cmake ..\n$ make \n$ ./hls-example-exe             # - run application.\n")])])]),a("h4",{attrs:{id:"in-docker"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#in-docker"}},[e._v("#")]),e._v(" In Docker")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("$ docker build -t example-hls .\n$ docker run -p 8000:8000 -t example-hls\n")])])]),a("hr"),e._v(" "),a("h3",{attrs:{id:"screenshots"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#screenshots"}},[e._v("#")]),e._v(" Screenshots")]),e._v(" "),a("div",[a("img",{attrs:{src:"https://raw.githubusercontent.com/oatpp/example-hls-media-stream/master/screenshots/screen-2.png",width:"33%"}}),e._v(" "),a("img",{attrs:{src:"https://raw.githubusercontent.com/oatpp/example-hls-media-stream/master/screenshots/screen-3.png",width:"33%"}}),e._v(" "),a("img",{attrs:{src:"https://raw.githubusercontent.com/oatpp/example-hls-media-stream/master/screenshots/screen-4.png",width:"33%"}})]),e._v(" "),a("hr"),e._v(" "),a("h2",{attrs:{id:"notes"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#notes"}},[e._v("#")]),e._v(" Notes")]),e._v(" "),a("h3",{attrs:{id:"urls"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#urls"}},[e._v("#")]),e._v(" Urls")]),e._v(" "),a("ul",[a("li",[e._v("localhost:8000 - Index page")]),e._v(" "),a("li",[e._v("localhost:8000/media/live - Live stream made from {repo}/video/video1.mp4 and {repo}/video/video2.mp4 played in the loop")])]),e._v(" "),a("h3",{attrs:{id:"files"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#files"}},[e._v("#")]),e._v(" Files")]),e._v(" "),a("ul",[a("li",[e._v("{repo}/video/playlist_live.m3u8 - playlist used for live HLS streaming")]),e._v(" "),a("li",[e._v("{repo}/video/generate_pls.sh - example script used to generate sub-playlists and video fragmets using ffmpeg tool. #EXTINF sections of sub-playlists then have to be manualy moved to playlist_live.m3u8.")])]),e._v(" "),a("h3",{attrs:{id:"note"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#note"}},[e._v("#")]),e._v(" Note")]),e._v(" "),a("p",[e._v("If app can't find playlist of video files then specify full-file-paths for {repo}/video/playlist_live.m3u8 file and {repo}/video folder in AppComponent.hpp")])])}),[],!1,null,null,null);t.default=r.exports}}]);