[
  {
    "path": ".gitignore",
    "content": "test/\n"
  },
  {
    "path": "Dockerfile.bento4",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.3.0\nRUN apt-get install -y unzip \nRUN cd /root/source && \\\n    wget http://zebulon.bok.net/Bento4/binaries/Bento4-SDK-1-6-0-634.x86_64-unknown-linux.zip && \\\n    unzip ./Bento4-SDK-1-6-0-634.x86_64-unknown-linux.zip -d /usr/local && \\\n    ln -s /usr/local/Bento4-SDK-1-6-0-634.x86_64-unknown-linux /usr/local/bento4\nENV PATH=\"${PATH}:/usr/local/bento4/bin\"\n"
  },
  {
    "path": "Dockerfile.ffmpeg",
    "content": "FROM ubuntu:22.04\nLABEL MAINTAINER=\"Eyevinn Technology <info@eyevinn.se>\" \nARG DEBIAN_FRONTEND=noninteractive\nRUN apt-get -y update\nRUN apt-get install -y autoconf\nRUN apt-get install -y --force-yes automake\nRUN apt-get install -y --force-yes build-essential\nRUN apt-get install -y --force-yes pkg-config\nRUN apt-get install -y --force-yes libtool\nRUN apt-get install -y --force-yes wget\nRUN apt-get install -y --force-yes yasm\nRUN apt-get install -y --force-yes libx264-dev\nRUN mkdir /root/source\nRUN mkdir /root/source/ffmpeg\nRUN cd /root/source/ffmpeg && \\\n  wget -O fdk-aac.tar.gz https://github.com/mstorsjo/fdk-aac/tarball/master && \\\n  tar xzvf fdk-aac.tar.gz && \\\n  cd mstorsjo-fdk-aac* && \\\n  autoreconf -fiv && \\\n  ./configure --disable-shared && \\\n  make && \\\n  make install && \\\n  make distclean\nRUN apt-get install -y --force-yes git\nRUN apt-get install -y --force-yes cmake\nRUN apt-get install -y --force-yes python2.7\nRUN mkdir -p /root/source/ffmpeg/libaom && \\\n  cd /root/source/ffmpeg/libaom && \\\n  git clone https://aomedia.googlesource.com/aom && \\\n  cmake ./aom && \\\n  make && \\\n  make install\nRUN apt-get install -y --force-yes python3 python3-pip ninja-build\nRUN pip3 install meson\nRUN apt-get install -y --force-yes nasm\nRUN cd /root/source/ffmpeg && \\\n  git clone https://code.videolan.org/videolan/dav1d.git && \\\n  cd dav1d && \\\n  meson build --buildtype release && \\\n  ninja -C build && \\\n  ninja -C build install && \\\n  ldconfig\nRUN apt-get install -y --force-yes libvpx-dev\nRUN apt-get install -y --force-yes libssl-dev\nRUN apt-get install -y --force-yes tclsh\nRUN cd /root/source/ffmpeg && \\\n  git clone https://github.com/Haivision/srt.git && \\\n  cd srt && \\\n  ./configure && \\\n  make && make install && \\\n  ldconfig\nRUN apt-get install -y --force-yes libx265-dev libnuma-dev\nRUN apt-get install -y --force-yes libfreetype6-dev\nRUN apt-get install -y --force-yes libopus-dev\nRUN apt-get install -y --force-yes openssl\nRUN apt-get install -y --force-yes libssl-dev\nRUN apt-get install -y --force-yes libmp3lame-dev\nRUN cd /root/source/ffmpeg && \\\n  wget http://ffmpeg.org/releases/ffmpeg-6.0.tar.bz2 && \\\n  tar xjvf ffmpeg-6.0.tar.bz2 && \\\n  cd ffmpeg-6.0 && \\\n  ./configure \\\n    --pkg-config-flags=\"--static\" \\\n    --enable-gpl \\\n    --enable-libfdk-aac \\\n    --enable-libx264 \\\n    --enable-libaom \\\n    --enable-libdav1d \\\n    --enable-libvpx \\\n    --enable-libsrt \\\n    --enable-libx265 \\\n    --enable-libfreetype \\\n    --enable-libopus \\\n    --enable-libmp3lame \\\n    --enable-version3 \\\n    --enable-openssl \\\n    --enable-nonfree && \\\n  make && \\\n  make install && \\\n  make distclean && \\\n  hash -r\n"
  },
  {
    "path": "Dockerfile.ffmpeg-mp3",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.3.0\nRUN apt-get install -y libmp3lame-dev\nRUN cd /root/source/ffmpeg && \\\n  cd ffmpeg && \\\n  ./configure \\\n    --pkg-config-flags=\"--static\" \\\n    --enable-gpl \\\n    --enable-libfdk-aac \\\n    --enable-libx264 \\\n    --enable-libaom \\\n    --enable-libdav1d \\\n    --enable-libvpx \\\n    --enable-libsrt \\\n    --enable-libx265 \\\n    --enable-libfreetype \\\n    --enable-libopus \\\n    --enable-libmp3lame \\\n    --enable-version3 \\\n    --enable-openssl \\\n    --enable-nonfree && \\\n  make && \\\n  make install && \\\n  make distclean && \\\n  hash -r\n"
  },
  {
    "path": "Dockerfile.gpac",
    "content": "FROM ubuntu:14.04\nMAINTAINER Eyevinn Technology <info@eyevinn.se>\nRUN apt-get update\nRUN apt-get install -y --force-yes subversion make pkg-config \\\n  g++ zlib1g-dev libfreetype6-dev libjpeg62-dev libpng12-dev \\\n  libopenjpeg-dev libmad0-dev libfaad-dev libogg-dev libvorbis-dev \\\n  libtheora-dev liba52-0.7.4-dev libavcodec-dev libavformat-dev \\\n  libavutil-dev libswscale-dev libavresample-dev libxv-dev x11proto-video-dev \\\n  libgl1-mesa-dev x11proto-gl-dev linux-sound-base libxvidcore-dev libssl-dev \\\n  libjack-dev libasound2-dev libpulse-dev libsdl1.2-dev dvb-apps libavcodec-extra \\\n  libavdevice-dev libmozjs185-dev\nRUN apt-get install -y --force-yes git\nRUN mkdir /root/source\nRUN apt-get install -y --force-yes libx264-dev\nRUN apt-get install -y --force-yes yasm\nRUN apt-get install -y --force-yes wget\nRUN mkdir /root/source/ffmpeg\nRUN apt-get install -y --force-yes libssl-dev\nRUN apt-get install -y --force-yes cmake\nRUN DEBIAN_FRONTEND=noninteractive apt-get install -y --force-yes tclsh\nRUN cd /root/source/ffmpeg && \\\n  git clone https://github.com/Haivision/srt.git && \\\n  cd srt && \\\n  ./configure && \\\n  make && make install && \\\n  ldconfig\nRUN cd /root/source/ffmpeg && \\\n  wget http://ffmpeg.org/releases/ffmpeg-snapshot.tar.bz2 && \\\n  tar xjvf ffmpeg-snapshot.tar.bz2 && \\\n  cd ffmpeg && \\\n  ./configure \\\n    --enable-gpl \\\n    --enable-shared \\\n    --enable-libx264 \\\n    --enable-libsrt \\\n    --enable-version3 \\\n    --enable-nonfree && \\\n  make && \\\n  make install && \\\n  make distclean && \\\n  hash -r\nRUN cd /root/source/ && \\\n  git clone https://github.com/gpac/gpac.git && \\\n  cd gpac && \\\n  ./configure && \\\n  make && \\\n  make install && \\\n  hash -r\nRUN echo /usr/local/lib/x86_64-linux-gnu >> /etc/ld.so.conf.d/x86_64-linux-gnu.conf\nRUN ldconfig\n"
  },
  {
    "path": "Dockerfile.gst",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.1.3\nMAINTAINER Eyevinn Technology <info@eyevinn.se>\nRUN apt-get update\nRUN apt-get install -y --force-yes libgstreamer1.0-0 gstreamer1.0-plugins-base \\\n  gstreamer1.0-plugins-good gstreamer1.0-plugins-bad gstreamer1.0-plugins-ugly \\\n  gstreamer1.0-libav gstreamer1.0-doc gstreamer1.0-tools gstreamer1.0-x \\\n  gstreamer1.0-alsa gstreamer1.0-gl gstreamer1.0-gtk3 gstreamer1.0-qt5 \\\n  gstreamer1.0-pulseaudio\n\n"
  },
  {
    "path": "Dockerfile.hls2rtmp",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.3.0\nMAINTAINER Eyevinn Technology <info@eyevinn.se>\nCOPY python/hls2rtmp.py /root/hls2rtmp.py\nENTRYPOINT [\"/root/hls2rtmp.py\"]\nCMD []\n"
  },
  {
    "path": "Dockerfile.hls2srt",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.3.0\nMAINTAINER Eyevinn Technology <info@eyevinn.se>\nCOPY python/hls2srt.py /root/hls2srt.py\nENTRYPOINT [\"/root/hls2srt.py\"]\nCMD []\n"
  },
  {
    "path": "Dockerfile.hls2ts",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.2.2\nMAINTAINER Eyevinn Technology <info@eyevinn.se>\nCOPY python/hls2ts.py /root/hls2ts.py\nENTRYPOINT [\"/root/hls2ts.py\"]\nCMD []\n"
  },
  {
    "path": "Dockerfile.loopts",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.1.3\nMAINTAINER Eyevinn Technology <info@eyevinn.se>\nCOPY fonts/Vera.ttf /root/Vera.ttf\nCOPY python/loopts.py /root/loopts.py\nENTRYPOINT [\"/root/loopts.py\"]\nCMD []\n"
  },
  {
    "path": "Dockerfile.mosaicts",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.1.3\nMAINTAINER Eyevinn Technology <info@eyevinn.se>\nCOPY python/mosaicts.py /root/mosaicts.py\nENTRYPOINT [\"/root/mosaicts.py\"]\nCMD []"
  },
  {
    "path": "Dockerfile.rtmp2srt",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.3.0\nMAINTAINER Eyevinn Technology <info@eyevinn.se>\nCOPY python/rtmp2srt.py /root/rtmp2srt.py\nENTRYPOINT [\"/root/rtmp2srt.py\"]\nCMD []\n"
  },
  {
    "path": "Dockerfile.rtmprx",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.1.3\nMAINTAINER Eyevinn Technology <info@eyevinn.se>\nCOPY python/rtmprx.py /root/rtmprx.py\nENTRYPOINT [\"/root/rtmprx.py\"]\nCMD []"
  },
  {
    "path": "Dockerfile.srt2rtmp",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.3.0\nMAINTAINER Eyevinn Technology <info@eyevinn.se>\nCOPY python/srt2rtmp.py /root/srt2rtmp.py\nENTRYPOINT [\"/root/srt2rtmp.py\"]\nCMD []"
  },
  {
    "path": "Dockerfile.srtrx",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.1.3\nMAINTAINER Eyevinn Technology <info@eyevinn.se>\nCOPY python/srtrx.py /root/srtrx.py\nENTRYPOINT [\"/root/srtrx.py\"]\nCMD []"
  },
  {
    "path": "Dockerfile.srttx",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.3.0\nMAINTAINER Eyevinn Technology <info@eyevinn.se>\nCOPY python/srttx.py /root/srttx.py\nENTRYPOINT [\"/root/srttx.py\"]\nCMD []\n"
  },
  {
    "path": "Dockerfile.transcode",
    "content": "FROM eyevinntechnology/ffmpeg-base:0.3.0\nMAINTAINER Eyevinn Technology <info@eyevinn.se>\nCOPY python/transcode.py /root/transcode.py\nENTRYPOINT [\"/root/transcode.py\"]\nCMD []\n"
  },
  {
    "path": "LICENSE",
    "content": "The scripts used in the containers are licensed under the MIT License:\n\nThe MIT License\n\nCopyright (c) 2019 Eyevinn Technology (eyevinn.github.io)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated\ndocumentation files (the \"Software\"), to deal in the Software without restriction, including without limitation\nthe rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and \nto permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions\nof the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE \nWARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR \nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, \nARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# Eyevinn Toolbox\n\nThe Eyevinn Toolbox is a set of Docker containers with tools that may come in handy. They are all free to use and if you have any suggestions feel free to create a ticket.\n\n| Tool      | Description | Container |\n| ----      | ----------- | --------- |\n| Loop TS   | Generate MPEG-TS stream over multicast or SRT by looping an MP4 file | eyevinntechnology/toolbox-loopts |\n| SRT Tx    | Transport stream over SRT | eyevinntechnology/toolbox-srttx |\n| SRT Rx    | Receive stream over SRT | eyevinntechnology/toolbox-srtrx |\n| RTMP Rx   | Receive RTMP and stream over multicast | eyevinntechnology/toolbox-rtmprx |\n| Mosaic TS | Render a 2x2 or 3x3 mosaic in MPEG-TS from 4 or 9 HLS sources | eyevinntechnology/toolbox-mosaicts |\n| HLS 2 TS  | Pull a live HLS stream and output to multicast TS | eyevinntechnology/toolbox-hls2ts |\n| HLS 2 RTMP | Pull a live HLS stream and re-stream to multiple RTMP destinations. | eyevinntechnology/toolbox-hls2rtmp |\n| HLS 2 SRT | Pull a live HLS stream and transmit over SRT | eyevinntechnology/toolbox-hls2srt |\n| SRT 2 RTMP | Receive an SRT stream and re-stream to multiple RTMP destinations. | eyevinntechnology/toolbox-srt2rtmp |\n| RTMP 2 SRT | Receive an RTMP stream and transmit over SRT. | eyevinntechnology/toolbox-rtmp2srt |\n| VOD Transcode | Quickly transcode video file to a set of different bitrates | eyevinntechnology/toolbox-transcode |\n\n## Loop input file and output MPEG-TS multicast\n\n```\n$ docker run --rm -v $PWD:/mnt eyevinntechnology/toolbox-loopts IN.mp4 udp://239.0.0.1.1234?pkt_size=1316\n```\n\nwhere `$PWD` is your working directory where you have your input file.\n\nThe following options are available:\n\n```\n$ docker run --rm -v $PWD:/mnt eyevinntechnology/toolbox-loopts -h\nusage: loopts.py [-h] [--workdir WORKDIR] [--framerate FRAMERATE]\n                 [--kfinterval KFINTERVAL] [--bitrate BITRATE] [--hevc]\n                 [--withtc] [--withaudio] [--nologo] [--useflv]\n                 [--multibitrate]\n                 inputfile multicast\n\nLoop an MP4 file and output to MPEG-TS multicast\n\npositional arguments:\n  inputfile\n  multicast\n\noptional arguments:\n  -h, --help              show this help message and exit\n  --workdir WORKDIR       specify a working directory, default is /mnt\n  --framerate FRAMERATE   output framerate (DEFAULT 25fps)\n  --kfinterval KFINTERVAL specify keyframe interval (DEFAULT 2 sec)\n  --bitrate BITRATE       specify video bitrate in kbps (e.g. 2500)\n  --hevc                  use HEVC encoded output\n  --withtc                burn in local timecode in video output\n  --withaudio             adds a test tone on the audio track\n  --nologo                remove logo\n  --useflv                use FLV for RTMP output\n  --multibitrate          output multiple video bitrates\n```\n\nTo test this locally on your computer (Mac + VLC) assuming the file to loop is called IN.mp4 and in your working directory\n\n```\n$ docker run --rm -p 9998:9998/udp -v $PWD:/mnt eyevinntechnology/toolbox-loopts IN.mp4 udp://host.docker.internal:9998?pkt_size=1316 --withtc\n```\n\nThen open VLC with the following network address: `udp://@127.0.0.1:9998`\n\n### Output MPEG-TS over SRT\n\nTo use SRT (Secure Reliable Transport) instead of multicast you can run `loopts` as an SRT listener.\n\n```\ndocker run --rm -p 9998:9998/udp -v $PWD:/mnt eyevinntechnology/toolbox-loopts IN.mp4 \"srt://0.0.0.0:9998?pkt_size=1316&mode=listener\" --withtc\n```\n\nThen open VLC with the following network address: `srt://@127.0.0.1:9998`\n\n### Output FLV over RTMP\n\nTo use RTMP instead of multicast you can run `loopts` and push with RTMP\n\n```\ndocker run --rm -it -v $PWD:/mnt eyevinntechnology/toolbox-loopts --useflv IN.mp4 \"rtmp://live.twitch.tv/app/live_*****\"\n```\n\n## Receive MPEG-TS over SRT and restream over multicast\n\nUse the `srtrx` tool to receive an MPEG-TS stream over SRT (Secure Reliable Transport) and restream over multicast. This can be used in the following scenario:\n\n```\n+-----------+                     +-----------------+                       +------------+\n|           |                     |                 |                       |            |\n|  SRT Tx   | ===> INTERNET ===>  |  toolbox-srtrx  | ====> MULTICAST ====> | TRANSCODER |\n|           |                     |                 |                       |            |\n+-----------+                     +-----------------+                       +------------+\n```\n\nAssuming that the `SRT Tx` is running in listener mode and can be reached on 10.0.110.178:9998 you start the restreamer with the following commmand:\n\n```\n$ docker run --rm -p 1234:1234/udp eyevinntechnology/toolbox-srtrx 10.0.110.178:9998 239.0.0.1:1234\n```\n\nThis setup can be emulated by running loopts tool as the `SRT Tx` and VLC as the transcoder.\n\n```\n$ docker run --rm -p 9998:9998/udp -v $PWD:/mnt eyevinntechnology/toolbox-loopts IN.mp4 \"srt://0.0.0.0:9998?pkt_size=1316&mode=listener\" --withtc\n```\n\n```\n$ docker run --rm -p 9999:9999/udp eyevinntechnology/toolbox-srtrx 10.0.110.178:9998 host.docker.internal:9999\n```\n\nwhere 10.0.110.178 is the IP of your computer running the loopts container.\n\n```\n$ docker run --rm eyevinntechnology/toolbox-srtrx -h\nusage: srtrx.py [-h] [--listener] [--with-debug] inputaddress outputaddress\n\nReceive MPEG-TS over SRT and restream over Multicast\n\npositional arguments:\n  inputaddress\n  outputaddress\n\noptional arguments:\n  -h, --help     show this help message and exit\n  --listener     run as SRT listener\n  --passthrough  for low latency skip the unmux and mux step.\n```\n\n## Receive RTMP and restream over SRT\n\nThe `srttx` tool can be used to receive a local RTMP stream and restream to an `SRT Rx` over the Internet.\n\n```\n+------------------+                     +-----------------+                       +------------+\n|  Wirecast &      |                     |                 |                       |            |\n|  toolbox-srttx   | ===> INTERNET ===>  |  toolbox-srtrx  | ====> MULTICAST ====> | TRANSCODER |\n|  <IP-TX>         |                     |  <IP-RX>        |                       |            |\n+------------------+                     +-----------------+                       +------------+\n```\n\nOn the transmitter side with for example Wirecast as producing the stream first start the `srttx` tool.\n\n```\n$ docker run --rm -p 1935:1935 eyevinntechnology/toolbox-srttx:0.2.4 input_stream <IP-RX>:9998 --passthrough\n```\n\nThen point the Wirecast / OBS output to `rtmp://localhost/live/input_stream`\n\nOn the receiver side you then run the following:\n\n```\n$ docker run --rm -p 9998:9998/udp -p <MULTICAST-PORT>:<MULTICAST-PORT>/udp eyevinntechnology/toolbox-srtrx --listener --passthrough 0.0.0.0:9998 <MULTICAST>:<MULTICAST-PORT>`\n```\n\n```\n$ docker run --rm eyevinntechnology/toolbox-srttx:0.2.4 -h\nusage: srttx.py [-h] [--inputtype INPUTTYPE] [--listener] [--passthrough]\n                inputstream outputaddress\n\nReceive RTMP and stream over SRT\n\npositional arguments:\n  inputstream\n  outputaddress\n\noptional arguments:\n  -h, --help     show this help message and exit\n  --inputtype INPUTTYPE type of input [rtmp|mpegts], default is rtmp  \n  --listener     run as SRT listener\n  --passthrough  passthrough input and skip encoding process\n```\n\n### MPEG-TS as a source\n\nThe `srttx` tool can also take an MPEG-TS as a source. Instead run the following command on the transmitter side. The receiver side as before.\n\n```\n$ docker run --rm eyevinntechnology/toolbox-srttx:0.2.4 <MULTICAST>:<MULTICAST-PORT> <IP-RX>:9998 --passthrough --inputtype=mpegts\n```\n\n## Receive RTMP and restream over Multicast\n\nUse the `rtmprx` tool to receive RTMP and restream MPEG-TS over multicast if you want to use RTMP as the transport protocol with a live transcoder that for example only supports MPEG-TS multicast.\n\nOn the receiver side run the following command:\n\n```\n$ docker run --rm -p 1935:1935 -p <MULTICAST-PORT>:<MULTICAST-PORT>/udp eyevinntechnology/toolbox-rtmprx input_stream <MULTICAST>:<MULTICAST-PORT> --passthrough\n```\n\n```\n$ docker run --rm eyevinntechnology/toolbox-rtmprx -h\nusage: rtmprx.py [-h] [--passthrough] [--with-debug] inputstream outputaddress\n\nReceive RTMP and restream over Multicast\n\npositional arguments:\n  inputstream\n  outputaddress\n\noptional arguments:\n  -h, --help     show this help message and exit\n  --passthrough  passthrough input and skip encoding process\n```\n\n## Render a Mosaic from HLS sources\n\nUse the `mosaicts` tool to render a 2x2 or 3x3 mosaic of HLS sources.\n\n```\n$ docker run --rm eyevinntechnology/toolbox-mosaicts -h\nusage: mosaicts.py [-h] [--port PORT] [--multicast MULTICAST] [--with-debug]\n                   layout urlfile\n\nTake multiple HLS sources and render a mosaic in MPEG-TS\n\npositional arguments:\n  layout                2x2|3x3\n  urlfile               A text file containing URLs to HLS sources. One source\n                        per line.\n\noptional arguments:\n  -h, --help            show this help message and exit\n  --port PORT\n  --multicast MULTICAST\n                        Use multicast address specified here instead of SRT\n```\n\nTo read the list of URLs from STDIN:\n\n```\n$ docker run --rm -i -p 9998:9998/udp eyevinntechnology/toolbox-mosaicts 2x2 - < urls.txt\n```\n\n## Pull a live HLS stream and output to multicast TS\n\nUse the `hls2ts` tool to pull an HLS live stream and output to multicast TS.\n\n```\n$ docker run --rm eyevinntechnology/toolbox-hls2ts -h\nusage: hls2ts.py [-h] [--srt] [--bitrate BITRATE] [--with-debug]\n                 hlsurl outputaddress\n\nPull live HLS and output to multicast TS\n\npositional arguments:\n  hlsurl\n  outputaddress\n\noptional arguments:\n  -h, --help         show this help message and exit\n  --srt              use SRT as transport protocol\n  --bitrate BITRATE  which bitrate to use\n  --with-debug\n\n```\n\nExample:\n\n```\ndocker run --rm eyevinntechnology/toolbox-hls2ts:0.1.0 HLSURL <MULTICAST>:<MULTICAST-PORT>\n```\n\n## Re-stream SRT to multiple RTMP destinations\n\nUse the `srt2rtmp` tool to receive an SRT stream and re-stream to multiple RTMP destinations.\n\nExample:\n\n```\ndocker run --rm -p 1234:1234/udp eyevinntechnology/toolbox-srt2rtmp:0.1.1 0.0.0.0:1234 <RTMPURL1> <RTMPURL2>\n```\n\n## Pull a live HLS stream and output to multiple RTMP destinations\n\nUse the `hls2rtmp` tool to pull a live HLS stream and re-stream to multiple RTMP destinations.\n\nExample:\n\n```\ndocker run --rm eyevinntechnology/toolbox-hls2rtmp:0.1.3 HLSURL <RTMPURL1> <RTMPURL2>\n```\n\n## Pull a live HLS stream and output to SRT\n\nUse the `hls2srt` tool to pull a live HLS stream and make available over SRT.\n\nExample:\n\n```\ndocker run -d --restart always -p 1234:1234/udp eyevinntechnology/toolbox-hls2srt:0.1.1 HLSURL 0.0.0.0:1234\n```\n\n## Listen for an RTMP stream and output to SRT\n\nUse the `rtmp2srt` tool to receive an RTMP stream and transmit over SRT.\n\nExample:\n\n```\ndocker run --rm -p 1935:1935 -p 1234:1234/udp eyevinntechnology/toolbox-rtmp2srt:0.1.1 <STREAMKEY> <IP>:1234\n```\n\nBy deafult in SRT listener mode, to use SRT as a client:\n\n```\ndocker run --rm -p 1935:1935 eyevinntechnology/toolbox-rtmp2srt:0.1.0 --caller <STREAMKEY> <IP>:1234\n```\n\n## VOD Transcode\n\nQuickly transcode video file to a set of different bitrates.\n\n```\ndocker run --rm -v $PWD:/media eyevinntechnology/toolbox-transcode:0.1.0 --framerate 24 videofile-720p.mp4\n```\n\nand it will generate three GOP-aligned MP4 files prepared to be chunked into segments.\n\n# About Eyevinn Technology\n\nEyevinn Technology is an independent consultant firm specialized in video and streaming. Independent in a way that we are not commercially tied to any platform or technology vendor.\n\nAt Eyevinn, every software developer consultant has a dedicated budget reserved for open source development and contribution to the open source community. This give us room for innovation, team building and personal competence development. And also gives us as a company a way to contribute back to the open source community. \n\nWant to know more about Eyevinn and how it is to work here. Contact us at work@eyevinn.se!\n"
  },
  {
    "path": "build-bento4.sh",
    "content": "#!/bin/bash\n\ndocker build -t eyevinntechnology/bento4-base:0.1.0 -f Dockerfile.bento4 .\n"
  },
  {
    "path": "build-ffmpeg.sh",
    "content": "#!/bin/bash\n\ndocker build -t eyevinntechnology/ffmpeg-base:0.2.2 -f Dockerfile.ffmpeg .\n"
  },
  {
    "path": "build-gpac.sh",
    "content": "#!/bin/bash\n\ndocker build -t eyevinntechnology/gpac-base:0.1.0 -f Dockerfile.gpac .\n"
  },
  {
    "path": "build-gst.sh",
    "content": "#!/bin/bash\n\ndocker build -t eyevinntechnology/gst-base:0.1.0 -f Dockerfile.gst .\n"
  },
  {
    "path": "build-hls2rtmp.sh",
    "content": "#!/bin/bash\n\ndocker build --no-cache -t eyevinntechnology/toolbox-hls2rtmp:0.1.3 -f Dockerfile.hls2rtmp .\n"
  },
  {
    "path": "build-hls2srt.sh",
    "content": "#!/bin/bash\n\ndocker build -t eyevinntechnology/toolbox-hls2srt:0.1.1 -f Dockerfile.hls2srt .\n"
  },
  {
    "path": "build-hls2ts.sh",
    "content": "#!/bin/bash\n\ndocker build --no-cache -t eyevinntechnology/toolbox-hls2ts:0.1.3 -f Dockerfile.hls2ts .\n"
  },
  {
    "path": "build-loopts.sh",
    "content": "#!/bin/bash\n\ndocker build --no-cache -t eyevinntechnology/toolbox-loopts:0.2.1 -f Dockerfile.loopts .\n"
  },
  {
    "path": "build-mosaicts.sh",
    "content": "#!/bin/bash\n\ndocker build --no-cache -t eyevinntechnology/toolbox-mosaicts:0.1.0 -f Dockerfile.mosaicts .\n"
  },
  {
    "path": "build-rtmp2srt.sh",
    "content": "#!/bin/bash\n\ndocker build -t eyevinntechnology/toolbox-rtmp2srt:0.1.1 -f Dockerfile.rtmp2srt .\n"
  },
  {
    "path": "build-rtmprx.sh",
    "content": "#!/bin/bash\n\ndocker build --no-cache -t eyevinntechnology/toolbox-rtmprx:0.1.0 -f Dockerfile.rtmprx .\n"
  },
  {
    "path": "build-srt2rtmp.sh",
    "content": "#!/bin/bash\n\ndocker build --no-cache -t eyevinntechnology/toolbox-srt2rtmp:0.1.1 -f Dockerfile.srt2rtmp .\n"
  },
  {
    "path": "build-srtrx.sh",
    "content": "#!/bin/bash\n\ndocker build --no-cache -t eyevinntechnology/toolbox-srtrx:0.1.2 -f Dockerfile.srtrx .\n"
  },
  {
    "path": "build-srttx.sh",
    "content": "#!/bin/bash\n\ndocker build -t eyevinntechnology/toolbox-srttx:0.2.4 -f Dockerfile.srttx .\n"
  },
  {
    "path": "build-transcode.sh",
    "content": "#!/bin/bash\n\ndocker build -t eyevinntechnology/toolbox-transcode:0.1.0 -f Dockerfile.transcode .\n"
  },
  {
    "path": "python/hls2rtmp.py",
    "content": "#!/usr/bin/python2.7\n#\n# Copyright 2019 Eyevinn Technology. All rights reserved\n# Use of this source code is governed by a MIT License\n# that can be found in the LICENSE file.\n# Author: Jonas Rydholm Birme (Eyevinn Technology)\n#\n# Receive HLS and restream to multiple RTMP destinations\n#\nimport argparse\nimport subprocess\nfrom os.path import basename\nimport re\nimport glob\n\nparser = argparse.ArgumentParser(description='Pull HLS and restream to multiple RTMP destinations.')\nparser.add_argument('hlsurl')\nparser.add_argument('output', nargs=\"+\")\nparser.add_argument('--with-programreturn', dest='programreturn', action='store_true', help='open up an SRT program return')\nparser.add_argument('--returnport', dest='returnport', help='port for the SRT program return')\nparser.add_argument('--srtmode', dest='srtmode', help='SRT mode for program return. Default is listener')\nparser.add_argument('--with-debug', dest='debug', action='store_true')\nargs = parser.parse_args()\n\nreturnport = \"1234\"\nif args.returnport:\n  returnport = args.returnport\n\nsrtmode = \"&mode=listener\"\nif args.srtmode:\n  srtmode = args.srtmode\n\nsrtoutput = \"\"\nif args.programreturn:\n  srtoutput = \"-f fifo -fifo_format mpegts -map 0:v:0 -map 0:a:0 -c copy srt://0.0.0.0:%s?pkt_size=1316%s\" % (returnport, srtmode)\n\nffmpeg = \"ffmpeg -fflags +genpts -re -i %s -strict -2 -y %s \" % (args.hlsurl, srtoutput)\n\nfor dest in args.output:\n  ffmpeg = ffmpeg + \"-f fifo -fifo_format flv -map 0:v:0 -map 0:a:0 -c:v copy -vtag 7 -c:a copy -atag 10 -drop_pkts_on_overflow 1 -attempt_recovery 1 -recovery_wait_time 1 %s \" % (dest)\n\nif args.debug:\n  print \"%s\" % ffmpeg\n  print ffmpeg.split()\n\np1 = subprocess.Popen(ffmpeg.split())\noutput,err = p1.communicate()\n"
  },
  {
    "path": "python/hls2srt.py",
    "content": "#!/usr/bin/python2.7\n#\n# Copyright 2019 Eyevinn Technology. All rights reserved\n# Use of this source code is governed by a MIT License\n# that can be found in the LICENSE file.\n# Author: Jonas Rydholm Birme (Eyevinn Technology)\n#\n# Receive HLS and stream over SRT\n#\nimport argparse\nimport subprocess\nfrom os.path import basename\nimport re\nimport glob\n\nparser = argparse.ArgumentParser(description='Pull HLS and restream over SRT.')\nparser.add_argument('hlsurl')\nparser.add_argument('address')\nparser.add_argument('--srtmode', dest='srtmode', help='SRT mode [caller|listener]. Default is listener')\nparser.add_argument('--with-debug', dest='debug', action='store_true')\nargs = parser.parse_args()\n\nsrtmode = \"&mode=listener\"\nif args.srtmode == \"caller\":\n  srtmode = \"\"\n\nsrtoutput = \"-f mpegts srt://%s?pkt_size=1316%s\" % (args.address, srtmode)\n\nffmpeg = \"ffmpeg -fflags +genpts -re -i %s -strict -2 -y -acodec copy -vcodec copy %s \" % (args.hlsurl, srtoutput)\n\nif args.debug:\n  print \"%s\" % ffmpeg\n  print ffmpeg.split()\n\np1 = subprocess.Popen(ffmpeg.split())\noutput,err = p1.communicate()\n"
  },
  {
    "path": "python/hls2ts.py",
    "content": "#!/usr/bin/python2.7\n#\n# Copyright 2019 Eyevinn Technology. All rights reserved\n# Use of this source code is governed by a MIT License\n# that can be found in the LICENSE file.\n# Author: Jonas Rydholm Birme (Eyevinn Technology)\n#\n# Pull live HLS and output to multicast TS\n#\nimport argparse\nimport subprocess\nfrom os.path import basename\nimport re\nimport glob\n\nparser = argparse.ArgumentParser(description='Pull live HLS and output to multicast TS')\nparser.add_argument('hlsurl')\nparser.add_argument('outputaddress')\nparser.add_argument('--srt', action='store_true', help='use SRT as transport protocol')\nparser.add_argument('--channelbug', help='overlay logo as channel bug (poc)')\nparser.add_argument('--bitrate', help='which bitrate to use')\nparser.add_argument('--with-debug', dest='debug', action='store_true')\nargs = parser.parse_args()\n\nprotocol = 'udp'\nif args.srt:\n  protocol = 'srt'\n\nbitrate = ''\nif args.bitrate:\n  bitrate = \"-map m:variant_bitrate:%s\" % args.bitrate\n\nffmpeg = \"ffmpeg -fflags +genpts -re -i %s %s -strict -2 -y -vcodec copy -f mpegts %s://%s?pkt_size=1316\" % (args.hlsurl, bitrate, protocol, args.outputaddress)\nif args.channelbug:\n  ffmpeg = \"ffmpeg -fflags +genpts -re -i %s -r 25 -i %s -filter_complex [0:1][1:v]#overlay=10:10:eval=init -c:v libx264 -preset ultrafast -strict -2 -y -f mpegts -max_muxing_queue_size 2048 %s://%s?pkt_size=1316\" % (args.hlsurl, args.channelbug, protocol, args.outputaddress)\n\n\narglist = ffmpeg.split()\nif args.debug:\n  print \"%s\" % ffmpeg\n  print map(lambda x: x.replace(\"#\", \" \"), arglist)\n\np1 = subprocess.Popen(map(lambda x: x.replace(\"#\", \" \"), arglist))\noutput,err = p1.communicate()"
  },
  {
    "path": "python/loopts.py",
    "content": "#!/usr/bin/python2.7\n#\n# Copyright 2019 Eyevinn Technology. All rights reserved\n# Use of this source code is governed by a MIT License\n# that can be found in the LICENSE file.\n# Author: Jonas Rydholm Birme (Eyevinn Technology)\n#\n# Loop input file and output to multicast TS\n#\nimport argparse\nimport subprocess\nfrom os.path import basename\nimport re\nimport glob\n\nparser = argparse.ArgumentParser(description='Loop an MP4 file and output to MPEG-TS multicast')\nparser.add_argument('inputfile')\nparser.add_argument('multicast')\nparser.add_argument('--workdir', help='specify a working directory, default is /mnt')\nparser.add_argument('--framerate', help='output framerate (DEFAULT 25fps)')\nparser.add_argument('--kfinterval', help='specify keyframe interval (DEFAULT 2 sec)')\nparser.add_argument('--bitrate', help='specify video bitrate in kbps (e.g. 2500)')\nparser.add_argument('--hevc', action='store_true', help='use HEVC encoded output')\nparser.add_argument('--withtc', action='store_true', help='burn in local timecode in video output')\nparser.add_argument('--withaudio', action='store_true', help='adds a test tone on the audio track')\nparser.add_argument('--nologo', action='store_true', help='remove logo')\nparser.add_argument('--useflv', action='store_true', help='use FLV for RTMP output')\nparser.add_argument('--multibitrate', action='store_true', help='output multiple video bitrates')\nparser.add_argument('--with-debug', dest='debug', action='store_true')\nargs = parser.parse_args()\n\nworkdir = '/mnt'\nif args.workdir:\n  workdir = args.workdir\n\nframerate = '25'\nif args.framerate:\n  framerate = args.framerate\n\ntcstr = ''\nframestr = ''\nif args.withtc:\n  tcstr = ',drawtext=fontfile=/root/Vera.ttf:fontsize=200:text=\\'%{localtime\\\\:%T}\\':fontcolor=white@0.9:x=(w-tw)/2:y=250:shadowcolor=black:shadowx=2:shadowy=1'\n  framestr = ',drawtext=fontfile=/root/Vera.ttf:fontsize=40:text=\\'[%{n}/%{pts}]\\':fontcolor=white@0.9:x=(w-tw)/2:y=h-th-10:shadowcolor=black:shadowx=2:shadowy=1'\n\nbranding = 'drawtext=fontfile=/root/Vera.ttf:fontsize=12:text=\\'eyevinntechnology/toolbox-loopts\\':fontcolor=white@0.9:x=20:y=20:shadowcolor=black:shadowx=2:shadowy=1'\nif args.nologo:\n  branding = ''\n\naudiostr = '-f lavfi -i anullsrc=r=48000:cl=stereo'\nif args.withaudio:\n  audiostr = '-f lavfi -i sine=frequency=1000:sample_rate=48000'\n\naudiocopy = '-map 0:v -vcodec copy'\n\nkfinterval = float(framerate) * 2\nforcekf = 2\n\nif args.kfinterval:\n  kfinterval = float(framerate) * float(args.kfinterval)\n  forcekf = args.kfinterval\n\nstreamidstr = ''\noverlayfilter = '-filter_complex [0:v]%s%s%s[overlay]' % (branding, tcstr, framestr)\nscalefilter = '[overlay]scale=1280:720[out720]'\nmapstr = '%s;%s -map [out720] -map 1:0' % (overlayfilter, scalefilter)\n\nbitratestr = ''\nif args.bitrate:\n  bitratestr = '-b:v %sk -minrate %sk -maxrate %sk -bufsize %sk' % (args.bitrate, args.bitrate, args.bitrate, float(args.bitrate) / float(framerate))\n\noutputencoding = '-vcodec libx264 -preset veryfast -pix_fmt yuv420p -g %s -keyint_min %s %s' % (kfinterval, kfinterval, bitratestr)\nif args.hevc:\n  outputencoding = '-vcodec libx265 -preset superfast -pix_fmt yuv420p -g %s -keyint_min %s %s' % (kfinterval, kfinterval, bitratestr)\n\nif args.multibitrate:\n  scalefilter = '[overlay]split=4[o1][o2][o3][o4];'\n  scalefilter += '[o1]scale=480:360,drawtext=fontfile=/root/Vera.ttf:fontsize=12:text=\\'480x360\\':fontcolor=white@0.9:x=(w-tw)/2:y=20:shadowcolor=black:shadowx=2:shadowy=1[out360];'\n  scalefilter += '[o2]scale=854:480,drawtext=fontfile=/root/Vera.ttf:fontsize=12:text=\\'854x480\\':fontcolor=white@0.9:x=(w-tw)/2:y=20:shadowcolor=black:shadowx=2:shadowy=1[out480];'\n  scalefilter += '[o3]scale=1280:720,drawtext=fontfile=/root/Vera.ttf:fontsize=12:text=\\'1280x720\\':fontcolor=white@0.9:x=(w-tw)/2:y=20:shadowcolor=black:shadowx=2:shadowy=1[out720];'\n  scalefilter += '[o4]scale=1920:1080,drawtext=fontfile=/root/Vera.ttf:fontsize=12:text=\\'1920x1080\\':fontcolor=white@0.9:x=(w-tw)/2:y=20:shadowcolor=black:shadowx=2:shadowy=1[out1080]'\n  mapstr = '%s;%s -map [out360] -map 1:0 -map [out480] -map [out720] -map [out1080]' % (overlayfilter, scalefilter)\n  outputencoding = '-c:v:0 libx264 -preset veryfast -pix_fmt yuv420p -g %s -keyint_min %s -force_key_frames expr:gte(t,n_forced*%s) -b:v:0 400k -maxrate 400k -bufsize %sk' % (kfinterval, kfinterval, forcekf, 400 / float(framerate))\n  outputencoding += ' -c:v:1 libx264 -preset veryfast -pix_fmt yuv420p -g %s -keyint_min %s -force_key_frames expr:gte(t,n_forced*%s) -b:v:1 1000k -maxrate 1000k -bufsize %sk' % (kfinterval, kfinterval, forcekf, 1000 / float(framerate))\n  outputencoding += ' -c:v:2 libx264 -preset veryfast -pix_fmt yuv420p -g %s -keyint_min %s -force_key_frames expr:gte(t,n_forced*%s) -b:v:2 2000k -maxrate 2000k -bufsize %sk' % (kfinterval, kfinterval, forcekf, 2000 / float(framerate))\n  outputencoding += ' -c:v:3 libx264 -preset veryfast -pix_fmt yuv420p -g %s -keyint_min %s -force_key_frames expr:gte(t,n_forced*%s) -b:v:3 4500k -maxrate 4500k -bufsize %sk' % (kfinterval, kfinterval, forcekf, 4500 / float(framerate))\n\noutputformat = 'mpegts'\nif args.useflv:\n  outputformat = 'flv'\n  streamidstr = ''\n\n# ffmpeg -stream_loop -1 -i IN.mp4 -map 0:v -vcodec copy -bsf:v h264_mp4toannexb -f h264 - | ffmpeg -fflags +genpts -r 23.98 -re -i - -f lavfi -i anullsrc=r=48000:cl=stereo -c:a aac -shortest -vcodec libx264 -preset veryfast -pix_fmt yuv420p -strict -2 -y -f mpegts 'udp://239.0.0.1:1234'\nffmpeg1 = \"ffmpeg -stream_loop -1 -i %s/%s %s -bsf:v h264_mp4toannexb -f h264 -\" % (workdir, args.inputfile, audiocopy)\nffmpeg2 = \"ffmpeg -thread_queue_size 512 -threads 4 -framerate %s -fflags +genpts -r %s -re -i - %s %s -c:a aac -shortest %s -strict -2 -y -f %s -r %s %s %s\" % (framerate, framerate, audiostr, mapstr, outputencoding, outputformat, framerate, streamidstr, args.multicast)\n\nif args.debug:\n  print \"%s | %s\" % (ffmpeg1, ffmpeg2)\n  print ffmpeg1.split()\n  print ffmpeg2.split()\n\np1 = subprocess.Popen(ffmpeg1.split(), stdout=subprocess.PIPE)\np2 = subprocess.Popen(ffmpeg2.split(), stdin=p1.stdout)\np1.stdout.close()\n\noutput,err = p2.communicate()\n"
  },
  {
    "path": "python/mosaicts.py",
    "content": "#!/usr/bin/python2.7\n#\n# Copyright 2019 Eyevinn Technology. All rights reserved\n# Use of this source code is governed by a MIT License\n# that can be found in the LICENSE file.\n# Author: Jonas Rydholm Birme (Eyevinn Technology)\n#\n# Play multiple HLS sources and renders a mosaic in MPEG-TS \n#\nimport argparse\nimport subprocess\nfrom os.path import basename\nimport re\nimport glob\nimport sys\nparser = argparse.ArgumentParser(description='Take multiple HLS sources and render a mosaic in MPEG-TS')\nparser.add_argument('layout', help='2x2|3x3')\nparser.add_argument('urlfile', help='A text file containing URLs to HLS sources. One source per line.')\nparser.add_argument('--port', default='9998')\nparser.add_argument('--multicast', help='Use multicast address specified here instead of SRT')\nparser.add_argument('--with-debug', dest='debug', action='store_true')\nargs = parser.parse_args()\n\nif args.urlfile == '-':\n  sources = [x.strip() for x in sys.stdin.readlines()]\nelse:\n  with open(args.urlfile, \"r\") as f:\n    sources = [x.strip() for x in f.readlines()]\n\nscalex = 384\nscaley = 216\nwidth = 2\nheight = 2\n\nif args.layout == '3x3':\n  width = 3\n  height = 3\n\nfilter_complex = 'nullsrc=size=%dx%d [tmp0]; ' % (scalex * width, scaley * height)\nfor i in range(0, width*height):\n  filter_complex += '[%d:v] scale=%dx%d [s%d]; ' % (i, scalex, scaley, i)\nx = 0\ny = 0\nfor i in range(0, width*height):\n  if i < width*height - 1:\n    filter_complex += '[tmp%d][s%d] overlay=shortest=1:x=%d:y=%d [tmp%d];' % (i, i, x, y, i + 1)\n  else:\n    filter_complex += '[tmp%d][s%d] overlay=shortest=1:x=%d:y=%d' % (i, i, x, y)\n  if x >= (scalex * width) - scalex:\n    y += scaley\n    x = 0\n  else:\n    x += scalex\n\n#print filter_complex\ninputs = ''\nfor s in sources:\n  inputs += '-i %s ' % s\n\noutput = '\"srt://0.0.0.0:%s?pkt_size=1316&mode=listener\"' % args.port\nif args.multicast:\n  output = 'udp://%s?pkt_size=1316' % args.multicast\nffmpeg = 'ffmpeg -threads 8 -re %s -filter_complex \"%s\" -c:v libx264 -an -strict -2 -f mpegts %s' % (inputs, filter_complex, output)\n\nif args.debug:\n  print \"%s\" % ffmpeg\n\np1 = subprocess.Popen(ffmpeg, shell=True)\noutput,err = p1.communicate()"
  },
  {
    "path": "python/rtmp2srt.py",
    "content": "#!/usr/bin/python2.7\n#\n# Copyright 2020 Eyevinn Technology. All rights reserved\n# Use of this source code is governed by a MIT License\n# that can be found in the LICENSE file.\n# Author: Jonas Rydholm Birme (Eyevinn Technology)\n#\n# Receive RTMP and restream over SRT\n#\nimport argparse\nimport subprocess\nfrom os.path import basename\nimport re\nimport glob\n\nparser = argparse.ArgumentParser(description='Receive RTMP and restream over multicast')\nparser.add_argument('streamkey', help='RTMP stream key (path)')\nparser.add_argument('address', help='SRT address (IP:PORT)')\nparser.add_argument('--caller', dest='caller', action='store_true', help='SRT in caller mode (default listener)')\nparser.add_argument('--with-debug', dest='debug', action='store_true')\nargs = parser.parse_args()\n\nmode = '&mode=listener'\nif args.caller:\n  mode = ''\n\nif args.streamkey:\n  mode += '&passphrase=' + args.streamkey\n\nffmpeg = \"ffmpeg -fflags +genpts -listen 1 -re -i rtmp://0.0.0.0/rtmp/%s -acodec copy -vcodec copy -strict -2 -y -f mpegts srt://%s?pkt_size=1316%s\" % (args.streamkey, args.address, mode)\n\nif args.debug:\n  print \"%s\" % ffmpeg\n  print ffmpeg.split()\n\np1 = subprocess.Popen(ffmpeg.split())\noutput,err = p1.communicate()\n"
  },
  {
    "path": "python/rtmprx.py",
    "content": "#!/usr/bin/python2.7\n#\n# Copyright 2019 Eyevinn Technology. All rights reserved\n# Use of this source code is governed by a MIT License\n# that can be found in the LICENSE file.\n# Author: Jonas Rydholm Birme (Eyevinn Technology)\n#\n# Receive RTMP and restream over Multicast\n#\nimport argparse\nimport subprocess\nfrom os.path import basename\nimport re\nimport glob\n\nparser = argparse.ArgumentParser(description='Receive RTMP and restream over Multicast')\nparser.add_argument('inputstream')\nparser.add_argument('outputaddress')\nparser.add_argument('--passthrough', action='store_true', help='passthrough input and skip encoding process')\nparser.add_argument('--with-debug', dest='debug', action='store_true')\nargs = parser.parse_args()\n\noutputcoding = '-acodec copy -vcodec libx264 -preset veryfast -pix_fmt yuv420p'\nif args.passthrough:\n  outputcoding = '-acodec copy -vcodec copy'\n\nffmpeg = \"ffmpeg -fflags +genpts -listen 1 -re -i rtmp://0.0.0.0/live/%s %s -strict -2 -y -f mpegts udp://%s?pkt_size=1316\" % (args.inputstream, outputcoding, args.outputaddress)\n\nif args.debug:\n  print \"%s\" % ffmpeg\n  print ffmpeg.split()\n\np1 = subprocess.Popen(ffmpeg.split())\noutput,err = p1.communicate()"
  },
  {
    "path": "python/srt2rtmp.py",
    "content": "#!/usr/bin/python2.7\n#\n# Copyright 2019 Eyevinn Technology. All rights reserved\n# Use of this source code is governed by a MIT License\n# that can be found in the LICENSE file.\n# Author: Jonas Rydholm Birme (Eyevinn Technology)\n#\n# Receive SRT and restream to multiple RTMP destinations\n#\nimport argparse\nimport subprocess\nfrom os.path import basename\nimport re\nimport glob\n\nparser = argparse.ArgumentParser(description='Receive SRT and restream to multiple RTMP destinations')\nparser.add_argument('inputaddress')\nparser.add_argument('output', nargs=\"+\")\nparser.add_argument('--with-debug', dest='debug', action='store_true')\nargs = parser.parse_args()\n\nffmpeg = \"ffmpeg -re -i srt://%s?pkt_size=1316&mode=listener -strict -2 -y \" % (args.inputaddress)\n\nfor dest in args.output:\n  ffmpeg = ffmpeg + \"-f fifo -fifo_format flv -map 0:0 -map 0:1? -c copy -vtag 7 -atag 10 -drop_pkts_on_overflow 1 -attempt_recovery 1 -recovery_wait_time 1 %s \" % (dest)\n\nif args.debug:\n  print \"%s\" % ffmpeg\n  print ffmpeg.split()\n\np1 = subprocess.Popen(ffmpeg.split())\noutput,err = p1.communicate()\n"
  },
  {
    "path": "python/srtrx.py",
    "content": "#!/usr/bin/python2.7\n#\n# Copyright 2019 Eyevinn Technology. All rights reserved\n# Use of this source code is governed by a MIT License\n# that can be found in the LICENSE file.\n# Author: Jonas Rydholm Birme (Eyevinn Technology)\n#\n# Receive MPEG-TS over SRT and restream over Multicast\n#\nimport argparse\nimport subprocess\nfrom os.path import basename\nimport re\nimport glob\n\nparser = argparse.ArgumentParser(description='Receive MPEG-TS over SRT and restream over Multicast')\nparser.add_argument('inputaddress')\nparser.add_argument('outputaddress')\nparser.add_argument('--listener', action='store_true', help='run as SRT listener')\nparser.add_argument('--passthrough', action='store_true', help='for low latency skip the unmux and mux step.')\nparser.add_argument('--with-debug', dest='debug', action='store_true')\nargs = parser.parse_args()\n\nlistenermode = ''\nif args.listener:\n  listenermode = '&mode=listener'\n\nif args.passthrough:\n  ffmpeg = \"srt-live-transmit srt://%s?pkt_size=1316%s udp://%s?pkt_size=1316\" % (args.inputaddress, listenermode, args.outputaddress)\nelse:\n  ffmpeg = \"ffmpeg -re -i srt://%s?pkt_size=1316%s -vcodec copy -acodec copy -strict -2 -y -f mpegts udp://%s?pkt_size=1316\" % (args.inputaddress, listenermode, args.outputaddress)\n\nif args.debug:\n  print \"%s\" % ffmpeg\n  print ffmpeg.split()\n\np1 = subprocess.Popen(ffmpeg.split())\noutput,err = p1.communicate()"
  },
  {
    "path": "python/srttx.py",
    "content": "#!/usr/bin/python2.7\n#\n# Copyright 2019 Eyevinn Technology. All rights reserved\n# Use of this source code is governed by a MIT License\n# that can be found in the LICENSE file.\n# Author: Jonas Rydholm Birme (Eyevinn Technology)\n#\n# Receive RTMP and stream over SRT\n#\nimport argparse\nimport subprocess\nfrom os.path import basename\nimport re\nimport glob\n\nparser = argparse.ArgumentParser(description='Receive RTMP and stream over SRT')\nparser.add_argument('inputstream')\nparser.add_argument('outputaddress')\nparser.add_argument('--inputtype', default='rtmp', help='type of input [rtmp|mpegts], default is rtmp')\nparser.add_argument('--listener', action='store_true', help='run as SRT listener')\nparser.add_argument('--passthrough', action='store_true', help='passthrough input and skip encoding process')\nparser.add_argument('--analyzeduration', default='500000', help='set analyze duration for joining multicast TS')\nparser.add_argument('--with-debug', dest='debug', action='store_true')\nargs = parser.parse_args()\n\nlistenermode = ''\nif args.listener:\n  listenermode = '&mode=listener'\n\noutputcoding = '-acodec copy -vcodec libx264 -preset veryfast -pix_fmt yuv420p'\nif args.passthrough:\n  outputcoding = '-acodec copy -vcodec copy'\n\ninp = 'rtmp://0.0.0.0/live/%s -listen 1' % args.inputstream\nif args.inputtype == 'mpegts':\n  inp = 'udp://%s?pkt_size=1316&overrun_nonfatal=1&fifo_size=50000000' % args.inputstream\n\nffmpeg = \"ffmpeg -fflags +genpts -re -analyzeduration %s -i %s %s -strict -2 -y -f mpegts srt://%s?pkt_size=1316%s\" % (args.analyzeduration, inp, outputcoding, args.outputaddress, listenermode)\n\nif args.debug:\n  print \"%s\" % ffmpeg\n  print ffmpeg.split()\n\np1 = subprocess.Popen(ffmpeg.split())\noutput,err = p1.communicate()\n"
  },
  {
    "path": "python/transcode.py",
    "content": "#!/usr/bin/python2.7\n#\n# Copyright 2020 Eyevinn Technology. All rights reserved\n# Use of this source code is governed by a MIT License\n# that can be found in the LICENSE file.\n# Author: Jonas Rydholm Birme (Eyevinn Technology)\n#\n# Transcode an MP4 to multiple ABR-aligned MP4 files that can be packaged in various streaming formats\n#\nimport argparse\nimport subprocess\nfrom os.path import basename\nfrom os.path import splitext\nimport re\nimport glob\n\nparser = argparse.ArgumentParser(description='Transcode an MP4 file to multiple ABR-aligned MP4 files (AVC/AAC)')\nparser.add_argument('inputfile')\nparser.add_argument('--outdir', default='./', help=\"directory for the generated files. Default is current working directory.\")\nparser.add_argument('--framerate', default=30, help=\"framerate of input file. Default to 30\")\n\nargs = parser.parse_args()\n\nladder = [\n  (426, 240, 320),\n  (854, 480, 960),\n  (1280, 720, 1725),\n]\n\nffmpeg = \"ffmpeg -y -i /media/%s \" % args.inputfile\nfor p in ladder:\n  outputfile = \"/media/%s-%s.mp4\" % (splitext(args.inputfile)[0], p[2])\n  ffmpeg = ffmpeg + \"-pix_fmt yuv420p -r %s -c:v libx264 -sc_threshold 0 -profile:v main -bf 1 -refs 3 -vf scale=w=%s:h=%s -b:v %sk -maxrate %sk -bufsize %sk -keyint_min %s -g %s -strict experimental -acodec aac -b:a 96k -f mp4 %s \" % (args.framerate, p[0], p[1], p[2], p[2], p[2], args.framerate, (args.framerate * 2), outputfile)\nprint ffmpeg\n\np1 = subprocess.Popen(ffmpeg.split())\noutput,err = p1.communicate()\n"
  }
]