<texit info> author=Dick Snippe Dick.Snippe@npo.nl title=Vertaal MIDs naar filesysteem paden keywords=mid poms vod backgroundtext= </texit>
Vertaal MIDs naar filesysteem paden
NEP heeft van DDU een lijst met MIDs (POMS id's) gekregen. De data die daarbij hoort wil men graag naar het NEP platform kopieren. De vraag is: hoe vertaal je een lijst aan MIDs naar filesysteem paden? Dit document beschrijft een methode om dat te doen. Als dat nl gedaan is dat kan gebruik gemaakt worden van een ding genaamd “contentslurp.omroep.nl” dat ik eerder opgezet heb om zo al die data op uniforme wijze binnen te krijgen.
Het idee is om dit als een meertrapsraket aan te pakken:
-
Haal via de POMS api bij elk MID de onderliggende
programUrlop -
Bepaal aan de hand van hoe die url eruit ziet of je nog meer processing moet doen:
-
Kies van het lijstje programUrl's degene die je het beste lijkt (hoogste bitrate, h264 > windosmedia, e.d.)
-
De hoop is dat je uiteindelijk een uniek pad op het filesysteem hebt
Dikke Vette Disclaimer
Langs deze weg wordt content aan NEP ter download aangeboden die anders niet in alle gevallen zomaar downloadbaar is. Voorbeelden hiervan zijn:
-
Er zou potentieel POMS content tussen kunnen zitten die in POMS gemarkeerd staat als zijnde “REVOKED”
-
Er zit content tussen die in het NPO download platform over zgn hotlink bescherming beschikt
Experimenten POMS api
Api downloaden en uitproberen
Ik gebruik jq om JSON te processn, da's gewoon een rpm.
$ sudo dnf install -y jq $ git clone https://github.com/npo-poms/api $ cd api/bash $ cp creds-example.sh creds.sh $ vi creds.sh [via Cris heb ik creds voor NEP gekregen] apiKey=nepmigratie secret=___________________________ origin=http://dicktest.nepworldwide.nl
Stoeien met jq om nuttige info te verkrijgen
$ ./media/get.sh POW_00722648|jq
Access-Control-Allow-Headers: accept, authorization, content-type, cookie, origin, x-http-method-override, x-requested-with, x-npo-date, x-npo-mid, x-npo-url, 200, api/media/POW_00722648? @uster=balancer.poms8aas; path=/;, PUT
{
"objectType": "program",
"mid": "POW_00722648",
"type": "BROADCAST",
"avType": "VIDEO",
"workflow": "PUBLISHED",
"sortDate": 1389546000000,
"creationDate": 1387432091934,
"lastModified": 1389792202585,
enz...
$ ./media/get.sh RBX_RA4_4628952| jq '.locations[]|.programUrl' "http://radiobox2.omroep.nl/broadcaststream/file/478896.mp3"
Maar eigenlijk wil ik in 1 klap een lijst aan MIDs kunnen geven.
$ . ./api-functions.sh get api/media/multiple ids=POW_00470026,POW_00135450|jq
Hoe krijgen we daar de gewenste info uit?
$ get api/media/multiple ids=POW_00470026,POW_00135450|jq '.items[]|.id,(.result|.locations[]|.programUrl)' "POW_00470026" "odi+http://odi.omroep.nl/video/h264_sb/POW_00470026" "odi+http://odi.omroep.nl/video/h264_bb/POW_00470026" "odi+http://odi.omroep.nl/video/h264_std/POW_00470026" "odi+http://odi.omroep.nl/video/wvc1_std/POW_00470026" "odi+http://odi.omroep.nl/video/wmv_sb/POW_00470026" "odi+http://odi.omroep.nl/video/wmv_bb/POW_00470026" "POW_00135450" "http://content.omroep.nl/id/MAX/serie/POW_00135444/POW_00135450/bb.20070921.mp4" "http://cgi.omroep.nl/cgi-bin/streams?/id/MAX/serie/POW_00135444/POW_00135450/sb.20070921.asf" "http://cgi.omroep.nl/cgi-bin/streams?/id/MAX/serie/POW_00135444/POW_00135450/bb.20070921.asf"
Met nog een pietsie meer jq-fu zou hier een handig lijstje uit moeten kunnen komen, zou je zeggen.
$ get api/media/multiple ids=POW_00470026,POW_00135450|jq '.items[]|{ id: .id, urls: [ .result|.locations[]|.programUrl ]}'
{
"id": "POW_00470026",
"urls": [
"odi+http://odi.omroep.nl/video/h264_sb/POW_00470026",
"odi+http://odi.omroep.nl/video/h264_bb/POW_00470026",
"odi+http://odi.omroep.nl/video/h264_std/POW_00470026",
"odi+http://odi.omroep.nl/video/wvc1_std/POW_00470026",
"odi+http://odi.omroep.nl/video/wmv_sb/POW_00470026",
"odi+http://odi.omroep.nl/video/wmv_bb/POW_00470026"
]
}
{
"id": "POW_00135450",
"urls": [
"http://content.omroep.nl/id/MAX/serie/POW_00135444/POW_00135450/bb.20070921.mp4",
"http://cgi.omroep.nl/cgi-bin/streams?/id/MAX/serie/POW_00135444/POW_00135450/sb.20070921.asf",
"http://cgi.omroep.nl/cgi-bin/streams?/id/MAX/serie/POW_00135444/POW_00135450/bb.20070921.asf"
]
}
Data cleanup
Ik heb van Jantine 10 files gekregen:
VOD cleanup AVROTROS.txt VOD cleanup BNNVARA.txt VOD cleanup EO.txt VOD cleanup HUMAN.txt VOD cleanup KRO-NCRV.txt VOD cleanup MAX.txt VOD cleanup NOS events.txt VOD cleanup POWNED.txt VOD cleanup VPRO.txt VOD cleanup WNL.txt
maar daar zit nog wat rommel in (lege regels, tekstkopjes) Als volgt gecleaned:
$ cat clean.sed /^[[:blank:]]*$/d / /d /POMS-iD/d /Titel/d $ cat *.txt | wc -l 80260 $ sort *.txt | sed -f clean.sed > mids $ wc -l mids 79893 mids
Wat is dan de rommel die niet meegenomen is?
$ grep -c '^[[:blank:]]*$' *.txt VOD cleanup AVROTROS.txt:297 VOD cleanup BNNVARA.txt:0 VOD cleanup EO.txt:0 VOD cleanup HUMAN.txt:0 VOD cleanup KRO-NCRV.txt:0 VOD cleanup MAX.txt:42 VOD cleanup NOS events.txt:8 VOD cleanup POWNED.txt:0 VOD cleanup VPRO.txt:1 VOD cleanup WNL.txt:8 $ grep '[[:blank:]]' *.txt VOD cleanup AVROTROS.txt:AVRO KunstUur VOD cleanup HUMAN.txt:HUMAN_20050812 vloer VOD cleanup HUMAN.txt:HUMAN_20050826 vloer VOD cleanup HUMAN.txt:HUMAN_20050819 vloer VOD cleanup WNL.txt:De Koning Willem 1 Prijzen POMS_S_WNL_132698 VOD cleanup WNL.txt:Vrijdag met Vrienden POMS_S_WNL_133221 VOD cleanup WNL.txt: VOD cleanup WNL.txt: VOD cleanup WNL.txt: VOD cleanup WNL.txt: VOD cleanup WNL.txt:Wedstrijd van zijn leven POMS_S_WNL_387871 VOD cleanup WNL.txt:WNL Op Zondag POW_03347301 $ grep -E '(POMS-iD|Titel)' *.txt VOD cleanup AVROTROS.txt:POMS-iD'S VOD cleanup HUMAN.txt:Titel VOD cleanup VPRO.txt:POMS-iD
Verder blijken er een hoop duplicaten in te zitten:
$ uniq -d mids|wc -l 1624
Laten we die er nog maar even uitvissen
$ uniq mids >mids.tmp $ mv mids.tmp mids $ wc -l mids 79893 mids
Massaal MIDs opvragen
We hebben nu dus een lijst genaamd “mids”. Knip deze in chunks van -zeg- 100 items en vraag die op via api/media/multiple
### dit is mijn workspace waar mijn lijstje mids staat
### en waar ik de rest v/d processing ga doen
$ cd tmp/mid
$ split -l 100 -a 3 -d mids mids.
$ mkdir in
$ mv mids* in
### In ../api staat de git checkout
$ . ../api/bash/api-functions.sh
### ff proberen
$ head -1 in/mids.000
10act0505Canadezen
$ get api/media/multiple ids=10act0505Canadezen | jq
<ziet er goed uit>
$ mkdir out
$ for x in in/mids.???; do echo Doing $x; out=out/${x#in/}; get api/media/multiple ids=$(tr '\n' ',' <$x ) >$out; done
Transmogrificeren
We hebben nu een hele bak met info. Maak daar met jq iets van waar een bash of perl scriptje wat mee zou kunnen. (waarom? Omdat ik in bash beter thuis ben dan in jq. Sorry. Iets met nails en hammers. Hele oude hammers in dit geval.)
$ jq '.items[]|{ id: .id, urls: [ .result|.locations[]|.programUrl ]}' out/mids.??? >data
jq: error (at out/mids.000:0): Cannot iterate over null (null)
...
jq: error (at out/mids.785:0): Cannot iterate over null (null)
De “cannot iterate” errors komen van MIDs die blijkbaar geen programs zijn en geen “.locations.programUrl” hebben. Lekker gecleaned, die data he?
Wat hebben we eigenlijk voor spulletjes er tussen zitten?
$ jq '.items[]|{ id: .id, type: .result.objectType }' out/mids.???|grep type|sort -u
"type": "group"
"type": null
"type": "program"
"type": "segment"
Non-program mids
Hierboven hebben we “type: null”. Dat komt van niet bestaande mids. Verder hebben we een type “segment”. Dat kan zo te zien wel gebruikt worden. Daar hangen ook locations aan. Daarnaast hebben we dus ook mids van type “group”. Daar hebben we allemaal niets aan, omdat daar geen files aan hangen. Deze willen we er dus uitfilteren en we willen dit flaggen als foutieve input. Jq wederom to the rescue:
$ jq -c '.items[]| select(.result.objectType != "program" and .result.objectType != "segment")|{ id: .id, type: .result.objectType }' out/mids.??? >bad-type
$ wc -l bad-type
1480 bad-type
Programs zonder locations
Er blijken mids van type program of segment te zijn waar geen locations aan gelinked zijn. Daar kunnen we ook niets mee. Dus weg dermee
$ jq -c '.items[]| select(.result.objectType == "program" or .result.objectType == "segment")|select(.result|.locations |length == 0)|{ id: .id, locations: .result|.locations |length }' out/mids.??? > no-locations
$ wc -l no-locations
7206 no-locations
Beste bitrate
Een ID kan meerdere locations hebben (1:n relatie). Daarvan willen we graag degene met de
hoogste bitrate kiezen. Dat kan wederom in jq met max_by:
$ jq -c '.items[]| select(.result.objectType == "program" or .result.objectType == "segment")|select(.result|.locations |length > 0)|{ id: .id, url: .result.locations|max_by(.avAttributes.bitrate).programUrl }' out/mids.???
Maar, (zie even verderop) hiermee selecteren we veel sub+http content en dat wil ik niet, want daar heb ik de bestanden helemaal niet van. Dus die willen we uitfilteren. Dit zou er dan zo uit kunnen zien:
$ jq -c '.items[]| select(.result.objectType == "program" or .result.objectType == "segment")|select(.result|.locations |length > 0)|{ id: .id, url: .result.locations |[ .[]|select(.programUrl|contains("sub+http")|not) ]|max_by(.avAttributes.bitrate).programUrl }' out/mids.???
Verder blijkt dat er sinds kort ook
npo://internetvod.omroep.nl/<ID>
style urls in POMs zitten (ik denk om NEP content mee aan te geven). Daar kan ik ook niets mee dus die moeten er ook uitgefilted worden.
Disclaimer: een jq guru kan dit vast beter. Dit is alleen maar wat
ik zo snel bij elkaar gecobbled kon krijgen en werkt.
Een probleem wel in deze setup is dat als er nu mids zijn waar
uitsluitend sub+http locations aanhangen dan zegt de eerste test
dat er wel locations zijn, maar de 2e gooit ze vervolgens allemaal weg.
Verderop werken we daar omheen door null expliciet als location te
herkennen en het mid als poms id te interpreteren. Dat werkt.
Uiteindelijke filter
In het kader van leesbaarheid stoppen we de filter expressie maar in een losse file, dan kan het een beetje geformatteerd worden:
$ cat filter.jq
.items[]|
select(.result.objectType == "program" or .result.objectType == "segment")|
select(.result|.locations | length > 0)|
{
id: .id,
url: .result.locations |
[
.[]|
select(.avAttributes.avFileFormat == "MP4" or
.avAttributes.avFileFormat == "MP3" or
.avAttributes.avFileFormat == "H264" or
.avAttributes.avFileFormat == "M4V" )|
select(.programUrl|contains("sub+http")|not)|
select(.programUrl|contains("npo://")|not) |
select(.programUrl|contains("npo+drm://")|not)
]|
max_by(.avAttributes.bitrate).programUrl,
}
$ jq -c -f filter.jq out/mids.??? >data
$ wc -l data
71207 data
$ head -3 data
{"id":"10act0505Canadezen","url":"odi+http://odi.omroep.nl/video/wmv_bb/10act0505Canadezen"}
{"id":"10act1002CDA","url":"odi+http://odi.omroep.nl/video/wvc1_std/10act1002CDA"}
{"id":"11act0206Pieter","url":"odi+http://odi.omroep.nl/video/wvc1_std/11act0206Pieter"}
Kiezen location
Wat voor types locaties hebben we eigenlijk? (onderstaand is gedraaid op de data voordat daar de sub+http urls uitgehaald waren. Op de uiteindelijke data is de verhouding iets anders omdat in die gevallen bijna allemaal odi+http urls geselecteerd zijn)
$ jq . data | grep /|sed 's#\(//[^/?]*\).*#\1#' |sort|uniq -c|sort -n
1 "url": "http://content.omrep.nl
1 "url": "http://download
1 "url": "http://flashserver.rtvdrenthe.nl
1 "url": "http://radiobox.omroep.nl
1 "url": "http://weblogs.vpro.nl
1 "url": "http://www.publiekeomroep.nl
1 "url": "mp3://moby.vpro.nl
1 "url": "odiw+http://odi.omroep.nl
1 "url": "rtsp://halo.triple-it.nl:554
1 "url": "rtsp://streaming.xwits.nl
2 "url": "file://rtmpe:
2 "url": "ftp://upload-extern.omroep.nl
2 "url": "http://content1c.omroep.nl
2 "url": "http://files.vpro.nl
3 "url": "http://content1b.omroep.nl
3 "url": "http://content1d.omroep.nl
3 "url": "http://www.youtube.com
4 "url": "odiw+http://livestreams.omroep.nl
5 "url": "http://video.omroep.nl
6 "url": "ftp://powned02@upload-extern.omroep.nl
12 "url": "http://content1a.omroep.nl
18 "url": "odip+http://odi.omroep.nl
18 "url": "rtsp://halo.triple-it.nl
49 "url": "http://download.eo.nl
78 "url": "http://player.omroep.nl
756 "url": "sub+http://npoplus.nl
2232 "url": "sub+http://tvvod.omroep.nl
2391 "url": "sub+http://npo.npoplus.nl
3224 "url": "odis+http://content.omroep.nl
5498 "url": "http://radiobox2.omroep.nl
7577 "url": "http://download.omroep.nl
8571 "url": "http://content.omroep.nl
11476 "url": "http://cgi.omroep.nl
29428 "url": "odi+http://odi.omroep.nl
Je ziet dat hier wat rommel in zit. Typo's, mensen die het niet begrepen hebben enzo. De bovenste helft van het lijstje laat ik voor wat het is. De onderste helft moeten we eens beter bestuderen:
sub+http integratie
Er zijn een paar duizend urls van de vorm “sub+http”. Deze wijzen naar npoplus en tvvod
Wat is de structuur van deze links?
$ grep sub+http data |sed -e 's#.*sub+http://##' -e 's#/[^/]*$##'|sort |uniq -c|sort -n
12 npoplus.nl/video/h264_hr
61 tvvod.omroep.nl/video/MPEG2_3500
333 npoplus.nl/video/mpeg2_plus
411 npoplus.nl/video/mpeg2_hr
1071 npo.npoplus.nl/video/mpeg2_plus
1320 npo.npoplus.nl/video/MXF
2171 tvvod.omroep.nl/video/mpeg2_hr
In de grote-boze jq query hierboven zijn deze versies -denk ik- gekozen omdat ze de hoogste bitrates hadden. Maar nu is dat eigenlijk niet handig. De urls hebben allemaal een PRID in zich, dus we kunnen (zie hieronder) bij ODI te raad gaan of die iets voor ons heeft. Maar eigenlijk is het misschien slimmer om deze maar gewoon niet mee te nemen en ze in jq bij voorbaat uit te sluiten.
In de tussentijd nog weer wat jq bijgeleerd. Beschouw deze json file:
[
{ "foo": "bar", "bar": "meh" },
{ "foo": "blup", "bar": "whatever" },
{ "foo": "wibble", "bar": "wop" }
]
Stel nu dat ik de entries waar key “foo” de substring “blu” heeft niet wil. Hoe regelen we dat?
$ jq '.[]|select(.foo|contains("blu")|not)' test.json
{
"foo": "bar",
"bar": "meh"
}
{
"foo": "wibble",
"bar": "wop"
}
(mooie mentale hersengymnastiek vind ik die jq pipes trouwens, vooral zo'n
|not.)
Bovenstaande constructie gebruiken we om de sub+http zaken weg te filteren.
Dat is deze regel in het uiteindelijke jq filter:
[ .[]|select(.programUrl|contains("sub+http")|not) ]|
radiobox integratie integratie
Alle radiobox links verwijzen uiteindelijk naar het download platform. We kunnen alle radiobox urls aan radiobox voeren. Die levert je dan wel een 302 naar de download link. Voorbeeld:
$ curl -D - http://radiobox2.omroep.nl/videofragment/file/5843/fragment.mp4 HTTP/1.1 302 Found Date: Tue, 11 Apr 2017 12:33:29 GMT Server: Apache/2.4.23 (Unix) PHP/5.3.29 X-Powered-By: PHP/5.3.29 Location: http://download.omroep.nl/portal/radiomanager/video_archive/radio6/2013/06/03/340-hegezelligoverdevloerdeel1.mp4 [en nog wat meer headers]
Hier zie je meteen al dat je zonder de radiobox database nooit zelf die mapping (/videofragment/file/5843/fragment.mp4 → /portal/radiomanager/video_archive/radio6/2013/06/03/340-hegezelligoverdevloerdeel1.mp4) gaat kunnen maken.
Dus hier rest ons niets anders dan alle radiobox urls bij radiobox te resolven. Ik vind het handig om dit even vantevoren te doen, zodat het uiteindelijke script alleen een lookup hoef te doen in de data die we in deze fase genereren. Daar heb ik het volgende scriptje voor geschreven:
$ cat rbx_resolve
PATH=/usr/bin:/bin
hdrs=$(mktemp -t rbx_resolve.XXXXXX)
while IFS=, read id url; do
url=${url#\"url\":\"}; url=${url%\"\}}
id=${id#\{\"id\":\"}; id=${id%\"}
curl -s --fail -D $hdrs --output /dev/null "$url" &&
awk -v id="$id" '/^Location/ { print id,$2; }' $hdrs
done
rm -f $hdrs
En als volgt gedraaid:
$ grep radiobox2 data | ./rbx_resolve >rbx_map
Omdat het maar een heel dom scriptje is dat niets paralelliseert duurt het even; reken een minuut of 5 om alle radiobox urls te resolven.
En dan komt daar een lijstje uit dat er zo uit ziet:
$ head -3 rbx_map POMS_AT_1012052 http://download.omroep.nl/portal/radiomanager/rm3-radio1/audiofragments/21/20648-Reportage_deel_twee.mp3 POMS_AT_1012053 http://download.omroep.nl/portal/radiomanager/rm3-radio1/audiofragments/21/20993-Brein_in_de_rechtszaal.mp3 POMS_AT_1012054 http://download.omroep.nl/portal/radiomanager/rm3-radio1/audiofragments/22/21174-Kloosterleven.mp3
Deze data gaat verderop in het uiteindelijke glue scriptje weer gebruikt worden.
download, content en cgi integratie
Het download platform is onder een aantal namen bekend, die allemaal synoniemen voor elkaar zijn:
-
download.omroep.nl
-
content.omroep.nl
-
download.eo.nl
-
video.omroep.nl
Deze wijzen gewoon naar ons download platform. Daarnaast hebben (hadden) we het zgn “streams script”. Dit verwijst naar het streaming platform. Urls zien er zoiets uit:
http://cgi.omroep.nl/cgi-bin/streams?/vpro/39488696/windowsmedia.asf?title=Charles Frail sessie Motel Mozaique 12-04-2008&author=Charles Frail"
(ja, je ziet het goed, slimmerds die 2x ? in een url zetten…)
Dit kunnen we redelijk makkelijk masseren naar een downloadable locatie,
door contentslurp.omroep.nl ook bv een /media sectie te geven die naar
de streaming docroot (/e/ap/media) wijst.
ODI Integratie
Voor alle odi-style URLs hebben we de informatie uit ODI nodig om te bedenken welk bestand er gekopieerd moet gaan worden. In ODI heb je meerdere zgn “publicatie opties”, en die heb je weer nodig om het uiteindelijke pad af te kunnen leiden. Ik kies er maar voor om de informatie direct uit de odi database te trekken:
$ ssh tab-as68 $ mysql --host=10.15.4.18 --user=odi --password='**************' odi_db MariaDB [odi_db]> select * from puboption; +----+--------------+-----------+--------------+----------------+---------------------+ | id | puboption_id | puboption | family | prefix | updated | +----+--------------+-----------+--------------+----------------+---------------------+ | 1 | 1 | wmv_bb | windowsmedia | /ceres | 2015-02-02 15:27:13 | | 2 | 2 | wmv_sb | windowsmedia | /ceres | 2015-02-02 15:27:13 | | 3 | 10 | wvc1_std | windowsmedia | /ceres | 2015-02-02 15:27:13 | | 4 | 4 | h264_bb | download | /ceresodi/h264 | 2015-02-04 10:14:54 | | 5 | 5 | h264_sb | download | /ceresodi/h264 | 2015-02-04 10:14:54 | | 6 | 9 | h264_std | download | /ceresodi/h264 | 2015-02-04 10:14:54 | | 7 | 12 | adaptive | adaptive | | 2015-02-04 10:14:54 | +----+--------------+-----------+--------------+----------------+---------------------+ 7 rows in set (0.01 sec)
Voorbeeldje voor windowsmedia:
MariaDB [odi_db]> select episode_prid,location from episode_puboption where puboption_id=10 limit 3; +--------------+-------------------------------------------------------+ | episode_prid | location | +--------------+-------------------------------------------------------+ | AVRO_1353288 | /ceres/1/avro/rest/2010/AVRO_1353288/std.20100810.wmv | | AVRO_1367472 | /ceres/1/avro/rest/2010/AVRO_1367472/std.20100810.wmv | | AVRO_1378275 | /ceres/1/avro/rest/2010/AVRO_1378275/std.20100810.wmv | +--------------+-------------------------------------------------------+ 3 rows in set (0.00 sec)
Da's mooi. Dat betekent dat we ODI redelijk makkelijk leeg kunnen trekken. (onderstaand er van uitgaande dat er een .my.cnf met valide credentials staat)
$ mysql -B --skip-column-names -e 'select b.puboption,a.episode_prid,a.location from episode_puboption as a, puboption as b where a.puboption_id = b.puboption_id' odi_db | gzip -c >odi_map.gz $ zcat odi_map.gz |wc -l 956707 $ zcat odi_map.gz |head -3 h264_bb AVRO_1353288 /ceres/1/avro/rest/2010/AVRO_1353288/bb.20100810.m4v h264_sb AVRO_1353288 /ceres/1/avro/rest/2010/AVRO_1353288/sb.20100810.m4v h264_std AVRO_1353288 /ceres/1/avro/rest/2010/AVRO_1353288/std.20100810.m4v
De volgende vraag is nu: hoe bepaal ik de ODI publicatie optie aan de hand van een odi url? Ik zie de volgende ODI style urls terugkomen:
$ grep ':"odi[a-z]*\+' data |sed -e 's#://.*##' -e 's#^.*:"##'|sort|uniq -c
29428 odi+http
18 odip+http
3224 odis+http
5 odiw+http
Reverse engineerend denk ik dat dit de volgende betekenissen heeft:
| type | betekenis |
|---|---|
| odi | regulier, zoals ik ken, odi, puboption valt uit uri te herleiden. Alle odi+http urls verwijzen altijd naar odi.omroep.nl |
| odip | zo te zien voor adaptive dingen |
| odis | Wordt gebruikt voor protected content, voorbeeld odis+http://content.omroep.nl/vpro/protected/luisterpaal/video/2012/06/12/AngusStone3sngs.mp4. Grappig genoeg hoef ik dat niet aan odi te vragen en kan dit gewoon als download url behandeld worden |
| odiw | Dit zijn livestreams. Deze kunnen genegeerd worden |
Hoe zien odi+http uri's eruit?
$ grep odi+http data |sed -e 's#.*odi.omroep.nl/##' -e 's#/[^/]*$##'|sort|uniq -c
24 video/h264_bb
44 video/h264_sb
5913 video/h264_std
6427 video/wmv_bb
1 video/wmv_sb
17019 video/wvc1_std
En dit mapped natuurlijk perfect op de puboptions van odi.
Glue alles aan elkaar
Alle onderdelen hebben we nu:
-
Een file genaamd “data” met daarin een mapping
mid → urlzoals die in POMS staat -
Een file “rbx_map” met daarin een mapping
odi url → download urlvoor radiobox style urls -
Een file “odi_map” met daarin een mapping
PRID + puboption → location
Gewapend met bovenstaande maps kunnen we een scriptje schrijven dat de vertaling van de diverse smaken odi urls doet.
Ik heb een perl (sorry…) scriptje geschreven om dit allemaal aan
elkaar te lijmen.
Dit levert een lijst met mappings mid → uri, waarbij alle uri's aan contentslurp.omroep.nl te voeren zijn.
Dingen waar het script niets mee kon komen terecht in z'n errorlog.
Redenen hiervoor kunnnen zijn:
-
“unknown ODI prid/pubopt”: ODI kende deze prid/publicatie optie combinatie niet
-
“no ODI match found”: Urls van de stijl
sub+httpkunnen we niet resolven. Maar er zit wel een PRID in de url dat aan odi gevoerd kan worden om alsnog tot content te komen. Deze error krijg je bij PRID's die ODI niet kent. -
“cannot handle <url>”: Het script kon niets met deze url. Dit speelt vooral voor urls van de stijl
http://player.omroep.nl/?aflID=…. player.omroep.nl bestaat niet (meer) en ik weet niet hoe deze aflevering id's nog te herleiden zijn. -
“http://radiobox2.omroep.nl/… does not resolve”. In POMS zat blijkbaar een url naar radiobox, welke bij radiobox niet bekend was (en aldaar een 404 geeft)
$ ./dataglue.pl data >contentslurp_map 2>err
$ wc -l contentslurp_map err
71041 contentslurp_map
166 err
71207 total
Tot slot nog een paar opmerkingen:
-
Dat poms zegt dat een link bestaat hoeft nog niet te betekenen dat dat ook werkelijk waar is. Het kan zomaar zijn dat een omroep deze content op het downloadplatform heef tverwijderd en dat niet in poms heeft bijgewerkt oid.
-
adaptive links zijn links naar een directory. Daarvoor wil je alle bestanden in de directory downloaden (.ism en -meestal- 4 .ismv bestanden)
-
Naast h264 en adaptive is er ook windowsmedia en mp3 content.
-
En daarnaast is er ook nog andere random cruft die omroepen erin gestopt hebben. Ik zie een jpg bestand, maar bijvoorbeeld ook realmedia, flash video, mp2, mov…
-
De URL encoding in poms is niet bepaald consistent. Je kan dus urls met 'foo bar' tegenkomen, maar ook met 'foo%20bar' of 'foo+bar'. Hou daar rekening mee als je zelf nette url encoding wilt doen.
Nabrander Vragen
Nadat ik bovenstaand stukje geschreven had, heb ik nog minimaal 5x een verzoek vanuit Online gekregen om dit script nog een keer te runnen met een andere set aan mids. Bij de nmiddels voor-voor-voor-voor laatste keer mondde dat uit in deze mailconversatie:
Date: Mon, 25 Sep 2017 13:18:11 +0000
From: Dennis Verhoeven Dennis.Verhoeven@npo.nl
To: Dick Snippe Dick.Snippe@NPO.nl
CC: Nick Ceton Nick.Ceton@npo.nl, Egon Verharen Egon.Verharen@NPO.nl
Subject: RE: Migratielijst v NEP
Hoi Dick,
Dank voor de snelle en gedetailleerde reactie. Ik heb een vraag over de items
+waarvan jij aangeeft dat ze niet in POMS zitten, de items uit deze lijsten
+komen namelijk allemaal uit POMS. Kan het zijn dat ik iets over het hoofd zie?
+Het gaat gelukkig om een klein aantal, maar ben toch even benieuwd te weten
+waar dit zit.
Groet,
Dennis.
—–Oorspronkelijk bericht—–
Van: Dick Snippe [mailto:Dick.Snippe@npo.nl]
Verzonden: maandag 25 september 2017 14:58
Aan: Dennis Verhoeven Dennis.Verhoeven@npo.nl
CC: Nick Ceton Nick.Ceton@npo.nl; Egon Verharen Egon.Verharen@NPO.nl
Onderwerp: Re: Migratielijst v NEP
On Mon, Sep 25, 2017 at 11:45:47AM +0000, Dennis Verhoeven wrote:
> Het heeft wat langer geduurd, maar dit is de uiteindelijke lijst met items die
+volgens diverse criteria nog gemigreerd moeten worden. De CSV is in principe
+een tekstfile met maar 1 PRID per regel. Zou jij deze zoals we dat eerder
+besproken/gevraagd hebben kunnen omzetten naar een lijst met locaties opdat NEP
+deze kan migreren?
Zeker. Jij hebt mij een lijst aangeleverd met 122671 items.
Daar zaten wel duplicaten in; ik (nouja, mijn computer) telde 117646 unieke
+ID's. Na het wegfilteren van syntactisch incorrecte MIDs (met spaties erin
+enzo) bleven er nog 117639 over.
Daarvan kwam weer niet alles in POMS voor. Er werden 117489 items gevonden in
+POMS. Die kon ik uiteindelijk door mijn scriptje halen.
Daarvan konden er 117065 geresolved worden en 424 daar was wat mee.
Dat is wel een goede vraag. Maar hoe gaan we daar achter komen?
Om te beginnen wil ik weten welke MIDs dat zijn:
$ sort in/mids.* >mids.in $ wc -l mids.in 117639 mids.in ###Die hebben ook allemaal een POMS id: ###$ jq '.items[].id' out/mids.??? | tr -d '"' | sort >mids.poms ###$ wc -l mids.poms ###117639 mids.poms $ jq '.id' data|tr -d '"' | sort >mids.found $ wc -l mids.found 117489 mids.found $ comm -23 mids.in mids.found >mids.notfound $ get api/media/multiple ids=$(tr '\n' ',' <mids.notfound ) > data.notfound
Vervolgens kunnen we die data.notfound nog eens wat nader
bestuderen.