fpm

On-line (Internet) Audio/Video

Àudio i vídeo21 seccions1290 enllaçosVeure l'original

Seccions d'aquesta pàgina 21

01General#





IPTV Video over Internet
media video resolution
480i, 576i, 720p, 1080i, 1080p (any)
codec
  • MPEG-2
  • MPEG4-AVC/H264
  • VC-1
(any)
container
  • MPEG-2 TS
  • (direct)
  • MP4
  • QuickTime
  • WMedia
  • RealNetworks
  • Flash Video
  • ...
service discovery

SD&S
transmission progressive download
  • HTTP
  • FTP
- x
streaming live
video MPEG-2 RFC 2250
H264 RFC 3984
VC-1 RFC 4425
audio AAC RFC 3640
AMR-WB+ RFC 4352

x
on-demand x x
network delivery unicast
content on-demand x
multicast
x x
p2p
- x
receiver STB
x -
PC
  • Media Centre
  • browser (RTSP)
  • media player (RTP/RTCP)

02Streaming#

03RTP#

  • Documents
  • Jerarquia / Hierarchy
  • SRTP - Secure RTP
  • RTCP
  • SAP
  • SIP
  • RTP header (IETF RFC 3550: section 5.1):
    • 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
      V=2 P X CC M PT sequence_number
      timestamp
      synchronization source (SSRC) identifier
      contributing source (CSRC) identifiers
      • V: Version
      • P: Padding
      • X: Extension
      • CC: CSRC count
      • M: marker
      • PT: payload type
  • NAL header / nal_unit_type
  • H264/RTP (IETF RFC 3984):
    • WebRTC
    • In-band, out-band SPS, PPS

      • description
        SPS (7), PPS (8) NAL types
        SDP (manifest)
        example to generate
        problems


        in sdp manifest
        (sprop-parameter-sets)
        in stream
        (NALs 7, 8)




        out-band
        SPS,PPS only in manifest
        x
        -
        5, 1, 1... 5, 1, 1, ...
        a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z01AH+ygoP2AiAAAAwAIAAADAZB4wYyw,aOvssg==; profile-level-id=4D401F
        • ffmpeg -flags:v +global_header -c:v libx264 ...
        in-band
        SPS,PPS in both stream and manifest
        x
        x
        7, 8, 5, 1, 1... 7, 8, 5, 1, 1...
        • when coding and muxing:
        • when transmuxing:
          • ffmpeg ... -bsf:v h264_mp4toannexb ... -c:v copy ...
        SPS,PPS only in stream -
        x
        7, 8, 5, 1, 1... 7, 8, 5, 1, 1...
        a=fmtp:96 packetization-mode=1
        • when coding and muxing:
          • ffmpeg [-flags:v -global_header] -c:v libx264 ...
          • gst-launch-1.0 ... rtph264pay config-interval=-1 ...
        • when transmuxing:
          • ffmpeg ... -bsf:v h264_mp4toannexb ... -c:v copy ...
      • To check which NALs are transmitted:
        • ffplay -protocol_whitelist rtp,udp,file,http,https,tcp,tls,rtmp -v debug -i toto.sdp
        • remote:
          • ffplay -nodisp -protocol_whitelist rtp,udp,file,http,https,tcp,tls,rtmp -v debug -i toto.sdp
      • Transmux RTMP to RTP with ffmpeg:
        • When using nginx-rtmp-module, even if rtmp input contains NALs of type 7, 8 every GOP at the input, RTMP clients only get these type of NALs at the beginning. If the client is a transmuxer (e.g. ffmpeg), you must force reintroduction of NALs of type 7, 8 every GOP, by adding option -bsf:v h264_mp4toannexb
      • dump_extra
        • Error (ffmpeg 3.4.2):
          • ffmpeg -flags:v +global_header -bsf:v dump_extra -c:v copy ...
            • only sends NALs of type 1. NALs of type 5 are missing: the stream cannot be played
      • waiting for SPS/PPS when sending H.264 via RTP

    • RTP packet
      one several
      NAL unit one single fragmentation
      several aggregation -

    • single NAL aggregation fragmentation unit
      STAP MTAP FU-A FU-B
      A
      (w/o DON)
      B
      (w DON)
      16-bits
      offset
      timestamp
      24-bits
      offset
      timestamp


      NAL unit type -> 1-23 24 25 26 27 28 29
      packetization modes single NAL
      x





      non-interleaved

      x


      x
      interleaved


      x x x x x
  • Structure:
    frame AU layer slice NAL RTP
    # #

    type PT SN timestamp marker
    - 0

    8: PPS (96) 0 0
    1 1 base i 5: slice IDR 1 0 0
    ii 5: slice IDR 2 1?
    enh sp1 i 21: slice IDR scal 3 0
    ii 21: slice IDR scal 4 1?
    2 2 base i 2: slice A 5 3600 0
    ii 2: slice A 6 1
    3 3 base i 28: FU-A 7 7200 0
    8 0
    ii 1: slice non-IDR 9 1?
    enh sp1 i 20: slice non-IDR scal 10 0
    enh sp2 i 20: slice non-IDR scal 11 1?
    4 4 base i MTAP 12 14400 1
    5 5 base i
  • Problemes / Problems
  • Implementations:
  • SDP
    • SDP documents and standards
    • SDP in gstreamer
    • RTP audio video profile (wp)



    • info


      v=0
      c=IN IP4 ${destination_address}
      m=video ${video_rtp_port} RTP/AVP ${rtp_video_payload_type}
      a=rtpmap:${rtp_video_payload_type} H264/90000

      a=fmtp:${rtp_video_payload_type} ...

      m=audio ${audio_rtp_port} RTP/AVP ${rtp_audio_payload_type}
      a=rtpmap:${rtp_audio_payload_type} ${audio_media_subtype}/${rate}/${channels}

      a=fmtp:${rtp_audio_payload_type} ...
      video
      H.264
      m=video 5100 RTP/AVP 96
      a=rtpmap:96 H264/90000
      a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAH6zZQFAFuhAAAAMAEAAAAwMA8YMZYA==,aOvssiw=; profile-level-id=64001F
      m=video 5100 RTP/AVP 96
      a=rtpmap:96 H264/90000
      a=fmtp:96 packetization-mode=1
      VP8
      m=video 5100 RTP/AVPF 96
      a=rtpmap:96 VP8/90000
      a=fmtp:96 max-fr=30; max-fs=3600;

      VP9
      m=video 5100 RTP/AVPF 96
      a=rtpmap:96 VP9/90000
      a=fmtp:96 max-fr=30; max-fs=3600


      audio AAC (48000Hz, 2 channels)
      m=audio 5102 RTP/AVP 97
      a=rtpmap:97 mpeg4-generic/48000/2


      opus (48000Hz, 2 channels) m=audio 5102 RTP/AVP 97
      a=rtpmap:97 opus/48000/2

      a=fmtp:97 sprop-stereo=1

    • SDP generats / Generated SDP:
      • when a single instance of ffmpeg generates several rtp streams, the option sdp-file contains all the streams. To split them, use the following script:
        • sdp_split.sh
          • #!/bin/bash
            common_sdp_path=$1
            common_sdp_dirname=$(dirname $common_sdp_path)
            common_sdp_basename=$(basename $common_sdp_path)
            common_sdp_name=${common_sdp_basename%.*}
            # remove all windows line feeds (^M)
            sed -i 's/\r//g' ${common_sdp_path}
            # get the number of video streams
            number_videos=$(grep "m=video" ${common_sdp_path} | wc -l)
            for (( video=1; video<=$number_videos; video++ ))
            do
                output_sdp_path="${common_sdp_dirname}/${common_sdp_name}_${video}.sdp"
                echo "${output_sdp_path}"
                awk -v selected_video=${video} '
            BEGIN {block=0; }
            #sub(/\r/,"", $0)
            /^v=/ {flag=1}
            /^s=/ {$0=$0 "_" selected_video}
            /^m=video/ {block++}
            flag {if (block==0 || block==selected_video) {print $0}}
            ' ${common_sdp_path} >${output_sdp_path}
            done        
            exit 0
      • RTP (vlc)
        • v=0
          o=- 15549874082820351558 15549874082820351558 IN IP4 localhost
          s=toto
          i=N/A
          c=IN IP4 234.1.2.3/255
          t=0 0
          a=tool:vlc 2.1.5
          a=recvonly
          a=type:broadcast
          a=charset:UTF-8
          m=audio 1234 RTP/AVP 96
          b=RR:0
          a=rtpmap:96 mpeg4-generic/48000/6
          a=fmtp:96 streamtype=5; profile-level-id=15; mode=AAC-hbr; config=11b0; SizeLength=13; IndexLength=3; IndexDeltaLength=3; Profile=1;
          m=video 1236 RTP/AVP 96
          b=RR:0
          a=rtpmap:96 H264/90000
          a=fmtp:96 packetization-mode=1;profile-level-id=64001f;sprop-parameter-sets=Z2QAH6zZgFAEWhAAAAMAEAAAAwMA8YMZoA==,aOl4TLIs;
      • TS over RTP (vlc)
        • v=0
          o=- 15549875101994746492 15549875101994746492 IN IP4 localhost
          s=toto
          i=N/A
          c=IN IP4 234.1.2.3/255
          t=0 0
          a=tool:vlc 2.1.5
          a=recvonly
          a=type:broadcast
          a=charset:UTF-8
          m=video 5004 RTP/AVP 33
          b=RR:0
          a=rtpmap:33 MP2T/90000
      • ffmpeg -f sap sap://234.1.2.3?same_port=0 (default)
        • v=0
          o=- 0 0 IN IP4 127.0.0.1
          s=Sintel
          t=0 0
          a=tool:libavformat 55.12.100
          m=video 5004 RTP/AVP 96
          c=IN IP4 234.1.2.3/255
          b=AS:1615
          a=rtpmap:96 H264/90000
          a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAH6zZgFAEWhAAAAMAEAAAAwMA8YMZoA==,aOl4TLIs; profile-level-id=64001F
          m=audio 5006 RTP/AVP 97
          c=IN IP4 234.1.2.3/255
          b=AS:440
          a=rtpmap:97 MPEG4-GENERIC/48000/6
          a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=11B0
      • ffmpeg -f sap sap://234.1.2.3?same_port=1
        • v=0
          o=- 0 0 IN IP4 127.0.0.1
          s=Sintel
          t=0 0
          a=tool:libavformat 55.12.100
          m=video 5004 RTP/AVP 96
          c=IN IP4 234.1.2.3/255
          b=AS:1615
          a=rtpmap:96 H264/90000
          a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAH6zZgFAEWhAAAAMAEAAAAwMA8YMZoA==,aOl4TLIs; profile-level-id=64001F
          m=audio 5004 RTP/AVP 97
          c=IN IP4 234.1.2.3/255
          b=AS:440
          a=rtpmap:97 MPEG4-GENERIC/48000/6
          a=fmtp:97 profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3; config=11B0
  • Tests (only video)




    • ffplay
      gstreamer




      generated SDP
      sdp
      sdp
      caps




      ffplay -protocol_whitelist rtp,udp,file,http,https,tcp,tls -i test.sdp gst-launch-1.0 filesrc location=test.sdp ! sdpdemux name=demux demux. ! queue ! decodebin ! autovideosink gst-launch-1.0 udpsrc address=127.0.0.1 port=5004 ! "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, packetization-mode=(string)1, profile-level-id=(string)64001f,  payload=(int)96" ! queue ! rtph264depay ! decodebin ! autovideosink gst-launch-1.0 udpsrc address=127.0.0.1 port=5004 ! "application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264, packetization-mode=(string)1, profile-level-id=(string)64001f, sprop-parameter-sets=(string)\"...\", payload=(int)96" ! queue ! rtph264depay ! decodebin ! autovideosink
      ffmpeg
      test
      ffmpeg -re -f lavfi -i "testsrc=size=1280x720:rate=24" -c:v libx264 -b:v 700k -pix_fmt yuv420p -profile:v high -level:v 31 -f rtp rtp://127.0.0.1:5004 -sdp_file test.sdp
      SDP:
      v=0
      o=- 0 0 IN IP4 127.0.0.1
      s=No Name
      c=IN IP4 127.0.0.1
      t=0 0
      a=tool:libavformat 57.71.100
      m=video 5004 RTP/AVP 96
      b=AS:700
      a=rtpmap:96 H264/90000
      a=fmtp:96 packetization-mode=1
      correct
      correct
      There may be a timestamping problem, or this computer is too slow.
      • sprop from gstreamer test: correct
      • sprop from bbb: There may be a timestamping problem, or this computer is too slow.
      file
      ffmpeg -re -i bbb.mp4 -c:v copy -an -f rtp rtp://127.0.0.1:5004 -sdp_file test.sdp SDP:
      v=0
      o=- 0 0 IN IP4 127.0.0.1
      s=No Name
      c=IN IP4 127.0.0.1
      t=0 0
      a=tool:libavformat 57.71.100
      m=video 5004 RTP/AVP 96
      b=AS:698
      a=rtpmap:96 H264/90000
      a=fmtp:96 packetization-mode=1; sprop-parameter-sets=Z2QAH6zZQFAFuhAAAAMAEAAAAwMA8YMZYA==,aOvssiw=; profile-level-id=64001F
      correct
      videodecoder gstvideodecoder.c:2775:gst_video_decoder_prepare_finish_frame:<avdec_h264-0> decreasing timestamp (0:00:33.104109030 < 0:00:33.126489781)
      does not start playing
      • sprop from gstreamer test: correct
      • sprop from bbb: There may be a timestamping problem, or this computer is too slow.
      gstreamer
      test
      gst-launch-1.0 -v videotestsrc ! video/x-raw,framerate=24/1,width=1280,height=720 ! videoconvert ! x264enc ! video/x-h264,stream-format=byte-stream,profile=high ! rtph264pay config-interval=10 pt=96 ! udpsink host=127.0.0.1 port=5004 v=0
      o=- 0 0 IN IP4 127.0.0.1
      s=No Name
      c=IN IP4 127.0.0.1
      t=0 0
      a=tool:libavformat 57.71.100
      m=video 5004 RTP/AVP 96
      b=AS:700
      a=rtpmap:96 H264/90000
      a=fmtp:96 packetization-mode=1
      correct
      correct
      correct
      • sprop from gstreamer test: correct
      • sprop from bbb: There may be a timestamping problem, or this computer is too slow.
      file
      gst-launch-1.0 -v filesrc location=bbb_timecode_1280x720_700k_stereo.mp4 ! qtdemux name=demux demux.video_0 ! rtph264pay config-interval=10 pt=96 ! udpsink host=127.0.0.1 port=5004 v=0
      o=- 0 0 IN IP4 127.0.0.1
      s=No Name
      c=IN IP4 127.0.0.1
      t=0 0
      a=tool:libavformat 57.71.100
      m=video 5004 RTP/AVP 96
      b=AS:700
      a=rtpmap:96 H264/90000
      a=fmtp:96 packetization-mode=1
      correct
      videodecoder gstvideodecoder.c:2775:gst_video_decoder_prepare_finish_frame:<avdec_h264-0> decreasing timestamp (0:00:09.945574289 < 0:00:09.953238304)
      There may be a timestamping problem, or this computer is too slow.
      • sprop from gstreamer test: correct (!)
      • sprop from bbb (gstreamer verbose): There may be a timestamping problem, or this computer is too slow.

04RTMP#

  • RTMP (wp)
  • Estàndard / Standard
    • Adobe’s Real Time Messaging Protocol (pdf) (Dec 21 2012)
    • What is Real-Time Messaging Protocol (RTMP)?
      • handshake


    • nginx-rtmp-module logs
      header
      Basic Header (BH) RTMP bheader
      • Chunk Type / fmt
      • Stream ID / csid
      Chunk Message Header RTMP mheader
      • message size / mlen
      • Timestamp Delta / time
      • Message Type
        • 0x01 Set Packet Size Message
        • 0x02 Abort
        • 0x03 Acknowledge
        • 0x04 Control Message (not AMF encoded)
        • 0x05 Server Bandwidth
        • 0x06 Client Bandwidth
        • 0x07 Virtual Control
        • 0x08 Audio Packet / audio (8)
        • 0x09 Video Packet / video (9)
        • 0x0F Data Extended / (15)
        • 0x10 Container Extended / (16)
        • 0x11 Command Extended (am AMF3 type command) / (17)
        • 0x12 Data / meta (18)
        • 0x13 Container / (19)
        • 0x14 Command (An AMF0 type command) / amf_cmd (20)
          • commands
            standard
            nginx-rtmp-module log


            [debug] AMF func [info]
            7.2.1 NetConnection
            7.2.1.1 connect
            'connect'
            connect: app='my_app' args='' flashver='' swf_url='' tc_url='rtmp://192.168.1.138/my_app' page_url='' acodecs=0 vcodecs=0 object_encoding=0, client: 192.168.1.135, server: 0.0.0.0:1935
            7.2.1.2 Call

            7.2.1.3 createStream 'createstream' createStream, client: 192.168.1.135, server: 0.0.0.0:1935
            7.2.2 NetStream 7.2.2.1 play

            7.2.2.2 play2

            7.2.2.3 deleteStream 'deletestream' (1) deleteStream, client: 192.168.1.135, server: 0.0.0.0:1935
            7.2.2.4 receiveAudio

            7.2.2.5 receiveVideo

            7.2.2.6 publish 'publish' publish: name='sintel' args='' type=live silent=0, client: 192.168.1.135, server: 0.0.0.0:1935

            '@setdataframe' [debug] codec: data frame: width=640 height=360 duration=0 frame_rate=24 video=H264 (7) audio=AAC (10)
            7.2.2.7 seek

            7.2.2.8 pause

          • (1) [debug] AMF func 'deletestream' is not present when connection is closed by drop_idle_publisher: [error] live: drop idle publisher, client: 192.168.1.135, server: 0.0.0.0:1935
        • 0x15 UDP / (21)
        • 0x16 Aggregate / (22)
        • 0x17 Present / (23)




  • Timestamps
  • Ús / Usage

05HTTP Streaming#

  • Common Media Application Format - CMAF (MPEG)
  • MPEG-DASH
  • HTTP Live Streaming - HLS
    • HTTP Live Streaming draft-pantos-http-live-streaming (IETF)
    • HTTP Live Streaming Overview (Apple iPhone development center)
    • HLS Tags: Everything you need to know (MUX)
    • The HLS format (broadpeak.io)
    • codecs
      • video:
        • H.264/AVC baseline level 3.0
      • audio:
        • HE-AAC or AAC-LC up to 48 kHz, stereo audio
    • HTTP-Live-Video-Stream-Segmenter-and-Distributor (Carson McDonald)
    • iPhone HTTP Streaming with FFMpeg and an Open Source Segmenter
    • iPhone Windowed HTTP Live Streaming Using Amazon S3 and Cloudfront Proof of Concept
    • Streaming to the iPhone and iPod Touch (live, vod, multi-bitrate)
    • Streaming HowTo/Streaming for the iPhone (Videolan)
    • Galaxia HasDevTool
    • Best practices
      • Bit rate recommendations
        • "The first entry in the master playlist will be played at the initiation of a stream and is used as part of a test to determine which stream is most appropriate."
    • Xifratge / Encryption
    • Subtítols / Subtitles
      • convert srt to webvtt
        • ffmpeg -i en.srt -f webvtt en.webvtt
        • ffmpeg -i ca.srt -f webvtt ca.webvtt
      • index.m3u8
        • #EXTM3U
          #EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="English",FORCED=NO,AUTOSELECT=YES,URI="en.ttml",LANGUAGE="en"
          #EXT-X-MEDIA:TYPE=SUBTITLES,GROUP-ID="subs",NAME="Catalan",FORCED=NO,AUTOSELECT=YES,URI="ca.ttml",LANGUAGE="ca"
          #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=928000,RESOLUTION=640x360,SUBTITLES="subs"
          360p.m3u8
          #EXT-X-STREAM-INF:PROGRAM-ID=1,BANDWIDTH=2592000,RESOLUTION=1280x720,SUBTITLES="subs"
          720p.m3u8
          #EXT-X-ENDLIST
      • ca.ttml
        • #EXTM3U
          #EXT-X-VERSION:3
          #EXT-X-TARGETDURATION:3600
          #EXT-X-MEDIA-SEQUENCE:0
          #EXTINF:3600.0,
          ca.webvtt
          #EXT-X-ENDLIST
      • en.ttml
        • #EXTM3U
          #EXT-X-VERSION:3
          #EXT-X-TARGETDURATION:3600
          #EXT-X-MEDIA-SEQUENCE:0
          #EXTINF:3600.0,
          en.webvtt
          #EXT-X-ENDLIST
    • Monitor
      • AWS
        • Monitor HLS and DASH live streams using a canary monitor
          • aws-samples / monitor-hls-and-dash-streams-using-canary-monitor
            • Setup
              • AWS permissions
                • {
                      "Version": "2012-10-17",
                      "Statement": [
                          {
                              "Sid": "Statement1",
                              "Effect": "Allow",
                              "Action": [
                                  "cloudwatch:PutMetricData",
                                  "cloudwatch:ListDashboards",
                                  "cloudwatch:GetDashboard",
                                  "cloudwatch:DeleteDashboards",
                                  "cloudwatch:PutDashboard"
                              ],
                              "Resource": "*"
                          }
                      ]
                  }
              • script
                • config
                  • defaults.json
                    • ...
                • origins/demo.csv (all *.csv files in this dir will be read)
                  • # endpoint type (live), technology (hls/dash), workload name, endpoint name, origin name, monitoring config file, manifest url, tracking url [optional]
                    live, hls, my_workload, my_endpoint, my_origin, configs/default.json, https://myserver.org/path/to/index.m3u8
                    live, hls, lab, testendpoint, emp, configs/default.json, https://xxxxxx.mediapackage.us-west-2.amazonaws.com/out/v1/xxxxxx/index.mpd
            • Run
              • standalone
                • ./canarymonitor.py --region eu-west-1
              • service
                • canarymonitor.service
                  • ...
            • Generated files
              • archive
                • live
                  • my_workload
                    • my_origin
                      • my_endpoint
                        • hls
                          • reports
                            • <begin_datetime>_to_<end_datetime>.json
            • AWS CloudWatch
              • Dashboards > Custom dashboards > <WORKLOAD_NAME>-<Origin_name>-Canary-Monitor
                • verify that you have AWS permissions to manage  "cloudwatch:...Dashboards"
              • Metrics > All metrics > Browse > Custom namespaces > CanaryMonitor
                • Workload: ...
                • Endpoint
                • Origin
                • Rendition
                  • multi: index.m3u8
                  • v1: first_variant.m3u8
                • RequestType: manifest, ...
                • Technology: hls, dash
                • Type: live
                • Metric name: Latency, BufferFillDuration, ...
                • Alarms
      • Eyevinn
    • Eines / Tools
      • show cumulative time based on m3u8:
        • awk -F: '/^#EXTINF/ {gsub(/,/,"",$2); sum += $2; print $2 " " sum} /.ts/ {print $1} END {print sum}' monovariant.m3u8
      • hls_info.sh
        • #!/bin/bash
          m3u8_path=$1
          sum=0
          while read -r line
          do
              if [[ ${line} =~ ^"#EXTINF" ]]
              then
                  #echo ${line}
                  duration=$(echo ${line} | awk -F: '/^#EXTINF/ {gsub(/,/,"",$2); print $2}')
                  echo -n "---- start: ${sum} duration: ${duration} "
                  sum=$( echo "${sum}+${duration}" | bc -l)
                  echo -n "end: ${sum} "
              fi    
              if [[ ${line} =~ "ts"$ ]]
              then
                  echo "<-- ${line}"
                  ffprobe -v 0 -show_entries frame=pkt_pts_time,pict_type -print_format compact=nk=1:p=0:s='\ ' -select_streams v:0 -i ${line}
              fi    
          done < ${m3u8_path}
          echo "sum: ${sum}"
          exit 0
      • ts2m3u8.sh
        • #!/bin/bash
          function print_help_and_exit {
              cat <<EOF
          Usage: `basename $0` ts_dir ts_prefix ts_start ts_end
          Generate <ts_prefix>.gen.m3u8 file with reference to all ts files, in ts_dir, with file name:
          <ts_prefix><ts_start>.ts .. <ts_prefix><ts_stop>.ts
          Examples:
          - `basename $0` /tmp stream_low 4 55
          EOF
          }
          ts_dir=$1
          ts_prefix=$2
          ts_start=$3
          ts_end=$4
          function m3u8_header {
              # m3u8 header
              local m3u8_path=$1
              # TODO: calculate target duration from segments    
              cat >${m3u8_path} <<EOF
          #EXTM3U
          #EXT-X-VERSION:3
          #EXT-X-TARGETDURATION:2
          #EXT-X-MEDIA-SEQUENCE:1
          EOF
          }
          function m3u8_footer {
              # m3u8 footer
              local m3u8_path=$1
              cat >>${m3u8_path} <<EOF
          #EXT-X-ENDLIST
          EOF
          }
          # output m3u8 file
          m3u8_path=${ts_prefix}.gen.m3u8
          # create m3u8 header
          m3u8_header ${m3u8_path}
          # get all ts files
          ts_list=$(eval ls -vx ${ts_dir}/${ts_prefix}{$ts_start..$ts_end}.ts)
          for ts_path in ${ts_list}
          do
              # get duration in seconds (with decimals)
              duration=$(ffprobe -i $ts_path -show_format -v quiet | sed -n 's/duration=//p')
              # keep only numbers and decimal point (discard N/A):
              duration=$(echo $duration | tr -d -c 0-9.)
              echo ${ts_path} ${duration}
              ts_basename=$(basename $ts_path)
              # put information into m3u8 output file
              echo "#EXTINF:${duration}," >>${m3u8_path}
              echo ${ts_basename} >>${m3u8_path}
          done
          # create m3u8 footer
          m3u8_footer ${m3u8_path}
          exit 0
    • FAST
      • Tools
        • Eyevinn Channel Engine (VOD2Live)
          • Create your own FAST Channels based on VOD2Live Technology and Open Source Components
            • Docker examples based on docker-fast
          • Components
            • Library: Eyevinn Channel Engine
            • Implementation with plugins: FAST by Eyevinn Technology (FAST Channel Engine)
              • Docker
              • Available plugins
                • Demo
                • ScheduleService
                  • manages channels and schedules
                  • uses AWS DynamoDB (it can be local)
                • Loop
                • Playlist
                • Barker
                • WebHook
              • ...

                info plugin docker plugin access FAST Engine docker docker compose
                docker compose up
                hls player
                Loop repeats a single url

                docker run --rm -it -p 8000:8000 \
                  -e FAST_PLUGIN=Loop \
                  -e LOOP_VOD_URL=<uri-to-hls-vod> \
                  -e LOOP_CHANNEL_NAME=testchannel \
                  eyevinntechnology/fast-engine

                http://localhost:8000/channels/testchannel/master.m3u8
                Playlist retrieves a playlist and plays it from the top (any static http server)
                E.g.: nginx
                docker run -it --rm -p 8888:80 \
                  -v /tmp/html:/usr/share/nginx/html --name web nginx
                Host file:
                /tmp/html/playlist.txt

                docker run --rm -it -p 8000:8000 \
                  -e FAST_PLUGIN=Playlist \
                  -e PLAYLIST_URL=http://<container_ip_address>:80/playlist.txt \
                  -e PLAYLIST_CHANNEL_NAME=testchannel \
                  eyevinntechnology/fast-engine
                docker-compose.yaml
                services:
                  web:
                    image: nginx
                    ports:
                      - 8888:80
                    volumes:
                      - /tmp/html:/usr/share/nginx/html
                  engine:
                    image: eyevinntechnology/fast-engine
                    environment:
                      - FAST_PLUGIN=Playlist
                      - PLAYLIST_URL=http://web/playlist.txt
                      - PLAYLIST_CHANNEL_NAME=testchannel
                    ports:
                      - 8000:8000
                http://localhost:8000/channels/testchannel/master.m3u8
                ScheduleService
                DynamoDB:
                docker run --rm -d -p 6000:8000 amazon/dynamodb-local
                ScheduleService:
                docker run --rm -p 8080:8080 \
                  -e DB=dynamodb://host.docker.internal:6000/eu-north-1 \
                  -e AWS_ACCESS_KEY_ID=null \
                  -e AWS_SECRET_ACCESS_KEY=null \
                  -e IF=0.0.0.0 \
                  eyevinntechnology/schedule-service
                API docs:
                http://localhost:8080/api/docs
                Channel list:
                curl -X 'GET' \
                  'http://localhost:8080/api/v1/channels' \
                  -H 'accept: application/json'
                Current schedule for channel eyevinn:
                curl -X 'GET' \
                  'http://localhost:8080/api/v1/channels/eyevinn/schedule?date=2023-03-06' \
                  -H 'accept: application/json'
                Create a new channel:
                curl -X 'POST' \
                  'http://localhost:8080/api/v1/channels' \
                  -H 'accept: application/json' \
                  -H 'Content-Type: application/json' \
                  -d '{
                  "id": "mychannel",
                  "tenant": "test",
                  "title": "My channel"
                }'
                docker run --rm -p 8000:8000 \
                  -e OPTS_USE_DEMUXED_AUDIO=false \
                  -e FAST_PLUGIN=ScheduleService \
                  -e SCHEDULE_SERVICE_API_URL=http://host.docker.internal:8080/api/v1 \
                  eyevinntechnology/fast-engine
                DynamoDB +
                ScheduleService +
                FAST Engine:
                docker-compose.yml
                http://localhost:8000/channels/eyevinn/master.m3u8
                http://localhost:8000/channels/mychannel/master.m3u8














Audio/Video

06Descàrrega progressiva / Progressive download#

Programari / Software

07Maquinari / Hardware#

08Projectes europeus / European projects#

09Conferències / Conferences#

10Música / Music#

Platform Components Technology Where / affiliates
Pressplay
(Duet)
  • Sony
  • Vivendi Universal
  • EMI
  • Madacy, Navarre, OWIE, Razor & Tie, Roadrunner, Rounder
  • TVT Records
  • Zomba

Musicnet

  • Virgin
  • HMV
Tornado

11Xarxes CDN / Content Delivery Networks (CDN)#

12SRT Secure Reliable Transport#

  • SRT Alliance
  • Info
  • Programari / Software
    • Biblioteques / Libraries
      • Haivision / srt (GitHub)
        • needed to be installed before compiling gstreamer, ffmpeg, sls
        • dependencies
          • Mageia
            • dnf install cmake tcl libopenssl-devel
          • CentOS
            • sudo yum install cmake tcl
        • compilació / compilation
          • cd src
          • git clone https://github.com/Haivision/srt.git
          • cd srt
          • ./configure
          • make
          • sudo make install
          • NOTE: srt.pc (needed by: pkg-config --exists srt) will be installed to /usr/local/lib64/pkgconfig/ . You may need to update environment variable accordingly before configuring the compilation of other packages:
            • export PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig/:/usr/local/lib/pkgconfig/
          • update ldconfig
            • echo '/usr/local/lib64' >/etc/ld.so.conf.d/local64.conf
            • sudo ldconfig
        • eines / tools

    • encoders servers players
      software
      maquinari / hardware
      • Kiloview
        • RE-3


    • TSDuck
      • Instal·lació / Installation
        • from packages
        • from source (Building TSDuck)
          • git clone https://github.com/tsduck/tsduck.git
          • cd tsduck
          • git checkout v3.40-4165
          • sudo scripts/install-prerequisites.sh
          • make -j10 default docs-html
          • sudo make install
      • Transport Stream Utilities
      • Usage
    • MediaMTX
      • SRT
      • Escalabilitat / Scalability
      • ...


        publish from client publish from server play


        url configuration file (mediamrx.yml)
        url
        SRT
        SRT clients srt://localhost:8890?streamid=publish:mystream&pkt_size=1316
        • ffmpeg -re -stream_loop -1 -i file.ts -c copy -f mpegts 'srt://localhost:8890?streamid=publish:mystream&pkt_size=1316'

        srt://localhost:8890?streamid=read:mystream
        • FFmpeg and SRT
          • ffmpeg -i 'srt://localhost:8890?streamid=mystream:test' -c copy output.mp4

        SRT cameras and servers
        paths:
          proxied:
            # url of the source stream, in the format srt://host:port?streamid=streamid&other_parameters
            source: srt://original-url

        WebRTC
        WebRTC clients
        • web page: http://localhost:8889/mystream/publish
          • Web browsers
            • <iframe src="http://mediamtx-ip:8889/mystream/publish" scrolling="no"></iframe>
        • WHIP (no web page): http://localhost:8889/mystream/whip
          • ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 \
            -f lavfi -i "sine=frequency=1000:sample_rate=48000" \
            -c:v libx264 -pix_fmt yuv420p -preset ultrafast -b:v 600k \
            -c:a libopus -ar 48000 -ac 2 -b:a 128k \
            -f whip http://localhost:8889/stream/whip
          • gst-launch-1.0 videotestsrc \
            ! video/x-raw,width=1920,height=1080,format=I420 \
            ! x264enc speed-preset=ultrafast bitrate=2000 \
            ! video/x-h264,profile=baseline \
            ! whipclientsink signaller::whip-endpoint=http://localhost:8889/mystream/whip
          • OBS Studio and WebRTC
          • Unity
            • /unity

        • web browser
        • WHEP (no whep browser)
          • http://localhost:8889/mystream/whep
          • GStreamer and WebRTC
            • gst-launch-1.0 whepsrc whep-endpoint=http://127.0.0.1:8889/stream/whep use-link-headers=true \
              video-caps="application/x-rtp,media=video,encoding-name=H264,payload=127,clock-rate=90000" \
              audio-caps="application/x-rtp,media=audio,encoding-name=PCMU,payload=0,clock-rate=8000" \
              ! rtph264depay ! decodebin ! autovideosink
          • Unity

        WebRTC servers

        yaml:
        paths:
          proxied:
            # url of the source stream, in the format whep://host:port/path (HTTP) or wheps:// (HTTPS)
            source: wheps://host:port/path

        if remote server is a MediaMTX server:
        paths:
          proxied:
            source: whep://host:port/mystream/whep

        RTSP
        RTSP clients
        rtsp://localhost:8554/mystream
        • ffmpeg -re -stream_loop -1 -i file.ts -c copy -f rtsp rtsp://localhost:8554/mystream
        • gst-launch-1.0 rtspclientsink name=s location=rtsp://localhost:8554/mystream \
          filesrc location=file.mp4 ! qtdemux name=d \
          d.video_0 ! queue ! s.sink_0 \
          d.audio_0 ! queue ! s.sink_1
        • OpenCV

        rtsp://localhost:8554/mystream
        • FFmpeg and RTSP
          • ffmpeg -i rtsp://localhost:8554/mystream -c copy output.mp4
        • GStreamer and RTSP
          • gst-launch-1.0 rtspsrc location=rtsp://127.0.0.1:8554/mystream latency=0 ! decodebin ! autovideosink
        • VLC
          • vlc --network-caching=50 rtsp://localhost:8554/mystream
        • OBS Studio

        RTSP cameras and servers

        yaml
        paths:
          proxied:
            # url of the source stream, in the format rtsp://user:pass@host:port/path
            source: rtsp://original-url
        /proxied
        RTMP RTMP clients rtmp://localhost/mystream
        • ffmpeg -re -stream_loop -1 -i file.ts -c copy -f flv rtmp://localhost:1935/mystream
        • gst-launch-1.0 -v flvmux name=mux ! rtmpsink location=rtmp://localhost/stream \
          videotestsrc ! video/x-raw,width=1280,height=720,format=I420 ! x264enc speed-preset=ultrafast bitrate=3000 key-int-max=60 ! video/x-h264,profile=high ! mux. \
          audiotestsrc ! audioconvert ! avenc_aac ! mux.
        • OBS studio and RTMP

        rtmp://localhost/mystream
        • FFmpeg and RTMP
          • ffmpeg -i rtmp://localhost/mystream -c copy output.mp4
          • ffmpeg -rtmp_enhanced_codecs ac-3,av01,avc1,ec-3,fLaC,hvc1,.mp3,mp4a,Opus,vp09 \
            -i rtmp://localhost/mystream -c copy output.mp4

        RTMP cameras and servers
        yaml
        paths:
          proxied:
            # url of the source stream, in the format rtmp://user:pass@host:port/path
            source: rtmp://original-url

        HLS HLS cameras and servers
        yaml
        paths:
          proxied:
            # url of the playlist of the stream, in the format http://user:pass@host:port/path
            source: http://original-url/stream/index.m3u8
        MPEG-TS MPEG-TS
        • udp+mpegts
          • ffmpeg -re -stream_loop -1 -i file.ts -c copy -f mpegts 'udp://127.0.0.1:3356?pkt_size=1316'
          • gst-launch-1.0 -v mpegtsmux name=mux alignment=1 ! udpsink host=238.0.0.1 port=1234 \
            videotestsrc ! video/x-raw,width=1280,height=720,format=I420 ! x264enc speed-preset=ultrafast bitrate=3000 key-int-max=60 ! video/x-h264,profile=high ! mux. \
            audiotestsrc ! audioconvert ! avenc_aac ! mux.
        • unix+mpegts
          • ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 \
            -c:v libx264 -pix_fmt yuv420p -preset ultrafast -b:v 600k \
            -f mpegts unix:/tmp/socket.sock
        udp+mpegts
        paths:
          mypath:
            source: udp+mpegts://238.0.0.1:1234
        unix+mpegts
        paths:
          mypath:
            source: unix+mpegts:///tmp/socket.sock

        RTP RTPhttps://mediamtx.org/docs/usage/publish#rtp
        • udp+rtp
          • ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 \
            -c:v libx264 -pix_fmt yuv420p -preset ultrafast -b:v 600k \
            -f rtp udp://238.0.0.1:1234?pkt_size=1316
        • unix+rtp
          • ffmpeg -re -f lavfi -i testsrc=size=1280x720:rate=30 \
            -c:v libx264 -pix_fmt yuv420p -preset ultrafast -b:v 600k \
            -f rtp unix:/tmp/socket.sock
        udp+rtp
        paths:
          mypath:
            source: udp+rtp://238.0.0.1:1234
            rtpSDP: |
              v=0
              o=- 123456789 123456789 IN IP4 192.168.1.100
              s=H264 Video Stream
              c=IN IP4 192.168.1.100
              t=0 0
              m=video 5004 RTP/AVP 96
              a=rtpmap:96 H264/90000
              a=fmtp:96 profile-level-id=42e01e;packetization-mode=1;sprop-parameter-sets=Z0LAHtkDxWhAAAADAEAAAAwDxYuS,aMuMsg==
        unix+rtp
        paths:
          mypath:
            source: unix+rtp:///tmp/socket.sock
            rtpSDP: |
              v=0
              o=- 123456789 123456789 IN IP4 192.168.1.100
              s=H264 Video Stream
              c=IN IP4 192.168.1.100
              t=0 0
              m=video 5004 RTP/AVP 96
              a=rtpmap:96 H264/90000
              a=fmtp:96 profile-level-id=42e01e;packetization-mode=1;sprop-parameter-sets=Z0LAHtkDxWhAAAADAEAAAAwDxYuS,aMuMsg==

        RPi Raspberry Pi cameras
        paths:
          cam:
            source: rpiCamera
        /cam

        Adding audio



        Secondary stream


        Webcam Generic webcams
        paths:
          cam:
            runOnInit: ffmpeg -f v4l2 -i /dev/video0 -c:v libx264 -pix_fmt yuv420p -preset ultrafast -b:v 600k -f rtsp rtsp://localhost:$RTSP_PORT/$MTX_PATH
            runOnInitRestart: yes
        /cam
      • Documentation
      • Metrics and statistics
        • similar to statistics in:
        • Get RTMP Metrics (Codec, FPS, Size, Codec) #5264
        • API (>=v1.17.0)
          • curl http://127.0.0.1:9997/v3/paths/list
            • {
                "itemCount": 1,
                "pageCount": 1,
                "items": [
                  {
                    "name": "mystream",
                    "confName": "all_others",
                    "ready": true,
                    "readyTime": "2026-03-21T10:38:59.27277763+01:00",
                    "available": true,
                    "availableTime": "2026-03-21T10:38:59.27277763+01:00",
                    "online": true,
                    "onlineTime": "2026-03-21T10:38:59.272778529+01:00",
                    "source": {
                      "type": "rtmpConn",
                      "id": "0b2d2961-0cc3-43e3-a7dd-8211f127db89"
                    },
                    "tracks": [
                      "H264",
                      "MPEG-4 Audio"
                    ],
                    "tracks2": [
                      {
                        "codec": "H264",
                        "codecProps": {
                          "width": 480,
                          "height": 270,
                          "profile": "High",
                          "level": "2.1"
                        }
                      },
                      {
                        "codec": "MPEG-4 Audio",
                        "codecProps": {
                          "sampleRate": 48000,
                          "channelCount": 2
                        }
                      }
                    ],

                    "readers": [],
                    "inboundBytes": 4878631,
                    "outboundBytes": 1706329,
                    "inboundFramesInError": 0,
                    "bytesReceived": 4878631,
                    "bytesSent": 1706329
                  }
                ]
              }
          • convert json to html
            • nginx JavaScript module (njs)
            • mtx.conf
              • load_module modules/ngx_http_js_module.so;
                events {  }
                http {
                    js_path "/etc/nginx/njs/";
                    js_import main from http/mtx.js;
                    server {
                        listen 80;
                        location /show-data {
                            js_content main.fetchAndTransform;
                        }
                    }
                }
            • mtx.js
              • async function fetchAndTransform(r) {
                    try {
                        let reply = await ngx.fetch('http://192.168.1.149:9997/v3/paths/list');
                        let data = await reply.json();
                        // Generem l'HTML a partir del JSON rebut
                        r.error("DEBUG JSON: " + JSON.stringify(data, null, 2));
                        let llistaHtml = data.items.map(i => `
                <tr>
                  <td>${i.name}</td>
                  <td>${i.tracks2[0].codec} ${i.tracks2[0].codecProps.profile} ${i.tracks2[0].codecProps.level}</td>
                  <td>b/s</td>
                  <td>${i.tracks2[0].codecProps.width}x${i.tracks2[0].codecProps.height}</td>
                  <td>fps</td>
                  <td>${i.tracks2[1].codec}</td>
                  <td>b/s</td>
                  <td>${i.tracks2[1].codecProps.sampleRate}</td>
                  <td>${i.tracks2[1].codecProps.channelCount}</td>
                </tr>`).join('');
                        let htmlFinal = `<!DOCTYPE html>
                            <html>
                                <body>
                                    <table border="1">
                                      <tr>
                                        <th>name</th>
                                        <th>video codec</th>
                                        <th>video bit-rate</th>
                                        <th>video size</th>
                                        <th>video fps</th>
                                        <th>audio codec</th>
                                        <th>audio bit-rate</th>
                                        <th>audio sampling-rate</th>
                                        <th>audio channels</th>
                                      </tr>
                                      <tbody>${llistaHtml}</tbody>
                                    </table>
                                </body>
                            </html>`;
                        r.headersOut['Content-Type'] = 'text/html; charset=utf-8';
                        r.return(200, htmlFinal);
                    } catch (e) {
                        r.return(500, "Error connectant amb l'API externa");
                    }
                }
                export default { fetchAndTransform };
    • SRS
    • SRT Live Server
      • fork pros
        cons
        Edward-Wu
        • stats not working
        • minor change to make it compile in Ubuntu 24.04 (make error #139):
          • sed -i '/#include <sys\/time.h>/ i #include <time.h>' slscore/common.cpp
        odensc
        • minor change to make it compile in Ubuntu 24.04 (make error #139):
          • sed -i '/#include <sys\/time.h>/ i #include <time.h>' slscore/common.cpp
        OpenIRL
        • stats not working
        irlserver
        • latest version (...) is not compiling
        • no git labels
        rstular

      • Docker
        • ravenium/srt-live-server (Docker Hub)
          • ravenium/srt-live-server (GitHub)
            • option a: from public repo DockerHub:
              • run container:
                • docker run -d -p 1935:1935/udp ravenium/srt-live-server
              • or run compose (not working on Mageia Linux):
                • mkdir -p logs; chmod a+w logs; docker compose up
            • option b: build your own image and run from it:
              1. clone repo
                • cd src
                • git clone https://github.com/ravenium/srt-live-server.git
                • cd srt-live-server
              2. build local image
                • docker build -t local-srt-live-server .
                • verify:
                  • docker image ls
              3. run container:
                • docker run -d -p 1935:1935/udp local-srt-live-server
                • verify that container is running:
                  • docker container ls -a
              4. or run from compose:
                • local-docker-compose.yaml
                  • version: '3'
                    services:
                      srt:
                        image: local-srt-live-server
                        ports:
                          - "1935:1935/udp"
                        volumes:
                          - ./sls.conf:/etc/sls/sls.conf
                          - ./logs:/logs
                • docker compose --file local-docker-compose.yml up
      • compilació / compilation
        • cd src
        • git clone https://github.com/Edward-Wu/srt-live-server.git
        • cd srt-live-server
        • # path to find libsrt
          export
          PKG_CONFIG_PATH=/usr/local/lib64/pkgconfig/:/usr/local/lib/pkgconfig/
        • make
      • config
      • ús / usage
        • cd src/srt-live-server/bin
        • ./sls -c ../sls.conf
        • port=8080
        • server_ip="192.168.1.141"
        • transmit with ffmpeg (caller):
          • ffmpeg -re -f lavfi -i testsrc=size=320x240:r=15 -f lavfi -i anoisesrc=a=0.2 -c:v libx264 -profile:v baseline -b:v 1M -pix_fmt yuv420p -c:a aac -b:a 16k -f mpegts "srt://${server_ip}:${port}?streamid=uplive.sls.com/live/test"
        • transmit an existing file with srt-live-client (bin/slc)
          • ./slc -r srt://${server_ip}:${port}?streamid=uplive.sls.com/live/test -i source_file.ts
        • transmit with obs (compiled wit srt-enabled ffmpeg):
          • Server: srt://192.168.1.141:8080?streamid=uplive.sls.com/live/test
          • Key: (empty)
        • receive with ffplay (caller):
          • ffplay -i "srt://${server_ip}:${port}?streamid=live.sls.com/live/test"
        • receive with srt-live-client (bin/slc) and generate a file:
          • ./slc -r srt://${server_ip}:${port}?streamid=live.sls.com/live/test -o destination_file.ts
      • estadístiques / statistics
        • similar to statistics in:
        • NOTE: use odensc fork
        • sls.conf
          • srt {
                stat_post_url http://127.0.0.1/unit/sls/stat ;
                stat_post_interval 5;
            }
        • unit behind nginx
          • unit.conf
            • location /unit/ {
                  proxy_pass http://127.0.0.1:8090/;
                  proxy_set_header Host $host;
                  proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
              }
        • /etc/fastapi/
          • asgi.py
            • from pathlib import Path
              from fastapi import FastAPI, Request
              from fastapi.templating import Jinja2Templates
              from pydantic import BaseModel
              app = FastAPI()
              # variable to store the values received by post
              app.statistics = []
              # absolute path for templates
              BASE_DIR = Path(__file__).resolve().parent
              templates = Jinja2Templates(directory=str(Path(BASE_DIR, "templates")))
              class Statistics(BaseModel):
                  port: str
                  role: str
                  pub_domain_app: str
                  stream_name: str
                  url: str
                  remote_ip: str
                  remote_port: str
                  start_time: str
                  kbitrate: str
              @app.get("/sls/statistics")
              async def get_statistics(request: Request):
                  """
                  Return html table with statistics
                  """
                  # print(app.statistics)
                  context = [st.dict() for st in app.statistics]
                  return templates.TemplateResponse(
                      request=request,
                      name="statistics.html",
                      context={"statistics": context},
                  )
              @app.get("/sls/stat")
              async def get_stat():
                  return app.statistics
              @app.post("/sls/stat")
              async def post_stat(statistics: list[Statistics]):
                  # curl -i -X POST -H 'Content-Type: application/json' --data '[{"port": "8080","role": "player","pub_domain_app": "uplive.sls.com/live","stream_name": "test","url": "live.sls.com/live/test","remote_ip": "192.168.1.146","remote_port": "60788","start_time": "2025-04-25 17:54:43","kbitrate": "1724"}]' http://localhost:8090/sls/stat
                  # sample body:
                  # [
                  #     {
                  #         "port": "8080",
                  #         "role": "player",
                  #         "pub_domain_app": "uplive.sls.com/live",
                  #         "stream_name": "test",
                  #         "url": "live.sls.com/live/test",
                  #         "remote_ip": "192.168.1.146",
                  #         "remote_port": "60788",
                  #         "start_time": "2025-04-25 17:54:43",
                  #         "kbitrate": "1724",
                  #     },
                  #     {
                  #         "port": "8080",
                  #         "role": "publisher",
                  #         "pub_domain_app": "uplive.sls.com/live",
                  #         "stream_name": "test",
                  #         "url": "uplive.sls.com/live/test",
                  #         "remote_ip": "192.168.1.146",
                  #         "remote_port": "36141",
                  #         "start_time": "2025-04-25 17:53:45",
                  #         "kbitrate": "1745",
                  #     },
                  #     {
                  #         "port": "8080",
                  #         "role": "listener",
                  #         "pub_domain_app": "",
                  #         "stream_name": "",
                  #         "url": "",
                  #         "remote_ip": "",
                  #         "remote_port": "",
                  #         "start_time": "2025-04-25 17:52:31",
                  #         "kbitrate": "0",
                  #     },
                  # ]
                  # body = await request.body()
                  # print(body)
                  # return {"status": "OK"}
                  app.statistics = statistics
                  return statistics
              @app.post("/sls/on_event")
              async def on_event(
                  on_event: str, role_name: str, srt_url: str, remote_ip: str, remote_port: int
              ):
                  # "POST /sls/on_event?on_event=on_connect&role_name=publisher&srt_url=publish/stream/fa0c67a2d70bb2c2-5464f06ed01a6b6e&remote_ip=139.47.125.46&remote_port=39642 HTTP/1.1" 200 OK
                  # "POST /sls/on_event?on_event=on_close&role_name=publisher&srt_url=publish/stream/fa0c67a2d70bb2c2-5464f06ed01a6b6e&remote_ip=139.47.125.46&remote_port=39642 HTTP/1.1" 200 OK
                  # on_event=on_connect
                  # role_name=publisher
                  # srt_url=publish/stream/fa0c67a2d70bb2c2-5464f06ed01a6b6e&
                  # remote_ip=139.47.125.46
                  # remote_port=39642
                  # body = await request.body()
                  # print(body)
                  print("  on_event: {}".format(on_event))
                  print("  role_name: {}".format(role_name))
                  print("  srt_url: {}".format(srt_url))
                  print("  remote_ip: {}".format(remote_ip))
                  print("  remote_port: {}".format(remote_port))
                  return {"status": "OK"}
          • templates/statistics.html
            • <html>
              <head>
                  <title>Statistics</title>
              </head>
              <body>
                  <h1>Statistics</h1>
                  <table border="1">
                      <tr>
                          <th>port</th>
                          <th>role</th>
                          <th>pub_domain_app</th>
                          <th>stream_name</th>
                          <th>url</th>
                          <th>remote_ip</th>
                          <th>remote_port</th>
                          <th>start_time</th>
                          <th>kbitrate</th>
                      </tr>
                      {% for stat in statistics %}
                      <tr>
                          <td>{{ stat.port }}</td>
                          <td>{{ stat.role }}</td>
                          <td>{{ stat.pub_domain_app }}</td>
                          <td>{{ stat.stream_name }}</td>
                          <td>{{ stat.url }}</td>
                          <td>{{ stat.remote_ip }}</td>
                          <td>{{ stat.remote_port }}</td>
                          <td>{{ stat.start_time }}</td>
                          <td>{{ stat.kbitrate }}</td>
                      </tr>
                      {% endfor %}        
                  </table>
              </body>
              </html>
        • set config
          • ...
        • get config:
          • curl -X GET --unix-socket /var/run/control.unit.sock http://localhost:8090/config/
        • get statistics:
          • http://my_server/unit/sls/statistics
    • modes (Medium: SRT)
      mode host port
      caller remote host remote port
      listener
      local listening port
      rendezvous other public host local and remote port
    • ...

      conf publish play
      SLS (Edward-Wu) # sls.conf
      server {
        listen 8080;
        domain_player live.sls.com live-1.sls.com;
        domain_publisher uplive.sls.com;
        app {
          app_player live;
          app_publisher live;
        }
      }
      srt://[your.sls.ip]:8080?streamid=uplive.sls.com/live/test srt://[your.sls.ip]:8080?streamid=live.sls.com/live/test
      SLS (OpenIRL) # sls.conf
      server {
        listen 4001;
        domain_player play;
        domain_publisher publish;
        app {
          app_player stream;
          app_publisher stream;
        }
      }
      srt://[your.sls.ip]:4001?streamid=publish/stream/test srt://[your.sls.ip]:4001?streamid=play/stream/test
      MediaMTX # mediamtx.yml
      • custom streamid syntax
        • srt://localhost:8890?streamid=publish:mystream&pkt_size=1316
        • srt://localhost:8890?streamid=publish:mystream:user:pass&pkt_size=1316
      • standard streamid syntax (SRT Access Control (Stream ID) Guidelines):
        • srt://localhost:8890?streamid=#!::m=publish,r=mypath,u=myuser,s=mypass&pkt_size=1316
          • m=<mode: publish, request, bidirectional>
          • r=<resource_name>
          • u=<username>
          • s=<session_id>
          • h=<host_name>
          • t=<type: stream, file, auth>
      • custom streamid syntax
        • srt://localhost:8890?streamid=read:mystream
        • srt://localhost:8890?streamid=read:mystream:user:pass
      • standard streamid syntax:
        • ...

    • transmitter Tx receiver Rx

      gst-launch-1.0 -v videotestsrc ! "video/x-raw,height=360,width=640" ! videoconvert ! x264enc tune=zerolatency ! "video/x-h264,profile=baseline" ! mpegtsmux ! srtsink uri="srt://:8888/" gst-launch-1.0 -v srtsrc uri=srt://127.0.0.1:8888 ! decodebin ! autovideosink

      ffmpeg -re -f lavfi -i testsrc=size=320x240:r=15 -f lavfi -i sine=f=440:b=1 -c:v libx264 -profile:v baseline -b:v 1M -pix_fmt yuv420p -c:a aac -b:a 16k -f mpegts srt://:8888
      ffplay srt://127.0.0.1:8888
      • transmitter is a client
        (caller)
      • receiver is a server
        (listener; should be started first)
      • port=9998
      • receiver_ip="192.168.1.141"
      • ffmpeg ... -f mpegts "srt://${receiver_ip}:${port}?pkt_size=1316"
      • from test source:
        • ffmpeg -re -f lavfi -i testsrc=size=320x240:r=15 -f lavfi -i anoisesrc=a=0.2 -c:v libx264 -profile:v baseline -b:v 1M -pix_fmt yuv420p -c:a aac -b:a 16k -f mpegts "srt://${receiver_ip}:${port}?pkt_size=1316"
        • gst-launch-1.0 -v videotestsrc ! "video/x-raw,height=360,width=640" ! videoconvert ! x264enc tune=zerolatency ! "video/x-h264,profile=baseline" ! mpegtsmux ! srtsink uri="srt://${receiver_ip}:${port}/"
      • transmux from udp:
        • ffmpeg -fflags +genpts -listen 1 -re -i udp://239.0.0.1:1234?pkt_size=1316 -acodec copy -vcodec copy -strict -2 -y -f mpegts "srt://${receiver_ip}:${port}?pkt_size=1316"
      • port=9998
      • ffplay -i "srt://0.0.0.0:${port}?pkt_size=1316&mode=listener"
      • ffmpeg -re -i "srt://0.0.0.0:${port}?pkt_size=1316&mode=listener" ...
      • gst-launch-1.0 -v srtsrc uri="srt://:${port}" mode=listener ! decodebin ! autovideosink
      • transmux to udp:
        • ffmpeg -re -i "srt://0.0.0.0:${port}?pkt_size=1316&mode=listener" -vcodec copy -acodec copy -strict -2 -y -f mpegts udp://239.0.0.2:1234?pkt_size=1316
      • transmitter is a server
        (listener; should be started first)
      • receiver is a client
        (caller)
      • port=9998
      • ffmpeg ... -f mpegts "srt://0.0.0.0:${port}?pkt_size=1316&mode=listener"
      • from test source:
        • ffmpeg -re -f lavfi -i testsrc=size=320x240:r=15 -f lavfi -i anoisesrc=a=0.2 -c:v libx264 -profile:v baseline -b:v 1M -pix_fmt yuv420p -c:a aac -b:a 16k -f mpegts "srt://0.0.0.0:${port}?pkt_size=1316&mode=listener"
        • gst-launch-1.0 -v videotestsrc ! "video/x-raw,height=360,width=640" ! videoconvert ! x264enc tune=zerolatency ! "video/x-h264,profile=baseline" ! mpegtsmux ! srtsink uri="srt://${receiver_ip}:${port}/" mode=listener
      • transmux from udp (e.g. 239.0.0.1:1234):
        • ffmpeg -fflags +genpts -listen 1 -re -i udp://239.0.0.1:1234?pkt_size=1316 -acodec copy -vcodec copy -strict -2 -y -f mpegts "srt://0.0.0.0:${port}?pkt_size=1316&mode=listener"
      • port=9998
      • transmitter_ip="192.168.1.141"
      • ffplay -i "srt://${transmitter_ip}:${port}?pkt_size=1316"
      • ffmpeg -re -i "srt://${transmitter_ip}:${port}?pkt_size=1316" ...
      • gst-launch-1.0 -v srtsrc uri="srt://${transmitter_ip}:${port}" ! decodebin ! autovideosink
      • transmux to udp:
        • ffmpeg -re -i "srt://${transmitter_ip}:${port}?pkt_size=1316" -vcodec copy -acodec copy -strict -2 -y -f mpegts udp://239.0.0.2:1234?pkt_size=1316
      • rendezvous
      • port=9998
      • receiver_public_ip="192.168.1.141"
      • from test source:
        • ffmpeg -re -f lavfi -i testsrc=size=320x240:r=15 -f lavfi -i anoisesrc=a=0.2 -c:v libx264 -profile:v baseline -b:v 1M -pix_fmt yuv420p -c:a aac -b:a 16k -f mpegts "srt://${receiver_public_ip}:${port}?pkt_size=1316&mode=rendezvous"
      • port=9998
      • transmitter_public_ip="192.168.1.141"
      • ffplay -i "srt://${transmitter_public_ip}:${port}?pkt_size=1316&mode=rendezvous"
    • NOTE: use pkt_size=1316 to allocate 7 TS packets into one IP packet: 188*7=1316 < 1500
    • Problemes / Problems

13RIST Reliable Internet Stream Transport#

14Gestió de drets / Rights Management (DRM)#

15Signatura / Signature#

16Xifratge / Encryption#

  • Estaǹdards / Standards
  • Eines / Tools

    command (Bento4)
    standard
    encrypt
    decrypt
    DCF
    mp4dcfpackager --method CTR
    --content-id cid:toto
    --key 000102030405060708090a0b0c0d0e0f:00000000000000000000000000000000
    toto.mp4 toto.dcf
    mp4decrypt
    --key 1:00112233445566778899aabbccddeeff
    toto.dcf toto.odf
    mp4extract toto.odf
    PDCF
    mp4encrypt --method OMA-PDCF-CTR
    --key 1:000102030405060708090a0b0c0d0e0f:0000000000000000
    --key 2:000102030405060708090a0b0c0d0e0f:0000000000000000
    toto.mp4 toto.pdcf
    mp4decrypt
    --key 1:000102030405060708090a0b0c0d0e0f:0000000000000000
    --key 2:000102030405060708090a0b0c0d0e0f:0000000000000000
    toto.pdcf toto.mp4

17Gestió de pagaments / Payment management#

18Formats ( * )#

19Seqüències / Sequencies#

20P2P (Peer to peer)#

21Reproductors MP3 Players#



dim LCD ràdio recording bluetooth video doc preu





dim res colors FM RDS FM line mic


1GB
(Z)
2GB (Q) 4GB
(A)










live prog







Samsung YP-F2R 28 52 15


x x -
-






YP-T7 37 62 14
96x96 65K - - -
-
-




YP-T7F 37 62 14 1,2" 96x96 262K x x x x x
- MPEG4
135, 138+9+iva

YP-T8 44 83 15 1,8" 128x160 262K x - x


-


169
YP-T9J
(unoff)
43 83 11 1,8" 172x220 262K x x x - - x x SVI: XVID 208x176 15 fps pdf 169+9+iva 155+9,9ii
189+9+iva
169+22ii
239+9+iva
199+22ii
YP-Z5F 42 90 12 1,8" 128x160
x x x
-

MPEG4
118 159, 149
F: FM
X: 512MB
Z: 1GB
Q: 2GB
A: 4GB

http://www.francescpinyol.cat/online_audio_video.html
Darrera modificació: 26 de juny de 2026 / Last update: 26th June 2026

Cap a casa / Back home.