Skip to content

xivid.bat

Reino Wijnsma edited this page Jul 4, 2021 · 1 revision

'xivid.bat'

De basis

Een simpele aanroep met alleen een programma-url toont de video-url van de video met de hoogste resolutie en/of bitrate.

xivid.bat https://www.npostart.nl/nos-journaal/28-02-2017/POW_03375558
https://npo.prd.cdn.bcms.kpn.com/[...]/POW_03375558_v4-audio=128000-video=1109000.m3u8

Let op! Bevat de programma-url een =-teken, gebruik dan altijd dubbele aanhalingstekens ("<programma-url>").

Met de optie -f wordt de video-url van een ander gewenst formaat, of meerdere gewenste formaten, getoond. Eindigt het id op een $, dan wordt het formaat met het hoogste nummer getoond.

xivid.bat -f hls-4 https://www.npostart.nl/nos-journaal/28-02-2017/POW_03375558
https://npo.prd.cdn.bcms.kpn.com/[...]/POW_03375558_v4-audio=128000-video=506000.m3u8

xivid.bat -f hls-$+sub-1 https://www.npostart.nl/nos-journaal/28-02-2017/POW_03375558
https://npo.prd.cdn.bcms.kpn.com/[...]/POW_03375558_v4-audio=128000-video=1109000.m3u8
https://assetscdn.npostart.nl/subtitles/original/nl/POW_03375558.vtt

De optie -i toont video informatie, incl. een opsomming van alle beschikbare formaten.

xivid.bat -i https://www.npostart.nl/nos-journaal/28-02-2017/POW_03375558
Naam:      NOS Journaal 20.00 uur
Datum:     28-02-2017 20:00:00
Tijdsduur: 00:25:37
Formaten:  id     formaat         taal  resolutie  bitrate
           sub-1  vtt             nl
           hls-0  m3u8[manifest]
           hls-1  m3u8[aac]                        64kbps
           hls-2  m3u8[aac]                        128kbps
           hls-3  m3u8[h264+aac]        480x270    203|64kbps
           hls-4  m3u8[h264+aac]        640x360    506|128kbps
           hls-5  m3u8[h264+aac]        768x432    707|128kbps
           hls-6  m3u8[h264+aac]        1024x576   1109|128kbps (best)

De optie -j toont de video informatie als JSON. De datum notatie altijd als "UTC+0 xs:dateTime" en de tijdsduur notatie altijd als xs:duration.

xivid.bat -j https://www.npostart.nl/POW_03375558
{
  "name": "NOS Journaal",
  "date": "2017-02-28T19:00:00Z",
  "duration": "PT25M37S",
  "formats": [
    {
      "id": "sub-1",
      "format": "vtt",
      "language": "nl",
      "label": "Nederlands",
      "url": "https://assetscdn.npostart.nl/subtitles/original/nl/POW_03375558.vtt"
    },
    {
      "id": "hls-0",
      "format": "m3u8[manifest]",
      "url": "https://npo.prd.cdn.bcms.kpn.com/[...]/POW_03375558/POW_03375558_v4.ism/playlist.m3u8"
    },
    {
      "id": "hls-1",
      "format": "m3u8[aac]",
      "bitrate": "64kbps",
      "url": "https://npo.prd.cdn.bcms.kpn.com/[...]/POW_03375558/POW_03375558_v4.ism/POW_03375558_v4-audio=64000.m3u8"
    },
    {
      "id": "hls-2",
      "format": "m3u8[aac]",
      "bitrate": "128kbps",
      "url": "https://npo.prd.cdn.bcms.kpn.com/[...]/POW_03375558/POW_03375558_v4.ism/POW_03375558_v4-audio=128000.m3u8"
    },
    {
      "id": "hls-3",
      "format": "m3u8[h264+aac]",
      "resolution": "480x270",
      "bitrate": "203|64kbps",
      "url": "https://npo.prd.cdn.bcms.kpn.com/[...]/POW_03375558/POW_03375558_v4.ism/POW_03375558_v4-audio=64000-video=203000.m3u8"
    },
    {
      "id": "hls-4",
      "format": "m3u8[h264+aac]",
      "resolution": "640x360",
      "bitrate": "506|128kbps",
      "url": "https://npo.prd.cdn.bcms.kpn.com/[...]/POW_03375558/POW_03375558_v4.ism/POW_03375558_v4-audio=128000-video=506000.m3u8"
    },
    {
      "id": "hls-5",
      "format": "m3u8[h264+aac]",
      "resolution": "768x432",
      "bitrate": "707|128kbps",
      "url": "https://npo.prd.cdn.bcms.kpn.com/[...]/POW_03375558/POW_03375558_v4.ism/POW_03375558_v4-audio=128000-video=707000.m3u8"
    },
    {
      "id": "hls-6",
      "format": "m3u8[h264+aac]",
      "resolution": "1024x576",
      "bitrate": "1109|128kbps",
      "url": "https://npo.prd.cdn.bcms.kpn.com/[...]/POW_03375558/POW_03375558_v4.ism/POW_03375558_v4-audio=128000-video=1109000.m3u8"
    }
  ]
}

De hier gebruikte programma-url (in het laatste voorbeeld de verkorte variant) is van het NOS Journaal van 28-02-2017 20:00u en is het laatste onversleutelde NOS Journaal. Vanaf 01-03-2017 zijn bijna alle video's op npostart.nl versleuteld en beveiligd met DRM en zijn daardoor, buiten de videospeler op npostart.nl om, niet te bekijken of te downloaden.

JSON ontleding

De twee urls die -f hls-$+sub-1 hier boven toont zou je ook zelf kunnen achterhalen met optie -j en een JSON parser zoals xidel. Sterker nog, dat is precies wat er onderhuids gebeurt.

xivid.bat -j https://www.npostart.nl/POW_03375558 | xidel -s -e "$json/(formats)()[id='hls-6']/url" -e "$json/(formats)()[id='sub-1']/url"
xivid.bat -j https://www.npostart.nl/POW_03375558 | xidel -se "$json/formats/(.()[8],.()[1])/url"
xivid.bat -j https://www.npostart.nl/POW_03375558 | xidel -se "$json/formats/(.()[last()],.()[id='sub-1'])/url"
xivid.bat -j https://www.npostart.nl/POW_03375558 | xidel -se "$json/reverse((formats)()[id='hls-6' or id='sub-1'])/url"
xivid.bat -j https://www.npostart.nl/POW_03375558 | xidel -se "$json/reverse((formats)()[id=('hls-6','sub-1')])/url"
xivid.bat -j https://www.npostart.nl/POW_03375558 | xidel -se "$json/reverse((formats)()[position() = (1,last())])/url"
xivid.bat -j https://www.npostart.nl/POW_03375558 | xidel -se "for $x in ('hls-$','sub-1') return if (ends-with($x,'$')) then $json/(formats)()[starts-with(id,substring($x,1,string-length($x) - 1))][last()]/url else $json/(formats)()[id=$x]/url"

De JSON output van xivid.bat wordt, door de "pipe" (|), de input voor xidel. Alle varianten (de laatste vind je in xivid.bat terug) tonen dezelfde twee urls als -f hls-$+sub-1 hier boven doet.

Ander voorbeeld. Stel je wilt de video-url van een video waarvan de resolutie 1280x720 is.

xivid.bat -j <programma-url> | xidel -se "$json/(formats)()[resolution='1280x720']/url"

Variabelen

FOR /F "delims=" %A IN ('xivid.bat <programma-url>') DO SET url=%A
FOR /F "delims=" %A IN ('xivid.bat -f <id>+<id> <programma-url>') DO (
  IF NOT DEFINED url[0] (SET url[0]=%A) ELSE (SET url[1]=%A)
)

Deze old-school methode werkt prima als je %url%, %url[0]%, of %url[1]% direct als argument voor een willekeurig programma/script gebruikt. Zolang je ze maar niet "ECHOot". Want zodra de url bijv. &-tekens bevat, dan ben je de klos, omdat cmd de tekens tussen de &-tekens in gaat interpreteren als commando's die uitgevoerd moeten worden.

Wil je de variabelen toch kunnen "ECHOën", dan kun je je beter wenden tot xidel.

FOR /F "delims=" %A IN ('xivid.bat <programma-url> ^| xidel -se "url:=$raw" --output-format^=cmd') DO %A
FOR /F "delims=" %A IN ('xivid.bat -f <id>+<id> <programma-url> ^| xidel -se "url:=x:lines($raw)" --output-format^=cmd') DO %A

Met --output-format=cmd voorziet xidel de variabelen automatisch van de nodige "escape characters", wat voorkomt dat cmd het &-teken zal interpreteren als aanzet om hetgeen daarna als commando uit te voeren.

Bij de tweede commando maakt x:lines() een reeks van $raw. Vervolgens zorgt --output-format=cmd er voor dat de urls beschikbaar worden als %url[0]% en %url[1]%.

Video bekijken

Je kunt natuurlijk de output van xivid.bat <programma-url> kopiëren en plakken in het input-venster van je favoriete mediaspeler, maar je kunt dit ook op verschillende manieren automatiseren.

Eén video-url

FOR /F "delims=" %A IN ('xivid.bat <programma-url>') DO @"C:\Program Files\MPC-HC\mpc-hc.exe" %A

Met een variabele

FOR /F "delims=" %A IN ('xivid.bat <programma-url>') DO @SET url=%A

FOR /F "delims=" %A IN ('xivid.bat <programma-url> ^| xidel -se "url:=$raw" --output-format^=cmd') DO @%A

"C:\Program Files\MPC-HC\mpc-hc.exe" %url%

Een video- en audio-url

Dit is het geval bij RTL. Ik neem deze RTL Nieuws uitzending als voorbeeld.

xivid.bat -i https://www.rtlxl.nl/programma/rtl-nieuws/703733a3-0b3a-381b-9bc4-4255626c89eb
Naam:      RTL: RTL Nieuws - RTL Nieuws - 19:30 uur
Datum:     23-06-2021 19:30:00
Tijdsduur: 00:20:38
Formaten:  id     formaat         resolutie  bitrate
           hls-0  m3u8[manifest]
           hls-1  m3u8[aac]                  136kbps
           hls-2  m3u8[h264+aac]  336x192    522kbps
           hls-3  m3u8[h264+aac]  512x288    742kbps
           hls-4  m3u8[h264+aac]  704x400    1153kbps
           hls-5  m3u8[h264+aac]  912x512    2422kbps
           hls-6  m3u8[h264+aac]  1280x720   4241kbps (best)

Ondanks dat hls-2 t/m hls-6 video én audio zouden moeten hebben (volgens het HLS-manifest in ieder geval, welke xivid.xqm ontleedt), zijn het alleen videostreams en zul je ze dus altijd met hls-1 moeten combineren.

Met variabelen

FOR /F "delims=" %A IN ('xivid.bat -f hls-$+hls-1 <programma-url>') DO @(
  IF NOT DEFINED url[0] (SET url[0]=%A) ELSE (SET url[1]=%A)
)

FOR /F "delims=" %A IN ('
  xivid.bat -f hls-$+hls-1 <programma-url> ^| xidel -se "url:=x:lines($raw)" --output-format^=cmd
') DO @%A

"C:\Program Files\MPC-HC\mpc-hc.exe" %url[0]% /dub %url[1]%

Met xidel

FOR /F "delims=" %A IN ('
  xivid.bat -f hls-$+hls-1 <programma-url> ^| xidel -se "join(x:lines($raw),' /dub ')"
') DO @"C:\Program Files\MPC-HC\mpc-hc.exe" %A

Natuurlijk kun je ook met de optie -j en xidel de JSON ontleden.

FOR /F "delims=" %A IN ('
  xivid.bat -j <programma-url> ^| xidel -se "join($json/formats/(.()[starts-with(id,'hls-')][last()],.()[id='hls-1'])/url,' /dub ')"
') DO @"C:\Program Files\MPC-HC\mpc-hc.exe" %A

Video met specifieke resolutie

xivid.bat -i https://nos.nl/collectie/13781/video/2385546-bekijk-de-samenvatting-van-nederland-oostenrijk-2-0
Naam:      NOS: Bekijk de samenvatting van Nederland-Oostenrijk (2-0)
Datum:     17-06-2021 23:06:27
Tijdsduur: 00:05:07
Formaten:  id      formaat         resolutie       bitrate
           dash-0  mpd[manifest]
           hls-0   m3u8[manifest]
           hls-1   m3u8[h264+aac]  640x360@25fps   355|128kbps
           hls-2   m3u8[h264+aac]  960x540@25fps   1170|128kbps
           hls-3   m3u8[h264+aac]  1280x720@25fps  1635|128kbps
           hls-4   m3u8[h264+aac]  848x480@25fps   8413|128kbps (best)

Door een fout van de NOS vermeldt het HLS-manifest dat de 848x480 video een veel te hoge bitrate heeft, waardoor ie onterecht onderaan is komen te staan.

Natuurlijk wil je de 1280x720 video bekijken, maar in dit geval weet je dus pas achteraf dat je -f hls-3 had moeten toevoegen. xidel biedt uitkomst.

FOR /F "delims=" %A IN ('
  xivid.bat -j <programma-url> ^| xidel -se "$json/(formats)()[starts-with(resolution,'1280x720')]/url"
') DO @"C:\Program Files\MPC-HC\mpc-hc.exe" %A

Met een variabele

FOR /F "delims=" %A IN ('
  xivid.bat -j <programma-url> ^| xidel -se "$json/(formats)()[starts-with(resolution,'1280x720')]/url"
') DO @SET url=%A

FOR /F "delims=" %A IN ('
  xivid.bat -j <programma-url> ^| xidel -se "url:=$json/(formats)()[starts-with(resolution,'1280x720')]/url"' --output-format^=cmd
') DO @%A

"C:\Program Files\MPC-HC\mpc-hc.exe" %url%

Video downloaden

Ik raad ffmpeg aan voor het downloaden van audio- en video-urls. Voor dynamische (of adaptive) videostreams (hls-#/dash-#) heb je ffmpeg sowieso nodig, maar ook voor progressieve (of progressive/muxed) videostreams (pg-#) raad ik het aan, omdat sommige smart tv's niet alle gedownloade mp4-bestanden goed af kunnen spelen. Daarnaast kan de bestandsgrootte van mp4-bestanden gedownload met ffmpeg, vanwege 'overhead', tot wel 7% kleiner worden dan wanneer je ze rechtstreeks zou downloaden.

Vanaf eind 2017 wordt Windows XP officieel niet meer ondersteunt door ffmpeg. Een jaar eerder al waren er nog amper mensen die Windows XP binaries beschikbaar stelden. Vanaf voorjaar 2017 ben ik, als Windows XP gebruiker, daarom zelf maar ffmpeg gaan compileren. Mijn binaries zijn gecompileerd met de mbedTLS beveiligingsbibliotheek (volledig geïntegreerd), zijn Windows XP compatible én werken op oude cpu's zonder SSE2 instructies.

Eén video-url

FOR /F "delims=" %A IN ('xivid.bat <programma-url>') DO @ffmpeg -i %A -c copy <bestandsnaam>.mp4

Met een variabele

FOR /F "delims=" %A IN ('xivid.bat -f pg-$ <programma-url>') DO @SET url=%A

FOR /F "delims=" %A IN ('xivid.bat -f pg-$ <programma-url> ^| xidel -se "url:=$raw" --output-format^=cmd') DO @%A

ffmpeg -i %url% -c copy <bestandsnaam>.mp4

HLS-manifest

FOR /F "delims=" %A IN ('xivid.bat -f hls-0 <programma-url>') DO @ffmpeg -i %A
[...]
  Program 4
    Metadata:
      variant_bitrate : 4240692
  Stream #0:0: Audio: aac (LC) ([15][0][0][0] / 0x000F), 48000 Hz, stereo, fltp, 128 kb/s (default)
    Metadata:
      comment         : audioname
  Stream #0:5: Video: h264 (High) ([27][0][0][0] / 0x001B), yuv420p, 1280x720 [SAR 1:1 DAR 16:9], 25 fps, 25 tbr, 90k tbn
    Metadata:
      variant_bitrate : 4240692
[...]

FOR /F "delims=" %A IN ('xivid.bat -f hls-0 <programma-url>') DO @ffmpeg -i %A -map 0:p:4 -c copy <bestandsnaam>.mp4

FOR /F "delims=" %A IN ('xivid.bat -f hls-0 <programma-url>') DO @ffmpeg -i %A -map 0:5 -map 0:0 -c copy <bestandsnaam>.mp4

DASH-manifest

FOR /F "delims=" %A IN ('xivid.bat -f dash-0 <programma-url>') DO @ffmpeg -i %A
[...]
  Program 0
  Stream #0:0: Video: h264 (Constrained Baseline) (avc3 / 0x33637661), yuv420p(tv, bt709), 640x360 [SAR 1:1 DAR 16:9], 324 kb/s, 600 fps, 25 tbr, 600 tbn (default)
    Metadata:
      variant_bitrate : 355156
      id              : video=355156
  Stream #0:1: Video: h264 (Constrained Baseline) (avc3 / 0x33637661), yuv420p(tv, bt709), 960x540 [SAR 1:1 DAR 16:9], 1108 kb/s, 600 fps, 25 tbr, 600 tbn (default)
    Metadata:
      variant_bitrate : 1170001
      id              : video=1170001
  Stream #0:2: Video: h264 (Constrained Baseline) (avc3 / 0x33637661), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 1552 kb/s, 600 fps, 25 tbr, 600 tbn (default)
    Metadata:
      variant_bitrate : 1634927
      id              : video=1634927
  Stream #0:3: Video: h264 (Constrained Baseline) (avc3 / 0x33637661), yuv420p(tv, bt709), 848x480 [SAR 1:1 DAR 53:30], 8231 kb/s, 600 fps, 25 tbr, 600 tbn (default)
    Metadata:
      variant_bitrate : 8412720
      id              : video=8412720
  Stream #0:4: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 127 kb/s (default)
    Metadata:
      variant_bitrate : 128000
      id              : audio=128000

FOR /F "delims=" %A IN ('xivid.bat -f dash-0 <programma-url>') DO @ffmpeg -i %A -map 0:2 -map 0:4 -c copy <bestandsnaam>.mp4

Een video- en audio-url

Met variabelen

FOR /F "delims=" %A IN ('xivid.bat -f hls-$+hls-1 <programma-url>') DO @(
  IF NOT DEFINED url[0] (SET url[0]=%A) ELSE (SET url[1]=%A)
)

FOR /F "delims=" %A IN ('
  xivid.bat -f hls-$+hls-1 <programma-url> ^| xidel -se "url:=x:lines($raw)" --output-format^=cmd
') DO @%A

ffmpeg -i %url[0]% -i %url[1]% -c copy <bestandsnaam>.mp4

Met xidel

FOR /F "delims=" %A IN ('
  xivid.bat -f hls-$+hls-1 <programma-url> ^| xidel -se "let $url:=x:lines($raw) return x'-i {$url[1]} -i {$url[2]}'"
') DO @ffmpeg %A  -c copy <bestandsnaam>.mp4

FOR /F "delims=" %A IN ('
  xivid.bat -j <programma-url> ^| xidel -se "$json/formats/x'-i {.()[starts-with(id,'hls-')][last()]/url} -i {.()[id='hls-1']/url}'"
') DO @ffmpeg %A -c copy <bestandsnaam>.mp4

Een video- en ondertiteling-url

Met variabelen

FOR /F "delims=" %A IN ('xivid.bat -f hls-$+sub-1 <programma-url>') DO @(
  IF NOT DEFINED url[0] (SET url[0]=%A) ELSE (SET url[1]=%A)
)

FOR /F "delims=" %A IN ('
  xivid.bat -f hls-$+sub-1 <programma-url> ^| xidel -se "url:=x:lines($raw)" --output-format^=cmd
') DO @%A

ffmpeg -i %url[0]% -i %url[1]% -c copy -c:s srt -metadata:s:s language=dut <bestandsnaam>.mkv

Met xidel

FOR /F "delims=" %A IN ('
  xivid.bat -f hls-$+sub-1 <programma-url> ^| xidel -se "let $url:=x:lines($raw) return x'-i {$url[1]} -i {$url[2]}'"
') DO @ffmpeg %A -c copy -c:s srt -metadata:s:s language=dut <bestandsnaam>.mkv

FOR /F "delims=" %A IN ('
  xivid.bat -j <programma-url> ^| xidel -se "$json/formats/x'-i {.()[starts-with(id,'hls-')][last()]/url} -i {.()[id='sub-1']/url}'"
') DO @ffmpeg %A -c copy -c:s srt -metadata:s:s language=dut <bestandsnaam>.mkv

Video met specifieke resolutie

FOR /F "delims=" %A IN ('
  xivid.bat -j <programma-url> ^| xidel -se "$json/(formats)()[starts-with(resolution,'1280x720')]/url"
') DO @ffmpeg -i %A -c copy <bestandsnaam>.mp4

Met een variabele

FOR /F "delims=" %A IN ('
  xivid.bat -j <programma-url> ^| xidel -se "$json/(formats)()[starts-with(resolution,'1280x720')]/url"
') DO @SET url=%A

FOR /F "delims=" %A IN ('
  xivid.bat -j <programma-url> ^| xidel -se "url:=$json/(formats)()[starts-with(resolution,'1280x720')]/url"' --output-format^=cmd
') DO @%A

ffmpeg -i %url% -c copy <bestandsnaam>.mp4

Videofragment downloaden

xivid.bat -i https://www.npostart.nl/POMS_NOS_7332477
Naam:      NOS Journaal: STOP! Verkeerslicht voor telefoonverslaafde
Datum:     14-02-2017 13:00:00
Tijdsduur: 00:01:05
Begin:     00:09:02
Einde:     00:10:07
Formaten:  id     formaat         taal  resolutie  bitrate
           sub-1  vtt             nl
           hls-0  m3u8[manifest]
           hls-1  m3u8[aac]                        64kbps
           hls-2  m3u8[aac]                        128kbps
           hls-3  m3u8[h264+aac]        480x270    209|64kbps
           hls-4  m3u8[h264+aac]        640x360    517|128kbps
           hls-5  m3u8[h264+aac]        768x432    721|128kbps
           hls-6  m3u8[h264+aac]        1024x576   1027|128kbps (best)
Download:  ffmpeg -ss 540 -i <url> -ss 2 -t 65 <bestandsnaam>

Dit een voorbeeld van een speciaal soort videofragment. De video-urls (van alle formaten) zijn die van de hele aflevering. Als je dit videofragment op npostart.nl bekijkt, dan krijg je keurig een video van iets langer dan een minuut te zien. Als je 't echter wilt downloaden, dan zul je 't zelf op de juiste momenten uit moeten knippen. De optie -i geeft je in dit geval de ffmpeg commando waarmee je dit kunt doen.

FOR /F "delims=" %A IN ('xivid.bat <programma-url>') DO @ffmpeg -ss 540 -i %A -ss 2 -t 65 -c copy <bestandsnaam>.mp4