Media-Streaming mit der Playstation 3 und Mediatomb

Über Mediatomb

Mediatomb ist ein freier UPnP-Server, der verschiedenste Inhalte an UPnP-Clients streamen kann. Mediatomb wurde so entwickelt, dass er sich ohne Probleme um diverse Funktionen erweitern lässt.

Zur Playstation 3

Die Playstation 3 ist schon lange mehr als eine Spielekonsole oder ein Blu Ray Player. Sony hat schon vor längerer Zeit ein Update nachgeschoben, welches das Gerät auch zu einem UPnP-Client macht, jedoch zu einem sehr zickigen!

Ich habe sehr lange kämpfen müssen, um mit der PS3 auf Mediatomb zugreifen zu können, zumal die PS3 auch nur einen sehr beschränkten Medien Codec besitzt. So ist es zum Beispiel nicht möglich, MKV-Dateien abzuspielen. Da sich Mediatomb aber erweitern lässt, lassen sich Scripte einsetzen, die ein On-the-fly Transcoding ermöglichen. Dazu aber später mehr an der passenden Stelle.

Mediatomb Setup

Eines kurz vorweg: Zu Hause nutze ich das Netzwerk 172.16.2.0/24. Entsprechende Angaben müssen für eure Bedürfnisse angepasst werden!

Auf die Installation von Mediatomb möchte ich nicht eingehen, dass ist nun wirklich mehr als einfach. Gerade, wie bei mir, unter Debian, worauf auch dieses HowTo basiert.

Wie fast jeder Daemon unter Debian, hat auch Mediatomb eine Default-Datei: /etc/default/mediatomb

mediatomb
# Defaults for MediaTomb initscript
# sourced by /etc/init.d/mediatomb
# installed at /etc/default/mediatomb by the maintainer scripts
 
#
# This is a POSIX shell fragment
#
 
# Set whether the daemon should be started. Set this value to anything
# but 'yes' to enable the daemon
### Kommentar Daniel:
# Auf "no" setzen, damit mediatomb überhaupt startet!
NO_START="no"
 
# Additional options that are passed to the daemon.
### Kommentar Daniel:
# Hier wird die IP und der Port angegeben, auf dem sich mediatomb binden soll.
# Bei der PS3 habe ich mitbekommen, dass das Binden auf eine IP und einen Port
# die zuverlässigste Variante ist. Das Binden auf ein Interface schlug hingegen
# oft/mehrmals/fast immer fehl.
# WICHTIG: Auch das Kommentar bei INTERFACE lesen!
OPTIONS="--ip 172.16.2.252 --port 50800"
 
# The network interface for MediaTomb to bind to and for which the multicast
# routing entry should be added; "" if the route shouldn't be added at all.
# For example: INTERFACE="eth0"
### Kommentar Daniel:
# INTERFACE muss leer bleiben, wenn in OPTIONS IP und Port spezifiziert wurden!
INTERFACE=""
 
# The route command and arguments to be used if INTERFACE is defined.
# These variables should normally be left unmodified.
### Kommentar Daniel:
# Interessiert nicht weiter, da wir uns nicht auf ein Interface binden.
ROUTE_ADD="/sbin/route add -net 239.0.0.0 netmask 255.0.0.0"
ROUTE_DEL="/sbin/route del -net 239.0.0.0 netmask 255.0.0.0"
 
# The user and group that MediaTomb should be run as.
USER="mediatomb"
GROUP="mediatomb"

Anschließend folgt die Konfigurations-Datei von Mediatomb, zu finden unter /etc/mediatomb/:

config.xml
<?xml version="1.0" encoding="UTF-8"?>
<config version="1" xmlns="http://mediatomb.cc/config/1" 
                    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
                    xsi:schemaLocation="http://mediatomb.cc/config/1 http://mediatomb.cc/config/1.xsd">
  <server>
    <ui enabled="yes" show-tooltips="yes">
      <accounts enabled="yes" session-timeout="30">
        <!-- Kommentar Daniel: Nutzer fuer Webinterface anpassen! -->
        <account user="username" password="password"/>
      </accounts>
    </ui>
    <!-- Kommentar Daniel: Namen fuer UPnP Device vergeben -->
    <name>diskette</name>
    <!-- Kommentar Daniel: UUID setzen, Generierung kann z.B. mit uuidgen geschehen -->
    <udn>uuid:aa6d74dd-47b7-4e8f-a553-2c498e376951</udn>
    <home>/var/lib/mediatomb</home>
    <webroot>/usr/share/mediatomb/web</webroot>
    <!-- Kommentar Daniel: Storage Backend konfigurieren, fuer meine Belange reicht sqlite3 -->
    <storage caching="yes">
      <sqlite3 enabled="yes">
        <database-file>mediatomb.db</database-file>
      </sqlite3>
      <mysql enabled="no">
        <host>localhost</host>
        <username>mediatomb</username>
        <database>mediatomb</database>
      </mysql>
    </storage>
    <!-- Kommentar Daniel: Wichtige Option fuer die PS3, damit zusaetzliche Informationen mitgeschickt werden und die MP3 und MPEG4 Wiedergabe funktioniert -->
    <protocolInfo extend="yes"/>
    <extended-runtime-options>
      <!-- Kommentar Daniel: Anzeige von Vorschaubildchen konfigurieren -->
      <ffmpegthumbnailer enabled="yes">
        <thumbnail-size>160</thumbnail-size>
        <seek-percentage>25</seek-percentage>
        <filmstrip-overlay>yes</filmstrip-overlay>
        <image-quality>100</image-quality>
        <workaround-bugs>no</workaround-bugs>
      </ffmpegthumbnailer>
      <mark-played-items enabled="no" suppress-cds-updates="yes">
        <string mode="prepend">*</string>
      </mark-played-items>
    </extended-runtime-options>
  </server>
  <import hidden-files="no">
    <scripting script-charset="UTF-8">
      <common-script>/usr/share/mediatomb/js/common.js</common-script>
      <playlist-script>/usr/share/mediatomb/js/playlists.js</playlist-script>
      <!--<virtual-layout type="builtin">-->
      <virtual-layout type="disabled">
        <import-script>/usr/share/mediatomb/js/import.js</import-script>
        <dvd-script>/usr/share/mediatomb/js/import-dvd.js</dvd-script>
      </virtual-layout>
    </scripting>
    <mappings>
      <extension-mimetype ignore-unknown="no">
        <map from="mp3" to="audio/mpeg"/>
        <map from="ogg" to="application/ogg"/>
        <map from="m3u" to="audio/x-mpegurl"/>
        <map from="pls" to="audio/x-scpls"/>
        <map from="avi" to="video/divx"/>
        <map from="vob" to="video/mpeg"/>
        <map from="m2ts" to="video/mpeg"/>
        <map from="ts" to="video/mpeg"/>
        <!-- Kommentar Daniel: Mapping2, damit unser On-the-fly Transcode-Script auch angesprochen wird -->
        <map from="mka" to="audio/transcode"/>
        <map from="mkv" to="video/transcode"/>
      </extension-mimetype>
      <mimetype-upnpclass>
        <map from="audio/*" to="object.item.audioItem.musicTrack"/>
        <map from="video/*" to="object.item.videoItem"/>
        <map from="image/*" to="object.item.imageItem"/>
        <map from="application/ogg" to="object.item.audioItem.musicTrack"/>
      </mimetype-upnpclass>
      <mimetype-contenttype>
        <treat mimetype="audio/mpeg" as="mp3"/>
        <treat mimetype="application/ogg" as="ogg"/>
        <treat mimetype="audio/x-flac" as="flac"/>
        <treat mimetype="image/jpeg" as="jpg"/>
        <treat mimetype="audio/x-mpegurl" as="playlist"/>
        <treat mimetype="audio/x-scpls" as="playlist"/>
        <treat mimetype="audio/x-wav" as="pcm"/>
        <treat mimetype="audio/L16" as="pcm"/>
        <treat mimetype="video/x-msvideo" as="avi"/>
        <treat mimetype="video/mp4" as="mp4"/>
        <treat mimetype="audio/mp4" as="mp4"/>
        <treat mimetype="application/x-iso9660" as="dvd"/>
        <treat mimetype="application/x-iso9660-image" as="dvd"/>
        <!-- Kommentar Daniel: Mimetype Mapping für mkv/mka -->
        <treat mimetype="video/transcode" as="mkv"/>
        <treat mimetype="audio/transcode" as="mka"/>
      </mimetype-contenttype>
    </mappings>
  </import>
  <transcoding enabled="yes">
    <mimetype-profile-mappings>
      <!-- Kommentar Daniel: Beim Mimetype video/transcode soll das Profil video2mpeg benutzt werden, also das On-the-fyl Transcoding -->
      <transcode mimetype="video/transcode" using="video2mpeg"/>
      <transcode mimetype="application/ogg" using="oggflac2raw"/>
      <transcode mimetype="audio/x-flac" using="oggflac2raw"/>
    </mimetype-profile-mappings>
    <profiles>
      <profile name="oggflac2raw" enabled="no" type="external">
        <mimetype>audio/L16</mimetype>
        <accept-url>no</accept-url>
        <first-resource>yes</first-resource>
        <accept-ogg-theora>no</accept-ogg-theora>
        <agent command="ogg123" arguments="-d raw -o byteorder:big -f %out %in"/>
        <buffer size="1048576" chunk-size="131072" fill-size="262144"/>
      </profile>
      <!-- Kommentar Daniel: Profil fuer On-the-fly Transcoding -->
      <profile name="video2mpeg" enabled="yes" type="external">
        <mimetype>video/mpeg</mimetype>
        <first-resource>yes</first-resource>
        <agent command="/etc/mediatomb/transcode.sh" arguments="%in %out"/>
        <buffer size="102400" chunk-size="51200" fill-size="20480"/>
      </profile>
    </profiles>
  </transcoding>
</config>

Damit ist Mediatomb fertig konfiguriert.

Script für On-the-fly Transcoding

On-thy-Fly Transcoding heisst nichts anderes, als das eine Datei, während sie gelesen wird, in ein anderes Format ausgegeben wird. Die Datei auf der Festplatte bleibt die selbe, auch das Format, sie wird nur temporär als Stream in neuem Format bereitgestellt.

Das Transcoding bewerkstelligt bei mir das Script transcode.sh. Es wurde von mir in abgewandelter Version aus dem HowTo MediaTomb and PS3: The Lazy Man's solution (Part II) übernommen und etwas angepasst:

transcode.sh
#!/bin/bash
#
# General all-covering MediaTomb transcoding script.
#
#############################################################################
# Edit the parameters below to suit your needs.
#############################################################################
 
# Language for DVD images
LANGUAGE="de"
 
# Subtitles imply transcoding; set to 1 to disable subtitle rendering.
# For divx this doesn't matter much but for mp4, mkv and DVD it does.
DISABLESUBS=1
 
# Change this to enable different DVD subtitle languages.
SUBS="de"
 
# Change this line to set the average bitrate.
# Use something like 8000 for wired connections; lower to 2000 for wireless.
AVBIT=8000
 
# Change this line to set the maximum bitrate.
# Use something like 12000 for wired connections; lower to 5000 for wireless.
MVBIT=12000
 
# Change this line to set the MPEG audio bitrate in kbps. AC3 is fixed to 384.
AABIT=256
 
# Change this line to set your favourite subtitle font.
SFONT="/etc/mediatomb/DejaVuSans.ttf"
 
# Change this line to set the size of subtitles. 20-25 is okay.
SUBSIZE=20
 
# Enable downscaling of transcoded content to 720 pixels wide (DVD format)?
DOWNSCALE=1
 
# If downscaling is enabled, anything over this width (pixels) will be downscaled.
MAXSIZE=900
 
# Enable logging to file?
LOGGING=1
 
# If logging is enabled, log to which file?
LOGFILE="/etc/mediatomb/transcode.log"
 
#############################################################################
# Do not change anything below this line.
#############################################################################
# Variables
#############################################################################
 
FILE=$1
VERSION="0.12"
 
MENCODER=$(which mencoder)
MEDIAINFO=$(which mediainfo)
FFMPEG=$(which ffmpeg)
LSDVD=$(which lsdvd)
XML=$(which xmlstarlet)
 
M_TR_M="-oac lavc -ovc lavc -of mpeg -lavcopts \
    abitrate=${AABIT}:vcodec=mpeg2video:keyint=1:vbitrate=${AVBIT}:\
    vrc_maxrate=${MVBIT}:vrc_buf_size=1835 \
    -mpegopts muxrate=12000 -af lavcresample=44100 "
M_TR_A="-oac lavc -ovc copy -of mpeg -lavcopts \
    abitrate=${AABIT} -af lavcresample=44100 "
M_RE_M="-oac copy -ovc copy -of mpeg -mpegopts format=dvd -noskip -mc 0 "
F_TR_M="-acodec ac3 -ab 384k -vcodec copy -vbsf h264_mp4toannexb -f mpegts -y "
F_RE_M="-acodec copy -vcodec copy -vbsf h264_mp4toannexb -f mpegts -y "
AUDIOOPTS="-alang ${LANGUAGE}"
SUBOPTS="-slang ${SUBS} "
SRTOPTS="-font ${SFONT} -subfont-autoscale 0 \
    -subfont-text-scale ${SUBSIZE} -subpos 100 "
SIZEOPTS="-vf harddup,scale=720:-2 "
NOSIZEOPTS="-vf harddup "
S24FPS="23.976"
S24OPT="-ofps 24000/1001 "
S30FPS="29.970"
S30OPT="-ofps 30000/1001 "
 
VCODEC=""
ACODEC=""
VWIDTH=""
VFPS=""
QPEL=""
AVCPROF=""
 
OPTS=("")
 
declare -i MODE=0
 
#############################################################################
# Functions
#############################################################################
 
function log {
        if [ "${LOGGING}" == "1" ] ; then
                echo -e "$(date +'%Y/%m/%d %H:%m:%S') \t $1" >> ${LOGFILE}
        fi
}
 
function mediainfo {
        MIOUT=$(mktemp /tmp/tmp.mediainfo.XXXXXX)
        log "Logging mediainfo XML to ${MIOUT}."
        ${MEDIAINFO} --output=xml "${FILE}" > ${MIOUT}
        VCODEC=$(${XML} sel -t -m ".//track[@type='Video']" -v "Format" ${MIOUT} )
        ACODEC=$(${XML} sel -t -m ".//track[@type='Audio']" -v "Format" ${MIOUT} )
        VWIDTH=$(${XML} sel -t -m ".//track[@type='Video']" -v "Width"  ${MIOUT} | sed 's/ pixels//' )
        VFPS=$(${XML} sel -t -m ".//track[@type='Video']" -v "Frame_rate" ${MIOUT} | sed 's/ fps//' )
        AVCPROF=$(${XML} sel -t -m ".//track[@type='Video']" -v "Format_profile" ${MIOUT} | sed 's/[^0-9]//g' )
        QPEL=$(${XML} sel -t -m ".//track[@type='Video']" -v "Format_settings__QPel" ${MIOUT} )
        log "Variables found: \
            ${VCODEC} | ${ACODEC} | ${VWIDTH} | ${VFPS} | ${AVCPROF} | ${QPEL} "
        rm -f ${MIOUT}
}
 
function tropts {
        if [ "${DOWNSCALE}" == "1" -a ${VWIDTH} -gt ${MAXSIZE} ] ; then
                log "Rescaling to 720 pixels wide."
                OPTS+=(${SIZEOPTS})
        else
                log "Rescaling disabled or file within limits."
                OPTS+=(${NOSIZEOPTS})
        fi
        if [ "${VFPS}" == "${S24FPS}" ] ; then
                log "Framerate adjusted for mencoder."
                OPTS+=(${S24OPT})
        else if [ "${VFPS}" == "${S30FPS}" ] ; then
                log "Framerate adjusted for mencoder."
                OPTS+=(${S30OPT})
        else
                log "Framerate acceptable for mencoder."
        fi
        fi
}
 
function getmode {
        # Fixed case: DVD ISO.
        if [ "${FEXT}" == "ISO" ] ; then
                CHAPTER=$(${LSDVD} "${FILE}" | grep Longest | sed 's/.* //')
                log "DVD iso image found: Longest chapter is ${CHAPTER}."
                MODE+=${DISABLESUBS}1000000
                return 0
        fi
        # Fixed case: subtitle found: transcode by default.
        if [ "${DISABLESUBS}" == "0" -a -e "$(echo $FILE | sed 's/...$/sub/')" ] ; then
                log "SRT subtitle found."
                SUB=$(echo $FILE | sed 's/...$/sub/')
                MODE+=100000
                return 0
        elif [ "${DISABLESUBS}" == "0" -a -e "$(echo $FILE | sed 's/...$/srt/')" ] ; then
                log "SUB subtitle found."
                SUB=$(echo $FILE | sed 's/...$/srt/')
                MODE+=100000
                return 0
        fi
 
        log "No subtitles found, or subtitle rendering disabled."
        mediainfo
 
        case ${VCODEC} in
        "AVC")
                if [ "${AVCPROF}" -gt "41" ] ; then
                        # Cannot handle h.264 4.1+
                        MODE+=10000
                else
                        # We can handle the rest
                        MODE+=1
                fi ;;
        "MPEG-4 Visual")
                if [ "${QPEL}" == "No" ] ; then
                        # No QPEL: we could remux the video
                        MODE+=100
                else
                        # QPEL: just transcode it all
                        MODE+=10000
                fi ;;
        * )
                        # Transcode everything we don't know
                        MODE+=10000 ;;
        esac
 
        case ${ACODEC} in
        "AC-3" | "MPEG Audio" )
                        # These should be wellknown
                        MODE+=1 ;;
        * )
                if [ "${MODE}" -lt "100" ] ; then
                        # If video is AVC, transcode audio in m2ts
                        MODE+=10
                else
                        # Otherwise in other container
                        MODE+=1000
                fi ;;
        esac
 
}
 
function processmode {
        log "Mode is ${MODE}."
        if [ ! "${MODE}" -lt "10000000" ] ; then
                EXEC="${MENCODER} -dvd-device"
                OPTS+=(dvd://${CHAPTER} ${AUDIOOPTS} ${M_RE_M} -o )
        elif [ ! "${MODE}" -lt "1000000" ] ; then
                EXEC="${MENCODER} -dvd-device"
                OPTS+=(dvd://${CHAPTER} ${AUDIOOPTS} ${SUBOPTS} ${M_TR_M} -o )
        elif [ ! "${MODE}" -lt "100000" ] ; then
                EXEC=${MENCODER}
                tropts
                OPTS+=(${M_TR_M} -sub ${SUB} ${SRTOPTS} -o )
        elif [ ! "${MODE}" -lt "10000" ] ; then
                EXEC=${MENCODER}
                tropts
                OPTS+=(${M_TR_M} -o )
        elif [ ! "${MODE}" -lt "1000" ] ; then
                EXEC=${MENCODER}
                tropts
                OPTS+=(${M_TR_M} -o)
        elif [ ! "${MODE}" -lt "100" ] ; then
                EXEC=${MENCODER}
                OPTS+=(${M_TR_M} -o)
        elif [ ! "${MODE}" -lt "10" ] ; then
                EXEC="${FFMPEG} -i"
                OPTS=(${F_TR_M})
        elif [ ! "${MODE}" -lt "1" ] ; then
                EXEC="${FFMPEG} -i"
                OPTS+=(${F_RE_M})
        else
                log "I'm sorry Dave, I'm afraid I can't do mode=0."
        fi
}
 
#############################################################################
# Main method
#############################################################################
 
log "Starting MediaTomb Multifunctional Transcoder (version ${VERSION})."
FEXT=$(echo $FILE | sed 's/.*\.//' | tr [a-z] [A-Z])
log "${FEXT} file specified: \"${FILE}\""
 
getmode
processmode
 
OPTS=$(echo ${OPTS[@]} | tr '\n' ' ')
 
log "Starting exec:"
log "${EXEC} \"${FILE}\" ${OPTS} ${2} &>/dev/null"
exec ${EXEC} "${FILE}" ${OPTS} "${2}" &>/dev/null

Auf das Script gehe ich jetzt nicht weiter ein, das würde zu lange dauern ;-) Wichtig ist noch, dass für die korrekte Ausführung noch ein paar Bianries nachinstalliert werden müssen:

  • mencoder
  • mediainfo
  • ffmpeg
  • lsdvd
  • xmlstarlet

transcode.sh selbst logt übrigens nach /etc/mediatomb/transcode.log, außer man definiert über die Variable $LOGFILE etwas anderes.

Das sollte auch schon alles gewesen sein. Nach einem Neustart von Mediatomb sollte die Wiedergabe von Videos (AVI, MKV, …) problemlos möglich sein.

howtos/media-streaming.mit.der.playstation.3.und.mediatomb.txt · Last modified: 2011/11/10 20:19 by daniel
 
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Share Alike 3.0 Unported
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki