Kartina.tv mit IPTV
Inhaltsverzeichnis |
Beschreibung
kartina.tv ist ein kommerzieller IPTV-Anbieter, der etwas über 100 russischsprachige Kanäle inkl. einigen HD- und Radiokanälen anbietet. Der Anbieter offeriert über seine Webseite mehrere unterschiedlich teure Set-Top-Boxen, die vermutlich auch nichts anderes machen als was ich hier beschreibe. Aber wer kauft schon eine Set-Top-Box, wenn er einen VDR hat.
Der automatisierte Zugriff auf das Webinterface erfolgt per REST-API (Representational State Transfer). Die Herausforderung beim Zugriff auf die einzelnen Streams liegt darin, dass die Stream-URLs dynamisch gebildet werden und nur für sehr kurze Zeit gültig sind. Eine statische Konfiguration funktioniert daher nicht; man muss bei jedem Umschaltvorgang einen neuen dynamischen URL holen.
Grundsätzlich funktioniert der Zugriff prima mit dem Iptv-plugin mithilfe des EXT-Protokolls und vlc als externem Player. Folgende Beispielkonfiguration habe ich mit vdr-1.7.15 erstellt. Es gibt im Moment noch einige Instabilitäten (was den WAF-Faktor erheblich senkt); Hinweise und Verbesserungen werden dankend angenommen :-) (Hinweis: Diese Anleitung ist Work in Progress und nicht für "Produktiv" Umgebungen geeignet!)
Software
vdr und Module neu übersetzen.
Funktionen
- 1x pro Tag wird die channel-Liste neu geholt. Vor jedem (Neu-) Start von VDR wird damit eine neue channels.conf gebaut (TODO). (Ich würde mir an der Stelle eine INCLUDE-Funktion in channels.conf wünschen, oder noch besser eine Verlagerung in eine sqlite-DB -- eine statische channels.conf ist einfach nicht mehr zeitgemäß).
- Beim Unschalten auf einen kartina-Kanal wird ein aktueller dynamischer Stream-URL geholt und dann vlc gestartet (basierend auf iptvstream.sh aus dem Iptv-plugin)
- 1x pro Tag werden die EPG-Daten für alle Kanäle geholt, ins epg.data-Format gewandelt und in den VDR geladen (TODO).
Konfiguration
Alle Konfigurationsdateien und Skripte liegen in /etc/vdr/plugins/iptv/kartina.tv/ .
Zunächst benötigen wir eine zentrale Datei, die die Zugangsdaten hält. Sie wird von den anderen Skripten benutzt (hier: nur Demo-Zugang):
Einmal am Tag wird die aktuelle Kanalliste geholt und in einen channels.conf-Abschnitt konvertiert. Das Skript sollte wegen Dateizugriffsrechten unter der gleichen UID laufen wie VDR selbst (root oder vdr):
#!/bin/bash
# Your logon Data
DIR=$(dirname $0)
. $DIR/kartina-login.sh
# Channels.conf
CHANNELS=$DIR/kartinatv-channels.conf
API=http://iptv.kartina.tv/api/xml
# Login
echo Login to iptv.kartina.tv
LOGIN=$(wget -O - -q --save-cookies k.x --keep-session-cookies "$API/login?login=$USER&pass=$PASS")
PACKET_NAME="$(echo "$LOGIN" | grep packet_name | sed 's!\(.*<packet_name>\)\(.*\)\(</packet_name>.*\)!\2!g' )"
if [ -z "$PACKET_NAME" ]; then
echo "login failed"
echo "$LOGIN"
exit 1
fi
echo 'Playlist for Paket:' $PACKET_NAME
# get Channel List
CHANNEL_LIST=$(wget -O - -q --load-cookies k.x --keep-session-cookies "$API/channel_list")
echo "$CHANNEL_LIST" > channel_list.xml
# very poor man's XML parser
echo "$CHANNEL_LIST" | sed 's/<id>/\n/g;' | grep 'stream' | \
sed 's!\([0-9]*\)</id><name>\(.*\)</name>.*<is_video>\(.\)</is_video>.*!\1 \3 \2!g' | \
while read ID VIDEO NAME; do
# wenn Radiokanal: VPID = 0
if [ $VIDEO -eq 0 ] ; then
VPID=0
else
VPID=$(( $ID + 1 ))
fi
APID=$(( $ID + 2 ))
SPID=$(( $ID + 3 ))
echo "$NAME;IPTV:$ID:S=0|P=0|F=EXT|U=iptvstream.sh|A=$ID:I:0:$VPID:$APID:0:0:$ID:0:0:0" >> "$CHANNELS.unsorted"
# jetzt epg für Channel holen
# nur ein Tag? Oder gleich für mehrere?
rm -f "epg/$ID-*"
DAY1=$(date +"%d%m%y")
DAY2=$(date +"%d%m%y" --date="tomorrow")
DAY3=$(date +"%d%m%y" --date="tomorrow + 1 day")
for DAY in $DAY1 $DAY2 $DAY3 ; do
wget -O "$DIR/epg/$ID-$DAY.xml" -q --load-cookies k.x --keep-session-cookies "$API/epg?cid=$ID&day=$DAY"
# epgparse.pl < $DIR/epg/$ID-$DAY.xml > $DIR/epg/$ID-$DAY.epg.data
done
done
# write channels.conf fragment
sort < "$CHANNELS.unsorted" > "$CHANNELS"
rm "$CHANNELS.unsorted"
# log out
LOGOUT=$(wget -O - -q --load-cookies k.x --keep-session-cookies "$API/logout")
chown -R vdr.vdr $DIR
Die erzeugte channels.conf sieht dann so aus (iptv-0.4.2 Format):
МТV Россия;IPTV:39:S=0|P=0|F=EXT|U=iptvstream.sh|A=39:I:0:40:41:0:0:39:0:0:0 РенТВ;IPTV:7:S=0|P=0|F=EXT|U=iptvstream.sh|A=7:I:0:8:9:0:0:7:0:0:0 Россия 24;IPTV:6:S=0|P=0|F=EXT|U=iptvstream.sh|A=6:I:0:7:8:0:0:6:0:0:0 ТНТ;IPTV:8:S=0|P=0|F=EXT|U=iptvstream.sh|A=8:I:0:9:10:0:0:8:0:0:0
/etc/vdr/plugins/iptv/iptvstream.sh ist ein symbolischer Link auf /etc/vdr/plugins/iptv//kartina.tv/kartina-iptvstream.sh:
#!/bin/bash
#
# iptvstream.sh can be used by the VDR iptv plugin to transcode external
# sources
#
# (C) 2007 Rolf Ahrenberg, Antti Seppälä
#
# iptvstream.sh is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This package is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this package; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
# MA 02110-1301, USA.
# adapted for kartina.tv hm@seneca.muc.de
exec 1>>/tmp/t.out
exec 2>>/tmp/t.out
set -x
if [ $# -ne 2 ]; then
logger "$0: error: Invalid parameter count '$#' $*"
exit 1
fi
# Channels.conf parameter
ID=${1}
# Iptv plugin listens this port
PORT=${2}
# Default settings for stream transcoding
VCODEC=mp2v
VBITRATE=2400
ACODEC=mpga
ABITRATE=320
##########################################################################
# retrieve current URL for this channel ID
##########################################################################
# Your logon Data
DIR="$(dirname $0)/kartina.tv"
cd $DIR
. kartina-login.sh
# For VLC set "false", for other players set "true"
FIXSTANDARD=false
API=http://iptv.kartina.tv/api/xml
# Login
LOGIN=$(wget -O - -q --save-cookies k.x --keep-session-cookies "$API/login?login=$USER&pass=$PASS")
# protect_code unconditional?
# URLRAW=$(wget -O - -q --load-cookies k.x --keep-session-cookies "$API/get_url?cid=$ID&protect_code=$PROT_CODE")
URLRAW=$(wget -O - -q --load-cookies k.x --keep-session-cookies "$API/get_url?cid=$ID")
URL="$(echo "$URLRAW" | grep url | sed 's!\(.*<url>\)\(.*\)\(</url>.*\)!\2!g')"
URL="$(echo "$URL" | sed 's/ /%20/g')"
if [ "$FIXSTANDARD" = "true" ]; then
URL="$(echo "$URL" | sed 's!http/ts!http!g')"
fi
# log out
LOGOUT=$(wget -O - -q --load-cookies k.x --keep-session-cookies "$API/logout")
if [ -z "${URL}" ]; then
logger "$0: error: URL not defined!"
exit 1
fi
# Create transcoding options
TRANSCODE_OPTS="vcodec=${VCODEC},acodec=${ACODEC},vb=${VBITRATE},ab=${ABITRATE}"
if [ -n "${WIDTH}" -a -n "${HEIGHT}" ] ; then
TRANSCODE_OPTS="${TRANSCODE_OPTS},width=${WIDTH},height=${HEIGHT}"
fi
# Create unique pids for the stream
VPID=$(( $ID + 1 ))
APID=$(( $ID + 2 ))
SPID=$(( $ID + 3 ))
# kill old vlc processes
killall vlc
# Execute vlc and feed stream into iptv port
exec vlc "${URL}" \
--sout "#transcode{${TRANSCODE_OPTS}}:standard{access=udp,mux=ts{pid-video=${VPID},pid-audio=${APID},pid-spu=${SPID}},dst=127.0.0.1:${PORT}}" \
--intf dummy \
--config $DIR/vlcrc
Bugs / What's missing / TODO
- Im Moment fehlt noch der Zugriff auf das Archiv von kartina.tv (HOWTO willkommen).
- Ton geht nicht bei allen (Demo-) Kanälen. Problem mit APID? HELP!
- Umschaltzeiten sind sehr lang, das liegt mit daran, dass man immer die dyn. URLs holen muss
- EPG-Auswertung
- channels.conf autom. neu bauen
- Bild ruckt alle paar Sekunden, das mag aber daran liegen, dass mein 6 MBit/s DSL zu langsam ist.