{"id":13508493,"url":"https://github.com/kaltura/nginx-vod-module","last_synced_at":"2025-05-14T03:11:34.570Z","repository":{"id":18589354,"uuid":"21793531","full_name":"kaltura/nginx-vod-module","owner":"kaltura","description":"NGINX-based MP4 Repackager","archived":false,"fork":false,"pushed_at":"2025-03-23T12:10:20.000Z","size":4772,"stargazers_count":2035,"open_issues_count":307,"forks_count":447,"subscribers_count":120,"default_branch":"master","last_synced_at":"2025-04-10T20:55:32.720Z","etag":null,"topics":["dash","drm","hds","hls","livestream","mp4","mss","nginx","stream","streaming","video","video-streaming","vod"],"latest_commit_sha":null,"homepage":"","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/kaltura.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2014-07-13T15:31:08.000Z","updated_at":"2025-03-31T12:54:54.000Z","dependencies_parsed_at":"2023-02-13T20:30:57.648Z","dependency_job_id":"1c8056c4-49e4-4564-8cec-6ff95a1af76a","html_url":"https://github.com/kaltura/nginx-vod-module","commit_stats":{"total_commits":907,"total_committers":33,"mean_commits":"27.484848484848484","dds":"0.22160970231532529","last_synced_commit":"26f06877b0f2a2336e59cda93a3de18d7b23a3e2"},"previous_names":[],"tags_count":38,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaltura%2Fnginx-vod-module","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaltura%2Fnginx-vod-module/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaltura%2Fnginx-vod-module/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/kaltura%2Fnginx-vod-module/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/kaltura","download_url":"https://codeload.github.com/kaltura/nginx-vod-module/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254059520,"owners_count":22007771,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dash","drm","hds","hls","livestream","mp4","mss","nginx","stream","streaming","video","video-streaming","vod"],"created_at":"2024-08-01T02:00:53.866Z","updated_at":"2025-05-14T03:11:29.560Z","avatar_url":"https://github.com/kaltura.png","language":"C","funding_links":[],"categories":["C","学习资料快速链接","DASH学习资料快速链接","HarmonyOS","video","Media Processing"],"sub_categories":["Windows Manager","Rust"],"readme":"# NGINX-based VOD Packager\n## nginx-vod-module [![Build Status](https://travis-ci.org/kaltura/nginx-vod-module.svg?branch=master)](https://travis-ci.org/kaltura/nginx-vod-module)\n\n[Join the list of organizations using this video packager project](https://github.com/kaltura/nginx-vod-module/issues/730/).\n\nFor live video streaming, please use [Media-Framework](https://github.com/kaltura/media-framework/).\n\n### Features\n\n* On-the-fly repackaging of MP4 files to DASH, HDS, HLS, MSS\n\n* Working modes:\n  1. Local - serve locally accessible files (local disk/NFS mounted)\n  2. Remote - serve files accessible via HTTP using range requests\n  3. Mapped - serve files according to a specification encoded in JSON format. The JSON can pulled from a remote server, or read from a local file\n\n* Adaptive bitrate support\n\n* Playlist support (playing several different media files one after the other) - mapped mode only\n\n* Simulated live support (generating a live stream from MP4 files) - mapped mode only\n\n* Fallback support for file not found in local/mapped modes (useful in multi-datacenter environments)\n  \n* Video codecs: H264, H265 (DASH/HLS), AV1 (DASH/HLS), VP8 (DASH), VP9 (DASH)\n\n* Audio codecs: AAC, MP3 (HLS/HDS/MSS), AC-3 (DASH/HLS), E-AC-3 (DASH/HLS), VORBIS (DASH), OPUS (DASH), FLAC (HLS), DTS (HLS)\n\n* Captions support - \n  \n  Input:\n  1. WebVTT\n  2. SRT\n  3. DFXP/TTML\n  4. CAP (Cheetah)\n  \n  Output:\n  1. DASH - either a single WebVTT or SMPTE-TT segments (configurable)\n  2. HLS - segmented WebVTT (m3u8)\n  3. MSS - converted to TTML and packaged in fragmented MP4 (no support for styling)\n\n* Audio only/video only files\n\n* Alternative audio renditions - supporting both:\n  1. Generation of manifest with different audio renditions, allowing selection on the client side\n  2. Muxing together audio and video streams from separate files / tracks - provides the ability\n\tto serve different audio renditions of a single video, without the need for any special support\n\ton the client side.\n\n* Track selection for multi audio/video MP4 files\n\n* Playback rate change - 0.5x up to 2x (requires libavcodec and libavfilter)\n\n* Source file clipping (only from I-Frame to P-frame)\n\n* Support for variable segment lengths - enabling the player to select the optimal bitrate fast,\nwithout the overhead of short segments for the whole duration of the video\n\n* Clipping of MP4 files for progressive download playback\n\n* Thumbnail capture (requires libavcodec) and resize (requires libswscale)\n\n* Volume map (requires libavcodec) - returns a CSV containing the volume level in each interval\n\n* Decryption of CENC-encrypted MP4 files (it is possible to create such files with MP4Box)\n\n* DASH: common encryption (CENC) support\n\n* MSS: PlayReady encryption support\n\n* HLS: Generation of I-frames playlist (EXT-X-I-FRAMES-ONLY)\n\n* HLS: support for AES-128 / SAMPLE-AES encryption\n\n### Limitations\n\n* Track selection and playback rate change are not supported in progressive download\n\n* I-frames playlist generation is not supported when encryption is enabled\n\n* Tested on Linux only\n\n### Compilation\n\n#### Dependencies\n\nIn general, if you have the dependencies that are required to build nginx, you should be able to build nginx-vod-module.\nHowever, some optional features of this module depend on additional packages. The module detects these packages \nduring `configure` - if a package is missing, the respective feature will be disabled.\n\nThe optional features are:\n1. Thumbnail capture \u0026 volume map - depend on ffmpeg (3.0 or newer)\n2. Audio filtering (for changing playback rate / gain) - depends on ffmpeg (3.0 or newer) and also on libfdk_aac.\n\tDue to licensing issues, libfdk_aac is not built into kaltura ffmpeg packages\n3. Encryption / decryption (DRM / HLS AES) - depends on openssl\n4. DFXP captions - depends on libxml2\n5. UTF-16 encoded SRT files - depends on iconv\n\n#### Build\n\nTo link statically against nginx, cd to nginx source directory and execute:\n\n    ./configure --add-module=/path/to/nginx-vod-module\n    make\n    make install\n\nTo compile as a dynamic module (nginx 1.9.11+), use:\n  \n\t./configure --add-dynamic-module=/path/to/nginx-vod-module\n\nIn this case, the `load_module` directive should be used in nginx.conf in order to load the module.\n\nOptional recommended settings:\n1. `--with-file-aio` - enable asynchronous I/O support, highly recommended, relevant only to local and mapped modes\n2. `--with-threads` (nginx 1.7.11+) - enable asynchronous file open using thread pool (also requires `vod_open_file_thread_pool` in nginx.conf), relevant only to local and mapped modes\n3. `--with-cc-opt=\"-O3 -mpopcnt\"` - enable additional compiler optimizations (we saw about 8% reduction in the mp4 parse time\n\tand frame processing time compared to the nginx default `-O`)\n\nDebug settings:\n1. `--with-debug` - enable debug messages (also requires passing `debug` in the `error_log` directive in nginx.conf).\n2. `--with-cc-opt=\"-O0\"` - disable compiler optimizations (for debugging with gdb)\n\nC Macro Configurations:\n1. `--with-cc-opt=\"-DNGX_VOD_MAX_TRACK_COUNT=256 -mavx2\"` - increase the maximum track count (preferably to multiples of 64). It's recommended to enable vector extensions (AVX2) as well.\n\n### Installation\n\n#### RHEL/CentOS 6/7 RPM\n```sh\n# rpm -ihv http://installrepo.kaltura.org/releases/kaltura-release.noarch.rpm\n# yum install kaltura-nginx\n```\n\n#### Debian/Ubuntu deb package\n*Ubuntu NOTE: before trying to install kaltura-nginx, you must also make sure the multiverse repo is enabled*\n\nFor Debian Wheezy [7], Debian Jessie [8], Ubuntu 14.04 and 14.10, add this repo:\n```sh\n# wget -O - http://installrepo.kaltura.org/repo/apt/debian/kaltura-deb-curr.gpg.key|apt-key add -\n# echo \"deb [arch=amd64] http://installrepo.kaltura.org/repo/apt/debian propus main\" \u003e /etc/apt/sources.list.d/kaltura.list\n```\n\nFor Ubuntu 16.04, 16.10 add this repo:\n```sh\n# wget -O - http://installrepo.kaltura.org/repo/apt/xenial/kaltura-deb-curr-256.gpg.key|apt-key add -\n# echo \"deb [arch=amd64] http://installrepo.kaltura.org/repo/apt/xenial propus main\" \u003e /etc/apt/sources.list.d/kaltura.list\n```\n\nFor Ubuntu 20.04 add this repo:\n```sh\n# wget -O - http://installrepo.kaltura.org/repo/aptn/focal/kaltura-deb-256.gpg.key|apt-key add -\n# echo \"deb [arch=amd64] http://installrepo.kaltura.org/repo/aptn/focal quasar main\" \u003e /etc/apt/sources.list.d/kaltura.list\n```\n\n\nThen install the kaltura-nginx package:\n```sh\n# apt-get update\n# apt-get install kaltura-nginx\n```\n\n\nIf you wish to make use of the following features:\n- Thumbnail capture\n- Playback rate change - 0.5x up to 2x\n\nYou will also need to install the kaltura-ffmpeg (\u003e= 3.1) package.\n\n### URL structure\n\n#### Basic URL structure\n\nThe basic structure of an nginx-vod-module URL is:\n`http://\u003cdomain\u003e/\u003clocation\u003e/\u003cfileuri\u003e/\u003cfilename\u003e`\n\nWhere:\n* domain - the domain of the nginx-vod-module server\n* location - the location specified in the nginx conf\n* fileuri - a URI to the mp4 file:\n  * local mode - the full file path is determined according to the root / alias nginx.conf directives\n  * mapped mode - the full file path is determined according to the JSON received from the upstream / local file\n  * remote mode - the mp4 file is read from upstream in chunks\n  * Note: in mapped \u0026 remote modes, the URL of the upstream request is `http://\u003cupstream\u003e/\u003clocation\u003e/\u003cfileuri\u003e?\u003cextraargs\u003e`\n  (extraargs is determined by the `vod_upstream_extra_args` parameter)\n* filename - detailed below\n\n#### Multi URL structure\n\nMulti URLs are used to encode several URLs on a single URL. A multi URL can be used to specify\nthe URLs of several different MP4 files that should be included together in a DASH MPD for example.\n\nThe structure of a multi URL is:\n`http://\u003cdomain\u003e/\u003clocation\u003e/\u003cprefix\u003e,\u003cmiddle1\u003e,\u003cmiddle2\u003e,\u003cmiddle3\u003e,\u003cpostfix\u003e.urlset/\u003cfilename\u003e`\n\nThe sample URL above represents 3 URLs:\n* `http://\u003cdomain\u003e/\u003clocation\u003e/\u003cprefix\u003e\u003cmiddle1\u003e\u003cpostfix\u003e/\u003cfilename\u003e`\n* `http://\u003cdomain\u003e/\u003clocation\u003e/\u003cprefix\u003e\u003cmiddle2\u003e\u003cpostfix\u003e/\u003cfilename\u003e`\n* `http://\u003cdomain\u003e/\u003clocation\u003e/\u003cprefix\u003e\u003cmiddle3\u003e\u003cpostfix\u003e/\u003cfilename\u003e`\n\nThe suffix `.urlset` (can be changed using `vod_multi_uri_suffix`) indicates that the URL should be treated as a multi URL.\nFor example - the URL `http://example.com/hls/videos/big_buck_bunny_,6,9,15,00k.mp4.urlset/master.m3u8` will return a manifest containing:\n* http://example.com/hls/videos/big_buck_bunny_600k.mp4/index.m3u8\n* http://example.com/hls/videos/big_buck_bunny_900k.mp4/index.m3u8\n* http://example.com/hls/videos/big_buck_bunny_1500k.mp4/index.m3u8\n\n#### URL path parameters\n\nThe following parameters are supported on the URL path:\n* clipFrom - an offset in milliseconds since the beginning of the video, where the generated stream should start. \n\tFor example, `.../clipFrom/10000/...` will generate a stream that starts 10 seconds into the video.\n* clipTo - an offset in milliseconds since the beginning of the video, where the generated stream should end.\n\tFor example, `.../clipTo/60000/...` will generate a stream truncated to 60 seconds.\n* tracks - can be used to select specific audio/video tracks. The structure of the parameter is: `v\u003cid1\u003e-v\u003cid2\u003e-a\u003cid1\u003e-a\u003cid2\u003e...`\n\tFor example, `.../tracks/v1-a1/...` will select the first video track and first audio track.\n\tThe default is to include all tracks.\n* shift - can be used to apply a timing shift to one or more streams. The structure of the parameter is: `v\u003cvshift\u003e-a\u003cashift\u003e-s\u003csshift\u003e`\n\tFor example, `.../shift/v100/...` will apply a forward shift of 100ms to the video timestamps.\n\n#### Filename structure\n\nThe structure of filename is:\n`\u003cbasename\u003e[\u003cseqparams\u003e][\u003cfileparams\u003e][\u003ctrackparams\u003e][\u003clangparams\u003e].\u003cextension\u003e`\n\nWhere:\n* basename + extension - the set of options is packager specific (the list below applies to the default settings):\n  * dash - manifest.mpd\n  * hds - manifest.f4m\n  * hls master playlist - master.m3u8\n  * hls media playlist - index.m3u8\n  * mss - manifest\n  * thumb - `thumb-\u003coffset\u003e[\u003cresizeparams\u003e].jpg` (offset is the thumbnail video offset in milliseconds)\n  * volume_map - `volume_map.csv`\n* seqparams - can be used to select specific sequences by id (provided in the mapping JSON), e.g. master-sseq1.m3u8.\n* fileparams - can be used to select specific sequences by index when using multi URLs.\n\tFor example, manifest-f1.mpd will return an MPD only from the first URL.\n* trackparams - can be used to select specific audio/video tracks.\n\tFor example, manifest-a1.f4m will return an F4M containing only the first audio stream of each sequence.\n\tThe default is to include the first audio and first video tracks of each file.\n\tThe tracks selected on the file name are AND-ed with the tracks selected with the /tracks/ path parameter.\n\tv0/a0 select all video/audio tracks respectively.\n\tThe a/v parameters can be combined with f/s, e.g. f1-v1-f2-a1 = video1 of file1 + audio1 of file2, f1-f2-v1 = video1 of file1 + video1 of file2.\n* langparams - can be used to filter audio tracks/subtitles according to their language (ISO639-3 code).\n\tFor example, master-leng.m3u8 will return only english audio tracks.\n* resizeparams - can be used to resize the returned thumbnail image. For example, thumb-1000-w150-h100.jpg captures a thumbnail\n\t1 second into the video, and resizes it to 150x100. If one of the dimensions is omitted, its value is set so that the \n\tresulting image will retain the aspect ratio of the video frame.\n\n### Mapping response format\n\nWhen configured to run in mapped mode, nginx-vod-module issues an HTTP request to a configured upstream server \nin order to receive the layout of media streams it should generate.\nThe response has to be in JSON format. \n\nThis section contains a few simple examples followed by a reference of the supported objects and fields. \nBut first, a couple of definitions:\n\n1. `Source Clip` - a set of audio and/or video frames (tracks) extracted from a single media file\n2. `Generator` - a component that can generate audio/video frames. Currently, the only supported generator is the silence generator.\n3. `Filter` - a manipulation that can be applied on audio/video frames. The following filters are supported: \n  * rate (speed) change - applies to both audio and video\n  * audio volume change\n  * mix - can be used to merge several audio tracks together, or to merge the audio of source A with the video of source B\n4. `Clip` - the result of applying zero or more filters on a set of source clips\n5. `Dynamic Clip` - a clip whose contents is not known in advance, e.g. targeted ad content\n6. `Sequence` - a set of clips that should be played one after the other. \n7. `Set` - several sequences that play together as an adaptive set, each sequence must have the same number of clips.\n\n#### Simple mapping\n\nThe JSON below maps the request URI to a single MP4 file:\n```json\n{\n\t\"sequences\": [\n\t\t{\n\t\t\t\"clips\": [\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"source\",\n\t\t\t\t\t\"path\": \"/path/to/video.mp4\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}\n```\n\nWhen using multi URLs, this is the only allowed JSON pattern. In other words, it is not\npossible to combine more complex JSONs using multi URL.\n\n#### Adaptive set\n\nAs an alternative to using multi URL, an adaptive set can be defined via JSON:\n```json\n{\n\t\"sequences\": [\n\t\t{\n\t\t\t\"clips\": [\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"source\",\n\t\t\t\t\t\"path\": \"/path/to/bitrate1.mp4\"\n\t\t\t\t}\n\t\t\t]\n\t\t},\n\t\t{\n\t\t\t\"clips\": [\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"source\",\n\t\t\t\t\t\"path\": \"/path/to/bitrate2.mp4\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}\n```\n\n#### Playlist\n\nThe JSON below will play 35 seconds of video1 followed by 22 seconds of video2:\n```json\n{\n\t\"durations\": [ 35000, 22000 ],\n\t\"sequences\": [\n\t\t{\n\t\t\t\"clips\": [\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"source\",\n\t\t\t\t\t\"path\": \"/path/to/video1.mp4\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"source\",\n\t\t\t\t\t\"path\": \"/path/to/video2.mp4\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}\n```\n\n#### Filters\n\nThe JSON below takes video1, plays it at x1.5 and mixes the audio of the result with the audio of video2,\nafter reducing it to 50% volume:\n```json\n{\n\t\"sequences\": [\n\t\t{\n\t\t\t\"clips\": [\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"mixFilter\",\n\t\t\t\t\t\"sources\": [\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"rateFilter\",\n\t\t\t\t\t\t\t\"rate\": 1.5,\n\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\"type\": \"source\",\n\t\t\t\t\t\t\t\t\"path\": \"/path/to/video1.mp4\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\t\"type\": \"gainFilter\",\n\t\t\t\t\t\t\t\"gain\": 0.5,\n\t\t\t\t\t\t\t\"source\": {\n\t\t\t\t\t\t\t\t\"type\": \"source\",\n\t\t\t\t\t\t\t\t\"path\": \"/path/to/video2.mp4\",\n\t\t\t\t\t\t\t\t\"tracks\": \"a1\"\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t]\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}\n```\n\n#### Continuous live\n\nThe JSON below is a sample of a continuous live stream (=a live stream in which all videos have exactly the same encoding parameters).\nIn practice, this JSON will have to be generated by some script, since it is time dependent.\n(see test/playlist.php for a sample implementation)\n```json\n{\n\t\"playlistType\": \"live\",\n\t\"discontinuity\": false,\n\t\"segmentBaseTime\": 1451904060000,\n\t\"firstClipTime\": 1451917506000,\n\t\"durations\": [83000, 83000],\n\t\"sequences\": [\n\t\t{\n\t\t\t\"clips\": [\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"source\",\n\t\t\t\t\t\"path\": \"/path/to/video1.mp4\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"source\",\n\t\t\t\t\t\"path\": \"/path/to/video2.mp4\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}\n```\n\n#### Non-continuous live\n\nThe JSON below is a sample of a non-continuous live stream (=a live stream in which the videos have different encoding parameters).\nIn practice, this JSON will have to be generated by some script, since it is time dependent \n(see test/playlist.php for a sample implementation)\n```json\n{\n\t\"playlistType\": \"live\",\n\t\"discontinuity\": true,\n\t\"initialClipIndex\": 171,\n\t\"initialSegmentIndex\": 153,\n\t\"firstClipTime\": 1451918170000,\n\t\"durations\": [83000, 83000],\n\t\"sequences\": [\n\t\t{\n\t\t\t\"clips\": [\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"source\",\n\t\t\t\t\t\"path\": \"/path/to/video1.mp4\"\n\t\t\t\t},\n\t\t\t\t{\n\t\t\t\t\t\"type\": \"source\",\n\t\t\t\t\t\"path\": \"/path/to/video2.mp4\"\n\t\t\t\t}\n\t\t\t]\n\t\t}\n\t]\n}\n```\n\n### Mapping reference\n\n#### Set (top level object in the mapping JSON)\n\nMandatory fields:\n* `sequences` - array of Sequence objects. \n\tThe mapping has to contain at least one sequence and up to 32 sequences.\n\t\nOptional fields:\n* `id` - a string that identifies the set. The id can be retrieved by `$vod_set_id`.\n* `playlistType` - string, can be set to `live`, `vod` or `event` (only supported for HLS playlists), default is `vod`.\n* `durations` - an array of integers representing clip durations in milliseconds.\n\tThis field is mandatory if the mapping contains more than a single clip per sequence.\n\tIf specified, this array must contain at least one element and up to 128 elements.\n* `discontinuity` - boolean, indicates whether the different clips in each sequence have\n\tdifferent media parameters. This field has different manifestations according to the \n\tdelivery protocol - a value of true will generate `#EXT-X-DISCONTINUITY` in HLS, \n\tand a multi period MPD in DASH. The default value is true, set to false only if the media\n\tfiles were transcoded with exactly the same parameters (in AVC for example, \n\tthe clips should have exactly the same SPS/PPS).\n* `segmentDuration` - integer, sets the segment duration in milliseconds. This field, \n\tif specified, takes priority over the value set in `vod_segment_duration`.\n* `consistentSequenceMediaInfo` - boolean, currently affects only DASH. When set to true (default)\n\tthe MPD will report the same media parameters in each period element. Setting to false\n\tcan have severe performance implications for long sequences (nginx-vod-module has \n\tto read the media info of all clips included in the mapping in order to generate the MPD)\n* `referenceClipIndex` - integer, sets the (1-based) index of the clip that should be used \n\tto retrieve the video metadata for manifest requests (codec, width, height etc.)\n\tIf `consistentSequenceMediaInfo` is set to false, this parameter has no effect -\n\tall clips are parsed. If this parameter is not specified, nginx-vod-module uses the last clip \n\tby default.\n* `notifications` - array of notification objects (see below), when a segment is requested,\n\tall the notifications that fall between the start/end times of the segment are fired.\n\tthe notifications must be ordered in an increasing offset order.\n* `clipFrom` - integer, contains a timestamp indicating where the returned stream should start.\n\tSetting this parameter is equivalent to passing /clipFrom/ on the URL.\n* `clipTo` - integer, contains a timestamp indicating where the returned stream should end.\n\tSetting this parameter is equivalent to passing /clipTo/ on the URL.\n* `cache` - boolean, if set to false, the mapping response will not be saved to cache (vod_mapping_cache).\n\tThe default value is true.\n* `closedCaptions` - array of closed captions objects (see below), containing languages and ids\n\tof any embedded CEA-608 / CEA-708 captions. If an empty array is provided, the module will output\n\t`CLOSED-CAPTIONS=NONE` on each `EXT-X-STREAM-INF` tag. If the list does not appear in the JSON, the \n\tmodule will not output any `CLOSED-CAPTIONS` fields in the playlist.\n\t\nLive fields:\n* `firstClipTime` - integer, mandatory for all live playlists unless `clipTimes` is specified.\n\tContains the absolute time of the first clip in the playlist, in milliseconds since the epoch (unixtime x 1000)\n* `clipTimes` - array of integers, sets the absolute time of all the clips in the playlist, \n\tin milliseconds since the epoch (unixtime x 1000). This field can be used only when \n\t`discontinuity` is set to true. The timestamps may contain gaps, but they are not allowed to overlap\n\t(`clipTimes[n + 1] \u003e= clipTimes[n] + durations[n]`)\n* `segmentBaseTime` - integer, mandatory for continuous live streams, contains the absolute\n\ttime of the first segment of the stream, in milliseconds since the epoch (unixtime x 1000).\n\tThis value must not change during playback.\n\tFor discontinuous live streams, this field is optional:\n\t* if not set, sequential segment indexes will be used throughout the playlist.\n\t\tIn this case, the upstream server generating the mapping json has to maintain state,\n\t\tand update initialSegmentIndex every time a clip is removed from the playlist.\n\t* if set, the timing gaps between clips must not be lower than `vod_segment_duration`.\n* `firstClipStartOffset` - integer, optional, measured in milliseconds. This field contains the\n\tdifference between first clip time, and the original start time of the first clip -\n\tthe time it had when it was initially added (before the live window shifted)\n* `initialClipIndex` - integer, mandatory for non-continuous live streams that mix videos having\n\tdifferent encoding parameters (SPS/PPS), contains the index of the first clip in the playlist. \n\tWhenever a clip is pushed out of the head of the playlist, this value must be incremented by one.\n* `initialSegmentIndex` - integer, mandatory for live streams that do not set `segmentBaseTime`, \n\tcontains the index of the first segment in the playlist. Whenever a clip is pushed out of the head of\n\tthe playlist, this value must be incremented by the number of segments in the clip.\n* `presentationEndTime` - integer, optional, measured in milliseconds since the epoch.\n\twhen supplied, the module will compare the current time to the supplied value, \n\tand signal the end of the live presentation if `presentationEndTime` has passed. \n\tIn HLS, for example, this parameter controls whether an `#EXT-X-ENDLIST` tag should be \n\tincluded in the media playlist.\n\tWhen the parameter is not supplied, the module will not signal live presentation end.\n* `expirationTime` - integer, optional, measured in milliseconds since the epoch.\n\twhen supplied, the module will compare the current time to the supplied value, \n\tand if `expirationTime` has passed, the module will return a 404 error for manifest requests \n\t(segment requests will continue to be served).\n\twhen both presentationEndTime and expirationTime have passed, presentationEndTime takes\n\tpriority, i.e. manifest requests will be served and signal presentation end.\n* `liveWindowDuration` - integer, optional, provides a way to override `vod_live_window_duration`\n\tspecified in the configuration. If the value exceeds the absolute value specified in \n\t`vod_live_window_duration`, it is ignored.\n* `timeOffset` - integer, sets an offset that should be applied to the server clock when serving\n\tlive requests. This parameter can be used to test future/past events.\n\t\n#### Sequence\n\nMandatory fields:\n* `clips` - array of Clip objects (mandatory). The number of elements must match the number\n\tthe durations array specified on the set. If the durations array is not specified,\n\tthe clips array must contain a single element.\n\t\nOptional fields:\n* `id` - a string that identifies the sequence. The id can be retrieved by `$vod_sequence_id`.\n* `language` - a 3-letter (ISO-639-2) language code, this field takes priority over any language\n\tspecified on the media file (MP4 mdhd atom)\n* `label` - a friendly string that identifies the sequence. If a language is specified,\n\ta default label will be automatically derived by it - e.g. if language is `ita`, \n\tby default `italiano` will be used as the label.\n* `default` - a boolean that sets the value of the DEFAULT attribute of EXT-X-MEDIA tags using this sequence.\n\tIf not specified, the first EXT-X-MEDIA tag in each group returns DEFAULT=YES, while the others return DEFAULT=NO.\n* `bitrate` - an object that can be used to set the bitrate for the different media types,\n\tin bits per second. For example, `{\"v\": 900000, \"a\": 64000}`. If the bitrate is not supplied,\n\tnginx-vod-module will estimate it based on the last clip in the sequence.\n* `avg_bitrate` - an object that can be used to set the average bitrate for the different media types,\n\tin bits per second. See `bitrate` above for a sample object. If specified, the module will use\n\tthe value to populate the AVERAGE-BANDWIDTH attribute of `#EXT-X-STREAM-INF` in HLS.\n\n#### Clip (abstract)\n\nMandatory fields:\n* `type` - a string that defines the type of the clip. Allowed values are:\n\t* source\n\t* rateFilter\n\t* mixFilter\n\t* gainFilter\n\t* silence\n\t* concat\n\t* dynamic\n\nOptional fields:\n* `keyFrameDurations` - array of integers, containing the durations in milliseconds of the video key frames\n\tin the clip. This property can only be supplied on the top level clips of each sequence,\n\tsupplying this property on nested clips has no effect.\n\tSupplying the key frame durations enables the module to both:\n\t1. align the segments to key frames \n\t2. report the correct segment durations in the manifest - providing an alternative to setting\n\t\t`vod_manifest_segment_durations_mode` to `accurate`, which is not supported for multi clip\n\t\tmedia sets (for performance reasons).\n* `firstKeyFrameOffset` - integer, offset of the first video key frame in the clip, \n\tmeasured in milliseconds relative to `firstClipTime`. Defaults to 0 if not supplied.\n\n#### Source clip\n\nMandatory fields:\n* `type` - a string with the value `source`\n* `path` - a string containing the path of the MP4 file. The string `\"empty\"` can be used to represent\n\tan empty captions file (useful in case only some videos in a playlist have captions)\n\nOptional fields:\n* `id` - a string that identifies the source clip\n* `sourceType` - sets the interface that should be used to read the MP4 file, allowed values are:\n\t`file` and `http`. By default, the module uses `http` if `vod_remote_upstream_location` is set,\n\tand `file` otherwise.\n* `tracks` - a string that specifies the tracks that should be used, the default is \"v1-a1\",\n\twhich means the first video track and the first audio track\n* `clipFrom` - an integer that specifies an offset in milliseconds, from the beginning of the \n\tmedia file, from which to start loading frames\n* `encryptionKey` - a base64 encoded string containing the key (128/192/256 bit) that should be used\n\tto decrypt the file.\n* `encryptionIv` - a base64 encoded string containing the iv (128 bit) that should be used\n\tto decrypt the file.\n* `encryptionScheme` - the encryption scheme that was used to encrypt the file. Currently,\n\tonly two schemes are supported - `cenc` for MP4 files, `aes-cbc` for caption files.\n\n#### Rate filter clip\n\nMandatory fields:\n* `type` - a string with the value `rateFilter`\n* `rate` - a float that specified the acceleration factor, e.g. a value of 2 means double speed.\n\tAllowed values are in the range 0.5 - 2 with up to two decimal points\n* `source` - a clip object on which to perform the rate filtering\n\n#### Gain filter clip\n\nMandatory fields:\n* `type` - a string with the value `gainFilter`\n* `gain` - a float that specified the amplification factor, e.g. a value of 2 means twice as loud.\n\tThe gain must be positive with up to two decimal points\n* `source` - a clip object on which to perform the gain filtering\n\n#### Mix filter clip\n\nMandatory fields:\n* `type` - a string with the value `mixFilter`\n* `sources` - an array of Clip objects to mix. This array must contain at least one clip and\n\tup to 32 clips.\n\n#### Concat clip\n\nMandatory fields:\n* `type` - a string with the value `concat`\n* `durations` - an array of integers representing MP4 durations in milliseconds,\n\tthis array must match the `paths` array in count and order.\n\nOptional fields:\n* `paths` - an array of strings, containing the paths of the MP4 files. Either `paths` or `clipIds` must be specified.\n* `clipIds` - an array of strings, containing the ids of source clips. \n\tThe ids are translated to paths by issuing a request to the uri specified in `vod_source_clip_map_uri`.\n\tEither `paths` or `clipIds` must be specified.\n* `tracks` - a string that specifies the tracks that should be used, the default is \"v1-a1\",\n\twhich means the first video track and the first audio track\n* `offset` - an integer in milliseconds that indicates the timestamp offset of the \n\tfirst frame in the concatenated stream relative to the clip start time\n* `basePath` - a string that should be added as a prefix to all the paths\n* `notifications` - array of notification objects (see below), when a segment is requested,\n\tall the notifications that fall between the start/end times of the segment are fired.\n\tthe notifications must be ordered in an increasing offset order.\n\n#### Dynamic clip\n\nMandatory fields:\n* `type` - a string with the value `dynamic`\n* `id` - a string that uniquely identifies the dynamic clip, used for mapping the clip to its content\n\n#### Notification\n\nMandatory fields:\n* `offset` - an integer in milliseconds that indicates the time in which the notification should be fired.\n\twhen the notification object is contained in the media set, `offset` is relative to `firstClipTime`\n\t(0 for vod). when the notification object is contained in a concat clip, `offset` is relative to\n\tthe beginning of the concat clip.\n* `id` - a string that identifies the notification, this id can be referenced by `vod_notification_uri`\n\tusing the variable `$vod_notification_id`\n\n#### Closed Captions\n\nMandatory fields:\n* `id` - a string that identifies the embedded captions. This will become the `INSTREAM-ID` field and must\nhave one of the following values: `CC1`, `CC3`, `CC3`, `CC4`, or `SERVICEn`, where `n` is between 1 and 63.\n* `label` - a friendly string that indicates the language of the closed caption track.\n\nOptional fields:\n* `language` - a 3-letter (ISO-639-2) language code that indicates the language of the closed caption track.\n\n\n### Security\n\n#### Authorization\n\n##### CDN-based delivery\n\nMedia packaged by nginx-vod-module can be protected using CDN tokens, this works as follows:\n* Some application authenticates the user and decides whether the user should be allowed \n\tto watch a specific video. If the user is allowed, the application generates a tokenized\n\tURL for the manifest of the video.\n* The CDN validates the token, and if found to be valid, forwards the request to nginx-vod-module \n\ton the origin. \n* The nginx server builds the manifest response and generates tokens for the segment URLs\n\tcontained inside it. The module https://github.com/kaltura/nginx-secure-token-module can\n\tbe used to accomplish this task, it currently support Akamai tokens and CloudFront tokens.\n\tSee the readme of this module for more details.\n* The CDN validates the token on each segment that is requested.\n\nIn this setup it also highly recommended to block direct access to the origin server by\nauthenticating the CDN requests. Without this protection, a user who somehow gets the address\nof the origin will be able to bypass the CDN token enforcement. If using Akamai, this can\nbe accomplished using https://github.com/refractalize/nginx_mod_akamai_g2o.\nFor other CDNs, it may be possible to configure the CDN to send a secret header to the origin\nand then simply enforce the header using an nginx if statement:\n```c\n\t\tif ($http_x_secret_origin_header != \"secret value\") {\n\t\t\treturn 403;\n\t\t}\n```\n\nIn addition to the above, most CDNs support other access control settings, such as geo-location.\nThese restrictions are completely transparent to the origin and should work well. \n\n##### Direct delivery\n\nDeployments in which the media is pulled directly from nginx-vod-module can protect the media\nusing nginx access control directives, such `allow`, `deny`, or `access_by_lua` (for more complex\nscenarios).\n\nIn addition, it is possible to build a token based solution (as detailed in the previous section) \nwithout a CDN, by having the nginx server validate the token. \nThe module https://github.com/kaltura/nginx-akamai-token-validate-module can be used\nto validate Akamai tokens. Locations on which the module is enabled will return 403 unless the \nrequest contains a valid Akamai token. See the readme of this module for more details.\n\n#### URL encryption\n\nAs an alternative to tokenization, URL encryption can be used to prevent an attacker from being\nable to craft a playable URL. URL encryption can be implemented with \nhttps://github.com/kaltura/nginx-secure-token-module, and is supported for HLS and DASH (with \nmanifest format set to segmentlist). \n\nIn terms of security, the main advantage of CDN tokens over URL encryption is that CDN tokens\nusually expire, while encrypted URLs do not (someone who obtains a playable URL will be able to\nuse it indefinitely)\n\n#### Media encryption\n\nNginx-vod-module supports AES-128 and SAMPLE-AES HLS encryption schemes. The main difference between\nmedia encryption and DRM (detailed below) is the mechanism used to transfer the encryption key to \nthe client. With media encryption the key is fetched by the client by performing a simple GET request\nto nginx-vod-module, while with DRM the key is returned inside a vendor specific license response.\n\nMedia encryption reduces the problem of securing the media to the need to secure the encryption key. \nThe media segment URLs (which compose the vast majority of the traffic) can be completely unprotected, \nand easily cacheable by any proxies between the client and servers (unlike tokenization). \nThe encryption key request can then be protected using one of the methods mentioned above (CDN tokens,\nnginx access rules etc.). \n\nIn addition, it is possible to configure nginx-vod-module to return the encryption key over HTTPS\nwhile having the segments delivered over HTTP. The way to configure this is to set `vod_segments_base_url`\nto `http://nginx-vod-host` and set `vod_base_url` to `https://nginx-vod-host`.\n\n#### DRM\n\nNginx-vod-module has the ability to perform on-the-fly encryption for MPEG DASH (CENC), MSS Play Ready and FairPlay HLS.\nAs in the case of media encryption, the encryption is performed while serving a video/audio segment to the client, \ntherefore, when working with DRM it is recommended not to serve the content directly from nginx-vod-module to end-users.\nA more scalable architecture would be to use proxy servers or a CDN in order to cache the encrypted segments.\n\nIn order to perform the encryption, nginx-vod-module needs several parameters, including key \u0026 key_id, these parameters\nare fetched from an external server via HTTP GET requests.\nThe `vod_drm_upstream_location` parameter specifies an nginx location that is used to access the DRM server,\nand the request uri is configured using `vod_drm_request_uri` (this parameter can include nginx variables). \nThe response of the DRM server is a JSON, with the following format:\n\n```json\n[{\n\t\"pssh\": [{\n\t\t\t\"data\": \"CAESEGMyZjg2MTczN2NjNGYzODIaB2thbHR1cmEiCjBfbmptaWlwbXAqBVNEX0hE\", \n\t\t\t\"uuid\": \"edef8ba9-79d6-4ace-a3c8-27dcd51d21ed\"\n\t\t}], \n\t\"key\": \"GzoNU9Dfwc//Iq3/zbzMUw==\", \n\t\"key_id\": \"YzJmODYxNzM3Y2M0ZjM4Mg==\"\n}]\n```\n\n* `pssh.data` - base64 encoded binary data, the format of this data is drm vendor specific\n* `pssh.uuid` - the drm system UUID, in this case, edef8ba9-79d6-4ace-a3c8-27dcd51d21ed stands for Widevine\n* `key` - base64 encoded encryption key (128 bit)\n* `key_id` - base64 encoded key identifier (128 bit)\n* `iv` - optional base64 encoded initialization vector (128 bit). The IV is currently used only in HLS (FairPlay), \n\tin the other protocols an IV is generated automatically by nginx-vod-module.\n\n##### Sample configurations\n\nApple FairPlay HLS:\n```nginx\nlocation ~ ^/fpshls/p/\\d+/(sp/\\d+/)?serveFlavor/entryId/([^/]+)/(.*) {\n\tvod hls;\n\tvod_hls_encryption_method sample-aes;\n\tvod_hls_encryption_key_uri \"skd://entry-$2\";\n\tvod_hls_encryption_key_format \"com.apple.streamingkeydelivery\";\n\tvod_hls_encryption_key_format_versions \"1\";\n\n\tvod_drm_enabled on;\n\tvod_drm_request_uri \"/udrm/system/ovp/$vod_suburi\";\n\n\tvod_last_modified_types *;\n\tadd_header Access-Control-Allow-Headers '*';\n\tadd_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range';\n\tadd_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';\n\tadd_header Access-Control-Allow-Origin '*';\n\texpires 100d;\n}\n```\n\nCommon Encryption HLS:\n```nginx\nlocation ~ ^/cenchls/p/\\d+/(sp/\\d+/)?serveFlavor/entryId/([^/]+)/(.*) {\n\tvod hls;\n\tvod_hls_encryption_method sample-aes-cenc;\n\tvod_hls_encryption_key_format \"urn:uuid:edef8ba9-79d6-4ace-a3c8-27dcd51d21ed\";\n\tvod_hls_encryption_key_format_versions \"1\";\n\n\tvod_drm_enabled on;\n\tvod_drm_request_uri \"/udrm/system/ovp/$vod_suburi\";\n\n\tvod_last_modified_types *;\n\tadd_header Access-Control-Allow-Headers '*';\n\tadd_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range';\n\tadd_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';\n\tadd_header Access-Control-Allow-Origin '*';\n\texpires 100d;\n}\n```\n\n##### Verified configurations\n\nFollowing is a list of configurations that were tested and found working:\n* DASH/CENC with PlayReady \u0026 Widevine PSSH together\n* MSS PlayReady\n* HLS FairPlay\n\n### Performance recommendations\n\n1. For medium/large scale deployments, don't have users play the videos directly from nginx-vod-module.\n\tSince all the different streaming protocols supported by nginx vod are HTTP based, they can be cached by standard HTTP proxies / CDNs. \n\tFor medium scale add a layer of caching proxies between the vod module and the end users \n\t(can use standard nginx servers with proxy_pass \u0026 proxy_cache). \n\tFor large scale deployments, it is recommended to use a CDN (such as Akamai, Level3 etc.). \n\t\n\tIn general, it's best to have nginx vod as close as possible to where the mp4 files are stored, \n\tand have the caching proxies as close as possible to the end users.\n2. Enable nginx-vod-module caches:\n\t* `vod_metadata_cache` - saves the need to re-read the video metadata for each segment. This cache should be rather large, in the order of GBs.\n\t* `vod_response_cache` - saves the responses of manifest requests. This cache may not be required when using a second layer of caching servers before nginx vod. \n\t\tNo need to allocate a large buffer for this cache, 128M is probably more than enough for most deployments.\n\t* `vod_mapping_cache` - for mapped mode only, few MBs is usually enough.\n\t* nginx's open_file_cache - caches open file handles.\n\n\tThe hit/miss ratios of these caches can be tracked by enabling performance counters (`vod_performance_counters`)\n\tand setting up a status page for nginx vod (`vod_status`)\n3. In local \u0026 mapped modes, enable aio. - nginx has to be compiled with aio support, and it has to be enabled in nginx conf (aio on). \n\tYou can verify it works by looking at the performance counters on the vod status page - read_file (aio off) vs. async_read_file (aio on)\n4. In local \u0026 mapped modes, enable asynchronous file open - nginx has to be compiled with threads support, and `vod_open_file_thread_pool`\n\thas to be specified in nginx.conf. You can verify it works by looking at the performance counters on the vod status page - \n\topen_file vs. async_open_file. Note that open_file may be nonzero with vod_open_file_thread_pool enabled, due to the open file cache - \n\topen requests that are served from cache will be counted as synchronous open_file.\n5. When using DRM enabled DASH/MSS, if the video files have a single nalu per frame, set `vod_min_single_nalu_per_frame_segment` to non-zero.\n6. The muxing overhead of the streams generated by this module can be reduced by changing the following parameters:\n\t* HDS - set `vod_hds_generate_moof_atom` to off\n\t* HLS - set `vod_hls_mpegts_align_frames` to off and `vod_hls_mpegts_interleave_frames` to on\n7. Enable gzip compression on manifest responses - \n\n\t`gzip_types application/vnd.apple.mpegurl video/f4m application/dash+xml text/xml`\n8. Apply common nginx performance best practices, such as tcp_nodelay=on, client_header_timeout etc.\n\n### Configuration directives - base\n\n#### vod\n* **syntax**: `vod segmenter`\n* **default**: `n/a`\n* **context**: `location`\n\nEnables the nginx-vod module on the enclosing location. \nThe allowed values for `segmenter` are:\n\n1. `none` - serves the MP4 files as is / clipped\n2. `dash` - Dynamic Adaptive Streaming over HTTP packager\n3. `hds` - Adobe HTTP Dynamic Streaming packager\n4. `hls` - Apple HTTP Live Streaming packager\n5. `mss` - Microsoft Smooth Streaming packager\n6. `thumb` - thumbnail capture\n7. `volume_map` - audio volume map\n\n#### vod_mode\n* **syntax**: `vod_mode mode`\n* **default**: `local`\n* **context**: `http`, `server`, `location`\n\nSets the file access mode - local, remote or mapped (see the features section above for more details)\n\n#### vod_status\n* **syntax**: `vod_status`\n* **default**: `n/a`\n* **context**: `location`\n\nEnables the nginx-vod status page on the enclosing location. \nThe following query params are supported:\n* `?reset=1` - resets the performance counters and cache stats.\n* `?format=prom` - returns the output in format compatible with Prometheus (the default format is XML).\n\n### Configuration directives - segmentation\n\n#### vod_segment_duration\n* **syntax**: `vod_segment_duration duration`\n* **default**: `10s`\n* **context**: `http`, `server`, `location`\n\nSets the segment duration in milliseconds. It is highly recommended to use a segment duration that is a multiple of the GOP duration.\nIf the segment duration is not a multiple of GOP duration, and `vod_align_segments_to_key_frames` is enabled, there could be significant\ndifferences between the segment duration that is reported in the manifest and the actual segment duration. This could also lead to\nthe appearance of empty segments within the stream.\n\n#### vod_live_window_duration\n* **syntax**: `vod_live_window_duration duration`\n* **default**: `30000`\n* **context**: `http`, `server`, `location`\n\nSets the total duration in milliseconds of the segments that should be returned in a live manifest.\nIf the value is positive, nginx vod returns a range of maximum `vod_live_window_duration` milliseconds, ending at the current server time.\nIf the value is negative, nginx vod returns a range of maximum `-vod_live_window_duration` milliseconds from the end of the mapping json.\nIf the value is set to zero, the live manifest will contain all the segments that are fully contained in the mapping json time frame.\n\n#### vod_force_playlist_type_vod\n* **syntax**: `vod_force_playlist_type_vod on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nGenerate a vod stream even when the media set has `playlistType=live`. \nEnabling this setting has the following effects:\n1. Frame timestamps will be continuous and start from zero\n2. Segment indexes will start from one\n3. In case of HLS, the returned manifest will have both `#EXT-X-PLAYLIST-TYPE:VOD` and `#EXT-X-ENDLIST`\n\nThis can be useful for clipping vod sections out of a live stream.\n\n#### vod_force_continuous_timestamps\n* **syntax**: `vod_force_continuous_timestamps on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nGenerate continuous timestamps even when the media set has gaps (gaps can created by the use of `clipTimes`)\nIf ID3 timestamps are enabled (`vod_hls_mpegts_output_id3_timestamps`), they contain the original timestamps that were set in `clipTimes`.\n\n#### vod_bootstrap_segment_durations\n* **syntax**: `vod_bootstrap_segment_durations duration`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nAdds a bootstrap segment duration in milliseconds. This setting can be used to make the first few segments\nshorter than the default segment duration, thus making the adaptive bitrate selection kick-in earlier without \nthe overhead of short segments throughout the video.\n\n#### vod_align_segments_to_key_frames\n* **syntax**: `vod_align_segments_to_key_frames on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, the module forces all segments to start with a key frame. Enabling this setting can lead to differences\nbetween the actual segment durations and the durations reported in the manifest (unless `vod_manifest_segment_durations_mode` is set to accurate).\n\n#### vod_segment_count_policy\n* **syntax**: `vod_segment_count_policy last_short/last_long/last_rounded`\n* **default**: `last_short`\n* **context**: `http`, `server`, `location`\n\nConfigures the policy for calculating the segment count, for segment_duration = 10 seconds:\n* last_short - a file of 33 sec is partitioned as - 10, 10, 10, 3\n* last_long - a file of 33 sec is partitioned as - 10, 10, 13\n* last_rounded - a file of 33 sec is partitioned as - 10, 10, 13, a file of 38 sec is partitioned as 10, 10, 10, 8\n\n#### vod_manifest_duration_policy\n* **syntax**: `vod_manifest_duration_policy min/max`\n* **default**: `max`\n* **context**: `http`, `server`, `location`\n\nConfigures the policy for calculating the duration of a manifest containing multiple streams:\n* max - uses the maximum stream duration (default)\n* min - uses the minimum non-zero stream duration\n\n#### vod_manifest_segment_durations_mode\n* **syntax**: `vod_manifest_segment_durations_mode estimate/accurate`\n* **default**: `estimate`\n* **context**: `http`, `server`, `location`\n\nConfigures the calculation mode of segment durations within manifest requests:\n* estimate - reports the duration as configured in nginx.conf, e.g. if `vod_segment_duration` has the value 10000,\nan HLS manifest will contain #EXTINF:10\n* accurate - reports the exact duration of the segment, taking into account the frame durations, e.g. for a \nframe rate of 29.97 and 10 second segments it will report the first segment as 10.01. accurate mode also\ntakes into account the key frame alignment, in case `vod_align_segments_to_key_frames` is on\n\n#### vod_media_set_override_json\n* **syntax**: `vod_media_set_override_json json`\n* **default**: `{}`\n* **context**: `http`, `server`, `location`\n\nThis parameter provides a way to override portions of the media set JSON (mapped mode only).\nFor example, `vod_media_set_override_json '{\"clipTo\":20000}'` clips the media set to 20 sec.\nThe parameter value can contain variables.\n\n### Configuration directives - upstream\n\n#### vod_upstream_location\n* **syntax**: `vod_upstream_location location`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets an nginx location that is used to read the MP4 file (remote mode) or mapping the request URI (mapped mode).\n\n#### vod_remote_upstream_location\n* **syntax**: `vod_remote_upstream_location location`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets an nginx location that is used to read the MP4 file on remote or mapped mode. If this directive is set on mapped mode, the module reads \nthe MP4 files over HTTP, treating the paths in the mapping JSON as URIs (the default behavior is to read from local files)\n\n#### vod_max_upstream_headers_size\n* **syntax**: `vod_max_upstream_headers_size size`\n* **default**: `4k`\n* **context**: `http`, `server`, `location`\n\nSets the size that is allocated for holding the response headers when issuing upstream requests (to vod_xxx_upstream_location).\n\n#### vod_upstream_extra_args\n* **syntax**: `vod_upstream_extra_args \"arg1=value1\u0026arg2=value2\u0026...\"`\n* **default**: `empty`\n* **context**: `http`, `server`, `location`\n\nExtra query string arguments that should be added to the upstream request (remote/mapped modes only).\nThe parameter value can contain variables.\n\n#### vod_media_set_map_uri\n* **syntax**: `vod_media_set_map_uri uri`\n* **default**: `$vod_suburi`\n* **context**: `http`, `server`, `location`\n\nSets the uri of media set mapping requests, the parameter value can contain variables.\nIn case of multi url, `$vod_suburi` will be the current sub uri (a separate request is issued per sub URL)\n\n#### vod_path_response_prefix\n* **syntax**: `vod_path_response_prefix prefix`\n* **default**: `{\"sequences\":[{\"clips\":[{\"type\":\"source\",\"path\":\"`\n* **context**: `http`, `server`, `location`\n\nSets the prefix that is expected in URI mapping responses (mapped mode only).\n\n#### vod_path_response_postfix\n* **syntax**: `vod_path_response_postfix postfix`\n* **default**: `\"}]}]}`\n* **context**: `http`, `server`, `location`\n\nSets the postfix that is expected in URI mapping responses (mapped mode only).\n\n#### vod_max_mapping_response_size\n* **syntax**: `vod_max_mapping_response_size length`\n* **default**: `1K`\n* **context**: `http`, `server`, `location`\n\nSets the maximum length of a path returned from upstream (mapped mode only).\n\n### Configuration directives - fallback\n\n#### vod_fallback_upstream_location\n* **syntax**: `vod_fallback_upstream_location location`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets an nginx location to which the request is forwarded after encountering a file not found error (local/mapped modes only).\n\n#### vod_proxy_header_name\n* **syntax**: `vod_proxy_header_name name`\n* **default**: `X-Kaltura-Proxy`\n* **context**: `http`, `server`, `location`\n\nSets the name of an HTTP header that is used to prevent fallback proxy loops (local/mapped modes only).\n\n#### vod_proxy_header_value\n* **syntax**: `vod_proxy_header_value name`\n* **default**: `dumpApiRequest`\n* **context**: `http`, `server`, `location`\n\nSets the value of an HTTP header that is used to prevent fallback proxy loops (local/mapped modes only).\n\n### Configuration directives - performance\n\n#### vod_metadata_cache\n* **syntax**: `vod_metadata_cache zone_name zone_size [expiration]`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nConfigures the size and shared memory object name of the video metadata cache. For MP4 files, this cache holds the moov atom.\n\n#### vod_mapping_cache\n* **syntax**: `vod_mapping_cache zone_name zone_size [expiration]`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nConfigures the size and shared memory object name of the mapping cache for vod (mapped mode only).\n\n#### vod_live_mapping_cache\n* **syntax**: `vod_live_mapping_cache zone_name zone_size [expiration]`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nConfigures the size and shared memory object name of the mapping cache for live (mapped mode only).\n\n#### vod_response_cache\n* **syntax**: `vod_response_cache zone_name zone_size [expiration]`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nConfigures the size and shared memory object name of the response cache. The response cache holds manifests\nand other non-video content (like DASH init segment, HLS encryption key etc.). Video segments are not cached.\n\n#### vod_live_response_cache\n* **syntax**: `vod_live_response_cache zone_name zone_size [expiration]`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nConfigures the size and shared memory object name of the response cache for time changing live responses. \nThis cache holds the following types of responses for live: DASH MPD, HLS index M3U8, HDS bootstrap, MSS manifest.\n\n#### vod_initial_read_size\n* **syntax**: `vod_initial_read_size size`\n* **default**: `4K`\n* **context**: `http`, `server`, `location`\n\nSets the size of the initial read operation of the MP4 file.\n\n#### vod_max_metadata_size\n* **syntax**: `vod_max_metadata_size size`\n* **default**: `128MB`\n* **context**: `http`, `server`, `location`\n\nSets the maximum supported video metadata size (for MP4 - moov atom size)\n\n#### vod_max_frames_size\n* **syntax**: `vod_max_frames_size size`\n* **default**: `16MB`\n* **context**: `http`, `server`, `location`\n\nSets the limit on the total size of the frames of a single segment\n\n#### vod_max_frame_count\n* **syntax**: `vod_max_frame_count count`\n* **default**: `1048576`\n* **context**: `http`, `server`, `location`\n\nSets the limit on the total count of the frames read to serve non segment (e.g. playlist) request.\n\n#### vod_segment_max_frame_count\n* **syntax**: `vod_segment_max_frame_count count`\n* **default**: `65536`\n* **context**: `http`, `server`, `location`\n\nSets the limit on the total count of the frames read to serve segment request.\n\n#### vod_cache_buffer_size\n* **syntax**: `vod_cache_buffer_size size`\n* **default**: `256K`\n* **context**: `http`, `server`, `location`\n\nSets the size of the cache buffers used when reading MP4 frames.\n\n#### vod_open_file_thread_pool\n* **syntax**: `vod_open_file_thread_pool pool_name`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nEnables the use of asynchronous file open via thread pool.\nThe thread pool must be defined with a thread_pool directive, if no pool name is specified the default pool is used.\nThis directive is supported only on nginx 1.7.11 or newer when compiling with --add-threads.\nNote: this directive currently disables the use of nginx's open_file_cache by nginx-vod-module\n\n#### vod_output_buffer_pool\n* **syntax**: `vod_output_buffer_pool size count`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nPre-allocates buffers for generating response data, saving the need allocate/free the buffers on every request.\n\n#### vod_performance_counters\n* **syntax**: `vod_performance_counters zone_name`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nConfigures the shared memory object name of the performance counters\n\n### Configuration directives - url structure\n\n#### vod_base_url\n* **syntax**: `vod_base_url url`\n* **default**: `see below`\n* **context**: `http`, `server`, `location`\n\nSets the base URL (scheme + domain) that should be returned in manifest responses.\nThe parameter value can contain variables, if the parameter evaluates to an empty string, relative URLs will be used.\nIf the parameter evaluates to a string ending with /, it is assumed to be a full URL - the module only appends the\nfile name to it, instead of a full URI.\nIf not set, the base URL is determined as follows:\n1. If the request did not contain a host header (HTTP/1.0) relative URLs will be returned\n2. Otherwise, the base URL will be `$scheme://$http_host`\nThe setting currently affects only HLS and DASH. In MSS and HDS, relative URLs are always returned.\n\n#### vod_segments_base_url\n* **syntax**: `vod_segments_base_url url`\n* **default**: `see below`\n* **context**: `http`, `server`, `location`\n\nSets the base URL (scheme + domain) that should be used for delivering video segments.\nThe parameter value can contain variables, if the parameter evaluates to an empty string, relative URLs will be used.\nIf not set, vod_base_url will be used.\nThe setting currently affects only HLS.\n\n#### vod_multi_uri_suffix\n* **syntax**: `vod_multi_uri_suffix suffix`\n* **default**: `.urlset`\n* **context**: `http`, `server`, `location`\n\nA URL suffix that is used to identify multi URLs. A multi URL is a way to encode several different URLs\nthat should be played together as an adaptive streaming set, under a single URL. When the default suffix is\nused, an HLS set URL may look like: \nhttp://host/hls/common-prefix,bitrate1,bitrate2,common-suffix.urlset/master.m3u8\n\n#### vod_clip_to_param_name\n* **syntax**: `vod_clip_to_param_name name`\n* **default**: `clipTo`\n* **context**: `http`, `server`, `location`\n\nThe name of the clip to request parameter.\n\n#### vod_clip_from_param_name\n* **syntax**: `vod_clip_from_param_name name`\n* **default**: `clipFrom`\n* **context**: `http`, `server`, `location`\n\nThe name of the clip from request parameter.\n\n#### vod_tracks_param_name\n* **syntax**: `vod_tracks_param_name name`\n* **default**: `tracks`\n* **context**: `http`, `server`, `location`\n\nThe name of the tracks request parameter.\n\n#### vod_time_shift_param_name\n* **syntax**: `vod_time_shift_param_name name`\n* **default**: `shift`\n* **context**: `http`, `server`, `location`\n\nThe name of the shift request parameter.\n\n#### vod_speed_param_name\n* **syntax**: `vod_speed_param_name name`\n* **default**: `speed`\n* **context**: `http`, `server`, `location`\n\nThe name of the speed request parameter.\n\n#### vod_lang_param_name\n* **syntax**: `vod_lang_param_name name`\n* **default**: `lang`\n* **context**: `http`, `server`, `location`\n\nThe name of the language request parameter.\n\n#### vod_force_sequence_index\n* **syntax**: `vod_force_sequence_index on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nUse sequence index in segment uris even if there is only one sequence\n\n### Configuration directives - response headers\n\n#### vod_expires\n* **syntax**: `vod_expires time`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets the value of the \"Expires\" and \"Cache-Control\" response headers for successful requests.\nThis directive is similar to nginx's built-in `expires` directive, except that it only supports the expiration interval scenario\n(epoch, max, off, day time are not supported)\nMain motivation for using this directive instead of the built-in `expires` is to have different expiration for VOD and dynamic live content.\nIf this directive is not specified, nginx-vod-module will not set the \"Expires\" / \"Cache-Control\" headers.\nThis setting affects all types of requests in VOD playlists and segment requests in live playlists.\n\n#### vod_expires_live\n* **syntax**: `vod_expires_live time`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSame as `vod_expires` (above) for live requests that are not time dependent and not segments (e.g. HLS - master.m3u8, HDS - manifest.f4m).\n\n#### vod_expires_live_time_dependent\n* **syntax**: `vod_expires_live_time_dependent time`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSame as `vod_expires` (above) for live requests that are time dependent (HLS - index.m3u8, HDS - bootstrap.abst, MSS - manifest, DASH - manifest.mpd).\n\n#### vod_last_modified\n* **syntax**: `vod_last_modified time`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets the value of the Last-Modified header returned on the response, by default the module does not return a Last-Modified header.\nThe reason for having this parameter here is in order to support If-Modified-Since / If-Unmodified-Since.\nSince nginx's builtin ngx_http_not_modified_filter_module runs before any other header filter module, it will not see any headers set by add_headers / more_set_headers.\nThis makes nginx always reply as if the content changed (412 for If-Unmodified-Since / 200 for If-Modified-Since)\nFor live requests that are not segments (e.g. live DASH MPD), Last-Modified is set to the current server time.\n\n#### vod_last_modified_types\n* **syntax**: `vod_last_modified_types mime-type1 mime-type2 ...`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets the MIME types for which the Last-Modified header should be set.\nThe special value \"*\" matches any MIME type.\n\n### Configuration directives - ad stitching (mapped mode only)\n\n#### vod_dynamic_mapping_cache\n* **syntax**: `vod_dynamic_mapping_cache zone_name zone_size [expiration]`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nConfigures the size and shared memory object name of the cache that stores the mapping of dynamic clips.\n\n#### vod_dynamic_clip_map_uri\n* **syntax**: `vod_dynamic_clip_map_uri uri`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets the uri that should be used to map dynamic clips. \nThe parameter value can contain variables, specifically, `$vod_clip_id` contains the id of the clip that should be mapped.\nThe expected response from this uri is a JSON containing a concat clip object.\n\n#### vod_source_clip_map_uri\n* **syntax**: `vod_source_clip_map_uri uri`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets the uri that should be used to map source clips defined using the clipIds property of concat. \nThe parameter value can contain variables, specifically, `$vod_clip_id` contains the id of the clip that should be mapped.\nThe expected response from this uri is a JSON containing a source clip object.\n\n#### vod_redirect_segments_url\n* **syntax**: `vod_redirect_segments_url url`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets a url to which requests for segments should be redirected.\nThe parameter value can contain variables, specifically, `$vod_dynamic_mapping` contains a serialized representation of the mapping of dynamic clips.\n\n#### vod_apply_dynamic_mapping\n* **syntax**: `vod_apply_dynamic_mapping mapping`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nMaps dynamic clips to concat clips using the given expression, previously generated by `$vod_dynamic_mapping`.\nThe parameter value can contain variables.\n\n#### vod_notification_uri\n* **syntax**: `vod_notification_uri uri`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets the uri that should be used to issue notifications. \nThe parameter value can contain variables, specifically, `$vod_notification_id` contains the id of the notification that is being fired.\nThe response from this uri is ignored.\n\n### Configuration directives - DRM / encryption\n\n#### vod_secret_key\n* **syntax**: `vod_secret_key string`\n* **default**: `empty`\n* **context**: `http`, `server`, `location`\n\nSets the seed that is used to generate the TS encryption key and DASH/MSS encryption IVs.\nThe parameter value can contain variables, and will usually have the structure \"secret-$vod_filepath\".\nSee the list of nginx variables added by this module below.\n\n#### vod_encryption_iv_seed\n* **syntax**: `vod_encryption_iv_seed string`\n* **default**: `empty`\n* **context**: `http`, `server`, `location`\n\nSets the seed that is used to generate the encryption IV, currently applies only to HLS/fMP4 with AES-128 encryption.\nThe parameter value can contain variables.\n\n#### vod_drm_enabled\n* **syntax**: `vod_drm_enabled on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, the module encrypts the media segments according to the response it gets from the drm upstream.\nCurrently supported only for dash and mss (play ready).\n\n#### vod_drm_single_key\n* **syntax**: `vod_drm_single_key on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, the module requests the drm info only for the first sequence and applies it to all sequences.\nWhen disabled, the drm info is requested for each sequence separately.\nIn addition, in DASH, enabling this setting makes the module place the ContentProtection tag under AdaptationSet,\notherwise, it is placed under Representation.\n\n#### vod_drm_clear_lead_segment_count\n* **syntax**: `vod_drm_clear_lead_segment_count count`\n* **default**: `1`\n* **context**: `http`, `server`, `location`\n\nSets the number of clear (unencrypted) segments in the beginning of the stream. A clear lead enables the player to start playing without having to wait for the license response.\n\n#### vod_drm_max_info_length\n* **syntax**: `vod_drm_max_info_length length`\n* **default**: `4K`\n* **context**: `http`, `server`, `location`\n\nSets the maximum length of a drm info returned from upstream.\n\n#### vod_drm_upstream_location\n* **syntax**: `vod_drm_upstream_location location`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets the nginx location that should be used for getting the DRM info for the file.\n\n#### vod_drm_info_cache\n* **syntax**: `vod_drm_info_cache zone_name zone_size [expiration]`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nConfigures the size and shared memory object name of the drm info cache.\n\n#### vod_drm_request_uri\n* **syntax**: `vod_drm_request_uri uri`\n* **default**: `$vod_suburi`\n* **context**: `http`, `server`, `location`\n\nSets the uri of drm info requests, the parameter value can contain variables.\nIn case of multi url, `$vod_suburi` will be the current sub uri (a separate drm info request is issued per sub URL)\n\n#### vod_min_single_nalu_per_frame_segment\n* **syntax**: `vod_min_single_nalu_per_frame_segment index`\n* **default**: `0`\n* **context**: `http`, `server`, `location`\n\nSets the minimum segment index (1-based) that should be assumed to have a single h264 nalu per frame.\nIf the value is 0, no assumption is being made on the number of nal units per frame.\nThis setting only affects DASH and MSS configurations that have DRM enabled.\n\nWhen transcoding videos using libx264, by default, all frames have a single nal unit, except the first frame\nthat contains an additional nalu with the libx264 copyright information. Setting this parameter to a value\ngreater than 0 can provide a significant performance improvement, since the layout of the segment can be\ncalculated in advance, allowing the module to:\n* Output segment buffers as they are generated (it doesn't have to wait for the whole segment to complete)\n* Avoid frame processing for requests that do not need the segment data (e.g. HEAD, range 0-0, etc.)\n\n### Configuration directives - DASH\n\n#### vod_dash_absolute_manifest_urls\n* **syntax**: `vod_dash_absolute_manifest_urls on/off`\n* **default**: `on`\n* **context**: `http`, `server`, `location`\n\nWhen enabled the server returns absolute URLs in MPD requests\n\n#### vod_dash_manifest_file_name_prefix\n* **syntax**: `vod_dash_manifest_file_name_prefix name`\n* **default**: `manifest`\n* **context**: `http`, `server`, `location`\n\nThe name of the MPD file (an mpd extension is implied).\n\n#### vod_dash_profiles\n* **syntax**: `vod_dash_profiles profiles`\n* **default**: `urn:mpeg:dash:profile:isoff-main:2011`\n* **context**: `http`, `server`, `location`\n\nSets the profiles that are returned in the MPD tag in manifest responses.\n\n#### vod_dash_init_file_name_prefix\n* **syntax**: `vod_dash_init_file_name_prefix name`\n* **default**: `init`\n* **context**: `http`, `server`, `location`\n\nThe name of the MP4 initialization file (an mp4 extension is implied).\n\n#### vod_dash_fragment_file_name_prefix\n* **syntax**: `vod_dash_fragment_file_name_prefix name`\n* **default**: `frag`\n* **context**: `http`, `server`, `location`\n\nThe name of the fragment files (an m4s extension is implied).\n\n#### vod_dash_manifest_format\n* **syntax**: `vod_dash_manifest_format format`\n* **default**: `segmenttimeline`\n* **context**: `http`, `server`, `location`\n\nSets the MPD format, available options are:\n* `segmentlist` - uses SegmentList and SegmentURL tags, in this format the URL of each fragment is explicitly set in the MPD\n* `segmenttemplate` - uses SegmentTemplate, reporting a single duration for all fragments\n* `segmenttimeline` - uses SegmentTemplate and SegmentTimeline to explicitly set the duration of the fragments\n\n#### vod_dash_subtitle_format\n* **syntax**: `vod_dash_subtitle_format format`\n* **default**: `webvtt`\n* **context**: `http`, `server`, `location`\n\nSets the format of the subtitles returned in the MPD, available options are:\n* `webvtt` - WebVTT\n* `smpte-tt` - SMPTE Timed Text\n\n#### vod_dash_init_mp4_pssh\n* **syntax**: `vod_dash_init_mp4_pssh on/off`\n* **default**: `on`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, the DRM pssh boxes are returned in the DASH init segment and in the manifest.\nWhen disabled, the pssh boxes are returned only in the manifest.\n\n#### vod_dash_duplicate_bitrate_threshold\n* **syntax**: `vod_dash_duplicate_bitrate_threshold threshold`\n* **default**: `4096`\n* **context**: `http`, `server`, `location`\n\nThe bitrate threshold for removing identical bitrates, streams whose bitrate differences are less than\nthis value will be considered identical.\n\n#### vod_dash_use_base_url_tag\n* **syntax**: `vod_dash_use_base_url_tag on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, a BaseURL tag will be used to specify the fragments/init segment base url.\nOtherwise, the media/initialization attributes under SegmentTemplate will contain absolute URLs. \n\n### Configuration directives - HDS\n\n#### vod_hds_absolute_manifest_urls\n* **syntax**: `vod_hds_absolute_manifest_urls on/off`\n* **default**: `on`\n* **context**: `http`, `server`, `location`\n\nWhen enabled the server returns the base URL in the F4M manifest\n\n#### vod_hds_manifest_file_name_prefix\n* **syntax**: `vod_hds_manifest_file_name_prefix name`\n* **default**: `manifest`\n* **context**: `http`, `server`, `location`\n\nThe name of the HDS manifest file (an f4m extension is implied).\n\n#### vod_hds_fragment_file_name_prefix\n* **syntax**: `vod_hds_fragment_file_name_prefix name`\n* **default**: `frag`\n* **context**: `http`, `server`, `location`\n\nThe prefix of fragment file names, the actual file name is `frag-f\u003cfile-index\u003e-v\u003cvideo-track-index\u003e-a\u003caudio-track-index\u003e-Seg1-Frag\u003cindex\u003e`.\n\n#### vod_hds_generate_moof_atom\n* **syntax**: `vod_hds_generate_moof_atom on/off`\n* **default**: `on`\n* **context**: `http`, `server`, `location`\n\nWhen enabled the module generates a moof atom in the HDS fragments, when disabled only an mdat atom is generated.\nTurning this parameter off reduces the packaging overhead, however the default is on since Adobe tools are generating this atom.\n\n### Configuration directives - HLS\n\n#### vod_hls_encryption_method\n* **syntax**: `vod_hls_encryption_method method`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets the encryption method of HLS segments, allowed values are: none (default), aes-128, sample-aes, sample-aes-cenc.\n\n#### vod_hls_force_unmuxed_segments\n* **syntax**: `vod_hls_force_unmuxed_segments on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nWhen enabled the server returns the audio stream in separate segments than the ones used by the video stream (using EXT-X-MEDIA)\n\n#### vod_hls_container_format\n* **syntax**: `vod_hls_container_format mpegts/fmp4/auto`\n* **default**: `auto`\n* **context**: `http`, `server`, `location`\n\nSets the container format of the HLS segments. \nThe default behavior is to use fmp4 for HEVC, and mpegts otherwise (Apple does not support HEVC over MPEG TS).\n\n#### vod_hls_absolute_master_urls\n* **syntax**: `vod_hls_absolute_master_urls on/off`\n* **default**: `on`\n* **context**: `http`, `server`, `location`\n\nWhen enabled the server returns absolute playlist URLs in master playlist requests\n\n#### vod_hls_absolute_index_urls\n* **syntax**: `vod_hls_absolute_index_urls on/off`\n* **default**: `on`\n* **context**: `http`, `server`, `location`\n\nWhen enabled the server returns absolute segment URLs in media playlist requests\n\n#### vod_hls_absolute_iframe_urls\n* **syntax**: `vod_hls_absolute_iframe_urls on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nWhen enabled the server returns absolute segment URLs in iframe playlist requests\n\n#### vod_hls_output_iframes_playlist\n* **syntax**: `vod_hls_output_iframes_playlist on/off`\n* **default**: `on`\n* **context**: `http`, `server`, `location`\n\nWhen disabled iframe playlists are not returned as part of master playlists\n\n#### vod_hls_master_file_name_prefix\n* **syntax**: `vod_hls_master_file_name_prefix name`\n* **default**: `master`\n* **context**: `http`, `server`, `location`\n\nThe name of the HLS master playlist file (an m3u8 extension is implied).\n\n#### vod_hls_index_file_name_prefix\n* **syntax**: `vod_hls_index_file_name_prefix name`\n* **default**: `index`\n* **context**: `http`, `server`, `location`\n\nThe name of the HLS media playlist file (an m3u8 extension is implied).\n\n#### vod_hls_iframes_file_name_prefix\n* **syntax**: `vod_hls_iframes_file_name_prefix name`\n* **default**: `iframes`\n* **context**: `http`, `server`, `location`\n\nThe name of the HLS I-frames playlist file (an m3u8 extension is implied).\n\n#### vod_hls_segment_file_name_prefix\n* **syntax**: `vod_hls_segment_file_name_prefix name`\n* **default**: `seg`\n* **context**: `http`, `server`, `location`\n\nThe prefix of segment file names, the actual file name is `seg-\u003cindex\u003e-v\u003cvideo-track-index\u003e-a\u003caudio-track-index\u003e.ts`.\n\n#### vod_hls_init_file_name_prefix\n* **syntax**: `vod_hls_init_file_name_prefix name`\n* **default**: `init`\n* **context**: `http`, `server`, `location`\n\nThe name of the init segment file name, only relevant when using fmp4 container.\n\n#### vod_hls_encryption_key_file_name\n* **syntax**: `vod_hls_encryption_key_file_name name`\n* **default**: `encryption.key`\n* **context**: `http`, `server`, `location`\n\nThe name of the encryption key file name, only relevant when encryption method is not `none`.\n\n#### vod_hls_encryption_key_uri\n* **syntax**: `vod_hls_encryption_key_uri uri`\n* **default**: `a url pointing to encryption.key`\n* **context**: `http`, `server`, `location`\n\nSets the value of the URI attribute of EXT-X-KEY, only relevant when encryption method is not `none`.\nThe parameter value can contain variables.\n\n#### vod_hls_encryption_key_format\n* **syntax**: `vod_hls_encryption_key_format format`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets the value of the KEYFORMAT attribute of EXT-X-KEY, only relevant when encryption method is not `none`.\n\n#### vod_hls_encryption_key_format_versions\n* **syntax**: `vod_hls_encryption_key_format_versions versions`\n* **default**: `none`\n* **context**: `http`, `server`, `location`\n\nSets the value of the KEYFORMATVERSIONS attribute of EXT-X-KEY, only relevant when encryption method is not `none`.\n\n#### vod_hls_mpegts_interleave_frames\n* **syntax**: `vod_hls_mpegts_interleave_frames on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, the HLS muxer interleaves frames of different streams (audio / video).\nWhen disabled, on every switch between audio / video the muxer flushes the MPEG TS packet.\n\n#### vod_hls_mpegts_align_frames\n* **syntax**: `vod_hls_mpegts_align_frames on/off`\n* **default**: `on`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, every video / audio frame is aligned to MPEG TS packet boundary,\npadding is added as needed.\n\n#### vod_hls_mpegts_output_id3_timestamps\n* **syntax**: `vod_hls_mpegts_output_id3_timestamps on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, an ID3 TEXT frame is outputted in each TS segment.\nThe content of the ID3 TEXT frame can be set using the directive `vod_hls_mpegts_id3_data`.\n\n#### vod_hls_mpegts_id3_data\n* **syntax**: `vod_hls_mpegts_id3_data string`\n* **default**: `{\"timestamp\":$vod_segment_time,\"sequenceId\":\"$vod_sequence_id\"}`\n* **context**: `http`, `server`, `location`\n\nSets the data of the ID3 TEXT frame outputted in each TS segment, when `vod_hls_mpegts_output_id3_timestamps` is set to `on`.\nWhen the directive is not set, the ID3 frames contain by default a JSON object of the format `{\"timestamp\":1459779115000,\"sequenceId\":\"{id}\"}`:\n- `timestamp` - an absolute time measured in milliseconds since the epoch (unixtime x 1000).\n- `sequenceId` - the id field of the sequence object, as specified in the mapping JSON. The field is omitted when the sequence id is empty / not specified in the mapping JSON.\nThe parameter value can contain variables.\n\n#### vod_hls_mpegts_align_pts\n* **syntax**: `vod_hls_mpegts_align_pts on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, the module will shift back the dts timestamps by the pts delay of the initial frame.\nThis can help keep the pts timestamps aligned across multiple renditions.\n\n#### vod_hls_encryption_output_iv\n* **syntax**: `vod_hls_encryption_output_iv on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, the module outputs the `IV` attribute in returned `#EXT-X-KEY` tags.\n\n### Configuration directives - MSS\n\n#### vod_mss_manifest_file_name_prefix\n* **syntax**: `vod_mss_manifest_file_name_prefix name`\n* **default**: `manifest`\n* **context**: `http`, `server`, `location`\n\nThe name of the manifest file (has no extension).\n\n#### vod_mss_duplicate_bitrate_threshold\n* **syntax**: `vod_mss_duplicate_bitrate_threshold threshold`\n* **default**: `4096`\n* **context**: `http`, `server`, `location`\n\nThe bitrate threshold for removing identical bitrates, streams whose bitrate differences are less than\nthis value will be considered identical.\n\n### Configuration directives - thumbnail capture\n\n#### vod_thumb_file_name_prefix\n* **syntax**: `vod_thumb_file_name_prefix name`\n* **default**: `thumb`\n* **context**: `http`, `server`, `location`\n\nThe name of the thumbnail file (a jpg extension is implied).\n\n#### vod_thumb_accurate_positioning\n* **syntax**: `vod_thumb_accurate_positioning on/off`\n* **default**: `on`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, the module grabs the frame that is closest to the requested offset.\nWhen disabled, the module uses the keyframe that is closest to the requested offset.\nSetting this parameter to off can result in faster thumbnail capture, since the module \nalways decodes a single video frame per request.\n\n#### vod_gop_look_behind\n* **syntax**: `vod_gop_look_behind millis`\n* **default**: `10000`\n* **context**: `http`, `server`, `location`\n\nSets the interval (in milliseconds) before the thumbnail offset that should be loaded.\nThis setting should be set to the maximum GOP size, setting it to a lower value may result in capture failure.\nNote that the metadata of all frames between `offset - vod_gop_look_behind` and `offset + vod_gop_look_ahead`\nis loaded, however only the frames of the minimum GOP containing `offset` will be read and decoded.\n\n#### vod_gop_look_ahead\n* **syntax**: `vod_gop_look_ahead millis`\n* **default**: `1000`\n* **context**: `http`, `server`, `location`\n\nSets the interval (in milliseconds) after the thumbnail offset that should be loaded.\n\n### Configuration directives - volume map\n\n#### vod_volume_map_file_name_prefix\n* **syntax**: `vod_volume_map_file_name_prefix name`\n* **default**: `volume_map`\n* **context**: `http`, `server`, `location`\n\nThe name of the volume map file (a csv extension is implied).\n\n#### vod_volume_map_interval\n* **syntax**: `vod_volume_map_interval millis`\n* **default**: `1000`\n* **context**: `http`, `server`, `location`\n\nSets the interval/resolution (in milliseconds) of the volume map.\n\n### Configuration directives - misc\n\n#### vod_ignore_edit_list\n* **syntax**: `vod_ignore_edit_list on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, the module ignores any edit lists (elst) in the MP4 file.\n\n#### vod_parse_hdlr_name\n* **syntax**: `vod_parse_hdlr_name on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, the module parses the name field of the hdlr MP4 atom, and uses it as the stream label.\n\n#### vod_parse_udta_name\n* **syntax**: `vod_parse_udta_name on/off`\n* **default**: `off`\n* **context**: `http`, `server`, `location`\n\nWhen enabled, the module parses the name atom child of the udta MP4 atom, and uses it as the stream label.\n\n### Nginx variables\n\nThe module adds the following nginx variables:\n* `$vod_suburi` - the current sub uri. For example, if the url is:\n  `http://\u003cdomain\u003e/\u003clocation\u003e/\u003cprefix\u003e,\u003cmiddle1\u003e,\u003cmiddle2\u003e,\u003cmiddle3\u003e,\u003cpostfix\u003e.urlset/\u003cfilename\u003e`\n  `$vod_suburi` will have the value `http://\u003cdomain\u003e/\u003clocation\u003e/\u003cprefix\u003e\u003cmiddle1\u003e\u003cpostfix\u003e/\u003cfilename\u003e` \n  when processing the first uri.\n* `$vod_filepath` - in local / mapped modes, the file path of current sub uri. In remote mode, has the same value as `$vod_suburi`.\n* `$vod_set_id` - contains the id of the set.\n* `$vod_sequence_id` - contains the id of the current sequence, if no id was specified in the mapping json this variable will be the same as `$vod_suburi`.\n* `$vod_clip_id` - the id of the current clip, this variable has a value during these phases:\n  1. Mapping of dynamic clips to concat clips\n  2. Mapping of source clip to paths\n* `$vod_notification_id` - the id of the current notification, the value is non-empty only when referenced by `vod_notification_uri`\n* `$vod_dynamic_mapping` - a serialized representation of the mapping of dynamic clips to concat clips.\n* `$vod_request_params` - a serialized representation of the request params, e.g. 12-f2-v1-a1. The variable contains:\n  1. The segment index (for a segment request)\n  2. The sequence index\n  3. A selection of audio/video tracks\n* `$vod_status` - the internal error code of the module, provides a more fine grained classification of errors than http status.\n\tthe following values are defined:\n\t`BAD_REQUEST` - the request is invalid, for example, `clipFrom` is larger than the video duration\n\t`NO_STREAMS` - an invalid segment index was requested\n\t`EMPTY_MAPPING` - the mapping response is empty\n\t`BAD_MAPPING` - the mapping json is invalid, for example, the `sequences` element is missing\n\t`BAD_DATA` - the video file is corrupt\n\t`EXPIRED` - the current server time is larger than `expirationTime`\n\t`ALLOC_FAILED` - the module failed to allocate memory\n\t`UNEXPECTED` - a scenario that is not supposed to happen, most likely a bug in the module\n* `$vod_segment_time` - for segment requests, contains the absolute timestamp of the first frame in the segment, measured in milliseconds since the epoch (unixtime x 1000).\n* `$vod_segment_duration` - for segment requests, contains the duration of the segment in milliseconds\n* `$vod_frames_bytes_read` - for segment requests, total number of bytes read while processing media frames\n\nNote: Configuration directives that can accept variables are explicitly marked as such.\n\n### Sample configurations\n\n#### Local configuration\n```nginx\n\thttp {\n\t\tupstream fallback {\n\t\t\tserver fallback.kaltura.com:80;\n\t\t}\n\n\t\tserver {\n\t\t\t# vod settings\n\t\t\tvod_mode local;\n\t\t\tvod_fallback_upstream_location /fallback;\n\t\t\tvod_last_modified 'Sun, 19 Nov 2000 08:52:00 GMT';\n\t\t\tvod_last_modified_types *;\n\n\t\t\t# vod caches\n\t\t\tvod_metadata_cache metadata_cache 512m;\n\t\t\tvod_response_cache response_cache 128m;\n\t\t\t\n\t\t\t# gzip manifests\n\t\t\tgzip on;\n\t\t\tgzip_types application/vnd.apple.mpegurl;\n\n\t\t\t# file handle caching / aio\n\t\t\topen_file_cache          max=1000 inactive=5m;\n\t\t\topen_file_cache_valid    2m;\n\t\t\topen_file_cache_min_uses 1;\n\t\t\topen_file_cache_errors   on;\n\t\t\taio on;\n\t\t\t\n\t\t\tlocation ^~ /fallback/ {\n\t\t\t\tinternal;\n\t\t\t\tproxy_pass http://fallback/;\n\t\t\t\tproxy_set_header Host $http_host;\n\t\t\t}\n\n\t\t\tlocation /content/ {\n\t\t\t\troot /web/;\n\t\t\t\tvod hls;\n\t\t\t\t\n\t\t\t\tadd_header Access-Control-Allow-Headers '*';\n\t\t\t\tadd_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range';\n\t\t\t\tadd_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';\n\t\t\t\tadd_header Access-Control-Allow-Origin '*';\n\t\t\t\texpires 100d;\n\t\t\t}\n\t\t}\n\t}\n```\n\n#### Mapped configuration\n```nginx\n\thttp {\n\t\tupstream kalapi {\n\t\t\tserver www.kaltura.com:80;\n\t\t}\n\n\t\tupstream fallback {\n\t\t\tserver fallback.kaltura.com:80;\n\t\t}\n\n\t\tserver {\n\t\t\t# vod settings\n\t\t\tvod_mode mapped;\n\t\t\tvod_upstream_location /kalapi;\n\t\t\tvod_upstream_extra_args \"pathOnly=1\";\n\t\t\tvod_fallback_upstream_location /fallback;\n\t\t\tvod_last_modified 'Sun, 19 Nov 2000 08:52:00 GMT';\n\t\t\tvod_last_modified_types *;\n\n\t\t\t# vod caches\n\t\t\tvod_metadata_cache metadata_cache 512m;\n\t\t\tvod_response_cache response_cache 128m;\n\t\t\tvod_mapping_cache mapping_cache 5m;\n\t\t\t\n\t\t\t# gzip manifests\n\t\t\tgzip on;\n\t\t\tgzip_types application/vnd.apple.mpegurl;\n\n\t\t\t# file handle caching / aio\n\t\t\topen_file_cache          max=1000 inactive=5m;\n\t\t\topen_file_cache_valid    2m;\n\t\t\topen_file_cache_min_uses 1;\n\t\t\topen_file_cache_errors   on;\n\t\t\taio on;\n\t\t\t\n\t\t\tlocation ^~ /fallback/ {\n\t\t\t\tinternal;\n\t\t\t\tproxy_pass http://fallback/;\n\t\t\t\tproxy_set_header Host $http_host;\n\t\t\t}\n\n\t\t\tlocation ^~ /kalapi/ {\n\t\t\t\tinternal;\n\t\t\t\tproxy_pass http://kalapi/;\n\t\t\t\tproxy_set_header Host $http_host;\n\t\t\t}\n\n\t\t\tlocation ~ ^/p/\\d+/(sp/\\d+/)?serveFlavor/ {\n\t\t\t\t# encrypted hls\n\t\t\t\tvod hls;\n\t\t\t\tvod_secret_key \"mukkaukk$vod_filepath\";\n\t\t\t\tvod_hls_encryption_method aes-128;\n\t\t\t\t\n\t\t\t\tadd_header Access-Control-Allow-Headers '*';\n\t\t\t\tadd_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range';\n\t\t\t\tadd_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';\n\t\t\t\tadd_header Access-Control-Allow-Origin '*';\n\t\t\t\texpires 100d;\n\t\t\t}\n\t\t}\n\t}\n```\n\n#### Mapped + Remote configuration\n```nginx\n\thttp {\n\t\tupstream jsonupstream {\n\t\t\tserver jsonserver:80;\n\t\t}\n\n\t\tserver {\n\t\t\t# vod settings\n\t\t\tvod_mode mapped;\n\t\t\tvod_upstream_location /json;\n\t\t\tvod_remote_upstream_location /proxy;\n\t\t\tvod_upstream_extra_args \"pathOnly=1\";\n\t\t\tvod_last_modified 'Sun, 19 Nov 2000 08:52:00 GMT';\n\t\t\tvod_last_modified_types *;\n\n\t\t\t# vod caches\n\t\t\tvod_metadata_cache metadata_cache 512m;\n\t\t\tvod_response_cache response_cache 128m;\n\t\t\tvod_mapping_cache mapping_cache 5m;\n\n\t\t\t# gzip manifests\n\t\t\tgzip on;\n\t\t\tgzip_types application/vnd.apple.mpegurl;\n\n\t\t\t# file handle caching / aio\n\t\t\topen_file_cache\t  max=1000 inactive=5m;\n\t\t\topen_file_cache_valid    2m;\n\t\t\topen_file_cache_min_uses 1;\n\t\t\topen_file_cache_errors   on;\n\t\t\taio on;\n\n\t\t\tlocation ^~ /json/hls/ {\n\t\t\t\tinternal;\n\t\t\t\tproxy_pass http://jsonupstream/;\n\t\t\t\tproxy_set_header Host $http_host;\n\t\t\t}\n\n\t\t\tlocation ~ /proxy/([^/]+)/(.*) {\n\t\t\t\tinternal;\n\t\t\t\tproxy_pass $1://$2;\n\t\t\t\tresolver 8.8.8.8;\n\t\t\t}\n\n\t\t\tlocation ~ ^/hls/ {\n\t\t\t\tvod hls;\n\n\t\t\t\tadd_header Access-Control-Allow-Headers '*';\n\t\t\t\tadd_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range';\n\t\t\t\tadd_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';\n\t\t\t\tadd_header Access-Control-Allow-Origin '*';\n\t\t\t\texpires 100d;\n\t\t\t}\n\t\t}\n\t}\n```\n\nSet it up so that http://jsonserver:80/test.json returns the following JSON:\n```json\n\t{\n\t\t\"sequences\": [{\n\t\t\t\"clips\": [{\n\t\t\t\t\"type\": \"source\",\n\t\t\t\t\"path\": \"/http/commondatastorage.googleapis.com/gtv-videos-bucket/sample/BigBuckBunny.mp4\"\n\t\t\t}]\n\t\t}]\n\t}\n```\n\nAnd use this stream URL - http://nginx-vod-server/hls/test.json/master.m3u8\n\n#### Remote configuration\n```nginx\n\thttp {\n\t\tupstream kalapi {\n\t\t\tserver www.kaltura.com:80;\n\t\t}\n\n\t\tserver {\n\t\t\t# vod settings\n\t\t\tvod_mode remote;\n\t\t\tvod_upstream_location /kalapi;\n\t\t\tvod_last_modified 'Sun, 19 Nov 2000 08:52:00 GMT';\n\t\t\tvod_last_modified_types *;\n\n\t\t\t# vod caches\n\t\t\tvod_metadata_cache metadata_cache 512m;\n\t\t\tvod_response_cache response_cache 128m;\n\t\t\t\n\t\t\t# gzip manifests\n\t\t\tgzip on;\n\t\t\tgzip_types application/vnd.apple.mpegurl;\n\t\t\t\n\t\t\tlocation ^~ /kalapi/ {\n\t\t\t\tinternal;\n\t\t\t\tproxy_pass http://kalapi/;\n\t\t\t\tproxy_set_header Host $http_host;\n\t\t\t}\n\n\t\t\tlocation ~ ^/p/\\d+/(sp/\\d+/)?serveFlavor/ {\n\t\t\t\tvod hls;\n\t\t\t\t\n\t\t\t\tadd_header Access-Control-Allow-Headers '*';\n\t\t\t\tadd_header Access-Control-Expose-Headers 'Server,range,Content-Length,Content-Range';\n\t\t\t\tadd_header Access-Control-Allow-Methods 'GET, HEAD, OPTIONS';\n\t\t\t\tadd_header Access-Control-Allow-Origin '*';\n\t\t\t\texpires 100d;\n\t\t\t}\n\t\t}\n\t}\n```\n### Copyright \u0026 License\n\nAll code in this project is released under the [AGPLv3 license](http://www.gnu.org/licenses/agpl-3.0.html) unless a different license for a particular library is specified in the applicable library path. \n\nCopyright © Kaltura Inc. All rights reserved.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkaltura%2Fnginx-vod-module","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkaltura%2Fnginx-vod-module","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkaltura%2Fnginx-vod-module/lists"}