FAQ  •  Register  •  Login

VDR Streamdev plugin

<<

Makka

Serviio newbie

Posts: 2

Joined: Fri Mar 23, 2012 4:21 pm

Post Fri Mar 23, 2012 4:45 pm

VDR Streamdev plugin

Hello all
I am using Serviio as serve the movies i have on the home server to the TVs around the house.
The home server is linux based and is used as PVR too vith VDR software.
VDR have a plugin which enable the stream of live channels (stremdev plugin) which give a web-frontend on port 3000 with actual channels and corresponding link to the stream.
I can add a single channel to serviio using the Live Stream source and using, as url, the link to the stream
example: http://127.0.0.1:3000/T-272-940-4006.ts
The problem is that this should be done for each channel (more than 200 now) and should be changed and reviewed each time a channel is added or changed (due for example to a re-tune).
Since the VDR plugin offers a web interface, a serviio plugin to fetch the web page and extract channel names and stream links to the sources will be perfect.
The streamdev plugin can even produce an m3u playlist but afaik playlist support is not there yet .
Anyone interested in developing the plugin?
I can give more informations if needed.

Makka
<<

Makka

Serviio newbie

Posts: 2

Joined: Fri Mar 23, 2012 4:21 pm

Post Fri Mar 30, 2012 11:42 am

Re: VDR Streamdev plugin

Sorry to bump my own thread.
Nobody able to create a plugin is interested in having such a setup?
I could try to do one on my own but i have found no suitable documentation about creating a plugin and my java skills are really poor.
Someone can point me on the right direction?
What the plugin should do is just parse the streamdev web page and:
1) get the channel groups to create virtual folders (one for each group + "all").
2) get the channels in each group and add to the corresponding folder the channel name with the corresponding streming link

Makka
<<

zip

User avatar

Serviio developer / Site Admin

Posts: 16328

Joined: Sat Oct 24, 2009 12:24 pm

Location: London, UK

Post Fri Mar 30, 2012 12:15 pm

Re: VDR Streamdev plugin

<<

cleem

Serviio newbie

Posts: 1

Joined: Sat Oct 19, 2013 5:42 pm

Post Sat Oct 19, 2013 7:42 pm

Re: VDR Streamdev plugin

Hi,

created a quick and dirty java tool today to transform Channels in VDRs streamdev channels.m3u to serviio Online-Sources.
The tool connects to streamdev loads channels.m3u and writes serviio sob file.
File can be imported via Control panel.

  Code:
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.StringReader;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLEncoder;
import java.util.Scanner;
import java.util.StringTokenizer;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.dom.DOMSource;
import javax.xml.transform.stream.StreamResult;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

public class streamdev2serviio {

   static URL m3uUrlRessource = null;
   static File sobFile = null;
   static String m3uContent = null;
   
   static int streamdevChannelCount;
   static Object[] channelArray;
   static int extractedChannelsCount;
   
   static String header_text_serviioLink_Element ="serviio://";
   static String user_text_serviioLink_Element ="video";
   static String pw_text_serviioLink_Element ="live";
   static String urlattrib_text_serviioLink_Element ="?url=";
   static String and_text_serviioLink_Element ="&";
   static String name_text_serviioLink_Element ="name=";
   static int xmlCreatedCount;
   
   
   public static void main(String[] args) {

      
    System.out.println("INFO:\t Starte streamdev2serviio");
    System.out.println("INFO:\t Prüfe Kommandozeilenargumente");
    checkArgs(args);
   
    System.out.println("INFO:\t Starte die Verarbeitung der URL <"+m3uUrlRessource+">");
    parseChannels();
   
    System.out.println("INFO:\t Erzeuge serviio XML-Import Datei");
    writeBackupFile();
   
   }
   
   private static void writeBackupFile() {
      // TODO Auto-generated method stub
      
      
      try {
         DocumentBuilderFactory docFactory = DocumentBuilderFactory.newInstance();
         DocumentBuilder docBuilder = docFactory.newDocumentBuilder();   
         Document doc = docBuilder.newDocument();
         Element onlineRepositoriesBackup_Element = doc.createElement("onlineRepositoriesBackup");
         doc.appendChild(onlineRepositoriesBackup_Element);
         Element items_Element = doc.createElement("items");
         onlineRepositoriesBackup_Element.appendChild(items_Element);

         String[] currentChannel_Array;
         String current_text_serviioLink_Element;
         
         for(int i = 0; i < channelArray.length; i++){
         currentChannel_Array = (String[])channelArray[i];
         
         Element current_backupItem_Element = doc.createElement("backupItem");
         current_backupItem_Element.setAttribute("enabled", "true");
         current_backupItem_Element.setAttribute("order", (i+1)+"");
         items_Element.appendChild(current_backupItem_Element);
   
         Element current_serviioLink_Element = doc.createElement("serviioLink");
         current_text_serviioLink_Element =    header_text_serviioLink_Element +
                              user_text_serviioLink_Element +
                              ":"+
                              pw_text_serviioLink_Element+
                              urlattrib_text_serviioLink_Element +
                              URLEncoder.encode(currentChannel_Array[1], "UTF-8") +
                              and_text_serviioLink_Element +
                              name_text_serviioLink_Element +
                           URLEncoder.encode(currentChannel_Array[0], "UTF-8");
         
         current_serviioLink_Element.setTextContent(current_text_serviioLink_Element);
         
         
         current_backupItem_Element.appendChild(current_serviioLink_Element);
          System.out.println("\t Erzeuge serviio Online-Quelle für streamdev Kanal <"+currentChannel_Array[0]+">");
         System.out.println(current_text_serviioLink_Element);
         
         Element current_accessGroupIds_Element = doc.createElement("accessGroupIds");
         current_backupItem_Element.appendChild(current_accessGroupIds_Element);
         
         Element current_id_Element = doc.createElement("id");
         current_id_Element.setTextContent("1");
         current_accessGroupIds_Element.appendChild(current_id_Element);
         xmlCreatedCount++;
         }
         
         System.out.println("INFO:\t Erzeugte serviio Online-Quellen <"+xmlCreatedCount+">");
         
         TransformerFactory transformerFactory = TransformerFactory.newInstance();
         Transformer transformer = transformerFactory.newTransformer();
         transformer.setOutputProperty(OutputKeys.INDENT, "yes");
         DOMSource source = new DOMSource(doc);
         StreamResult result = new StreamResult(sobFile);
         
         System.out.println("INFO:\t Schreibe Online-Quellen in serviio Import-Datei <"+sobFile+">");
         transformer.transform(source, result);
   
         if(extractedChannelsCount == streamdevChannelCount && extractedChannelsCount == xmlCreatedCount && streamdevChannelCount == xmlCreatedCount){
            System.out.println("INFO:\t Import-Datei mit <"+xmlCreatedCount+"> serviio Online-Quellen aus <"+streamdevChannelCount+"> streamdev Kanälen erzeugt");
            
            System.exit(0);
         }
         else{
            System.out.println("INFO:\t Import-Datei mit <"+xmlCreatedCount+"> serviio Online-Quellen aus <"+streamdevChannelCount+"> streamdev Kanälen erzeugt");
            
   
         }
         
         
      } catch (ParserConfigurationException e) {
         System.out.println("FEHLER:\t XML-Fehler beim erstellen der Ausgabedatei <"+sobFile+">");
                  
         
      } catch (UnsupportedEncodingException e) {
         System.out.println("FEHLER:\t URL Encoding fehlgeschlagen");
      } catch (TransformerConfigurationException e) {
         System.out.println("FEHLER:\t XML-Parser Konfigurationsfehler");
         System.exit(1);
      } catch (TransformerException e) {
         System.out.println("FEHLER:\t XML-Transformation fehlgeschlagen");
         System.exit(1);
      }
      
      
      
   }

   private static void parseChannels() {
   
      try {
         m3uContent = new Scanner(m3uUrlRessource.openStream(),"UTF-8").useDelimiter("\\A").next();
         
         if(!m3uContent.toLowerCase().startsWith("#EXTM3U".toLowerCase())){
            System.out.println("FEHLER:\t Ungültige channels.m3u <"+m3uUrlRessource+"> #EXTM3U nicht vorhanden");
            System.exit(1);   
         }
         
         streamdevChannelCount  = (((m3uContent.split(System.getProperty("line.separator")).length)-1)/2);

         
         if(!(streamdevChannelCount > 0)){
            System.out.println("FEHLER:\t Keine Kanäle in channels.m3u <"+m3uUrlRessource+">");
            System.exit(1);      
         }
         System.out.println("INFO:\t Gefundene Kanäle: <"+streamdevChannelCount+">");
         
         
         
         
      } catch (IOException e) {
         System.out.println("FEHLER:\t Fehler beim Laden der channels.m3u von <"+m3uUrlRessource+">");
         System.exit(1);
      }
      
      
      
      try {
         BufferedReader m3uFileReader = new BufferedReader(new StringReader(m3uContent));
         String currentLine = m3uFileReader.readLine();
         if(currentLine.equals("#EXTM3U")){
            
            channelArray = new Object[streamdevChannelCount];
            
            String part1 = null;
            String part2 = null;
            String part1_tmp1 = null;
            String to_remove_part1_tmp1 = null;
            String part1_tmp2 = null;
            extractedChannelsCount = 0;
            
            for(int i = 0; i < streamdevChannelCount; i++){
               part1 = m3uFileReader.readLine();
               part2 = m3uFileReader.readLine();
         
               if(!part1.toLowerCase().startsWith("#EXTINF:".toLowerCase()) && !part2.toLowerCase().startsWith("HTTP".toLowerCase())){
                  System.out.println("FEHLER:\t Ungültiger Eintrag in channels.m3u");
                  System.out.println("\t\t"+part1);
                  System.out.println("\t\t"+part2);
               }
               else{
                  extractedChannelsCount++;
                              
               
                  part1_tmp1 = part1.replace("#EXTINF:", "");
                  to_remove_part1_tmp1 = new StringTokenizer(part1_tmp1, " ").nextToken();
                  part1_tmp2 = part1_tmp1.replace(to_remove_part1_tmp1+" ","");
                  
                  String[] currentChannel = {part1_tmp2, part2};
                  
                  channelArray[i] = currentChannel;
                  System.out.println("\t Kanal <"+part1_tmp2+"> gefunden mit Streamdev URL <"+part2+">");
               }
               
               
            }
            
            if(extractedChannelsCount == streamdevChannelCount){
            System.out.println("INFO:\t Parsen der channels.m3u erfolgreich abgeschlossen  <"+extractedChannelsCount+"> von <"+streamdevChannelCount+"> Kanäle bearbeitet");
            }
            else{
            System.out.println("INFO:\t Parsen der channels.m3u fehlerhaft abgeschlossen <"+extractedChannelsCount+"> von <"+streamdevChannelCount+"> Kanäle bearbeitet");   
            }
      
         }
   
         
         
      } catch (IOException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
      
      
      
      
   }

   public static void checkArgs(String[] args){
      if (args.length != 2) {
   
         System.out.println("FEHLER:\t Korrekter Aufruf: java streamdev2serviio %streamdev-ts-channel.m3u-url% %servio-output-backup%");
         System.exit(1);

      } else {
         try {
            m3uUrlRessource = new URL(args[0]);
            
            HttpURLConnection huc =  ( HttpURLConnection )  m3uUrlRessource.openConnection ();
            huc.setRequestMethod ("GET");  //OR  huc.setRequestMethod ("HEAD");
            huc.connect () ;
            int httpResponseCode = huc.getResponseCode() ;
            String availabilityString;
            huc = null;
            
            if(httpResponseCode != 200){
               availabilityString = "offline <"+httpResponseCode+">";
               System.out.println("FEHLER:\t Streamdev URL <"+args[0]+"> ist offline");
               System.exit(1);
            }
            else{
               availabilityString = "online";
            }
               
            
            System.out.println("INFO:\t Ermittelte Konfiguration");
            System.out.println("\t Host:\t\t"+m3uUrlRessource.getHost());
            System.out.println("\t Port:\t\t"+m3uUrlRessource.getPort());
            System.out.println("\t Pfad:\t\t"+m3uUrlRessource.getFile());
            System.out.println("\t Status:\t"+availabilityString);
            
         } catch (MalformedURLException e) {
            System.out.println("FEHLER:\t Ungültige streamdev URL: <"+args[0]+"> - Beispiel: http://host:port/TS/channels.m3u");
            System.exit(1);
         } catch (IOException e) {
            System.out.println("FEHLER:\t Fehler bei der Verbindung zu Streamdev URL: <"+args[0]+">");
            System.exit(1);
         }
      
         
         sobFile = new File(args[1]);
         if(!sobFile.getParentFile().exists()){
            System.out.println("FEHLER:\t Ausgabeverzeichnis <"+args[1]+"> existiert nicht");
            System.exit(1);
         }
         
         if(!sobFile.getParentFile().isDirectory()){
            System.out.println("FEHLER:\t Ausgabeverzeichnis ist kein Verzeichnis");
            System.exit(1);
         }
         
         if(!sobFile.getParentFile().canWrite()){
            System.out.println("FEHLER:\t Ausgabeverzeichnis ist nicht beschreibbar");
            System.exit(1);
         }
         
         System.out.println("\t Ausgabe:\t"+sobFile);
         
         //System.out.println("INFO:\t Verwende Ausgabedatei <"+sobFile+">");
         
         

      }

   }

}


Tool can be executed as following
  Code:
java streamdev2serviio %m3u-url% %outputFile%



First i wanna know if there is a simple way to purge all added Online Sources?
Since we have no checkboxes for each Online Source and no select all button, its quite hard mass-removing entries...

Second i wanna add tvlogos as thumbnails.
Currently logos are stored at http://someserver/tvlogo/
Channel names are representing picture files on http server, so its easy to extend script.
My first tries did not succeed, as browsing Online Sources via :23424/mediabrowser/ channellogos did not appear.
Added Picture-URL works fine via Browser.
Are there any reqs for the pictures? E.g. size, format?

Regards
Clem
<<

abeani

Serviio newbie

Posts: 3

Joined: Mon Dec 09, 2013 7:53 am

Post Thu Dec 19, 2013 3:50 pm

Re: VDR Streamdev plugin

Hi,

well, I finally hacked together a very simple plugin to access the channels or a group of channels directly via the RSS interface provided by the Streamdev plugin.

Installation: Just drop it in the serviio/plugins, restart Serviio to have it pick up the new plugin and add a "Online RSS/Atom Feed" source with the url to one of your channel groups (e. g. http://hostname:3000/TS/groups.rss?group=1) (or all channels, but read the "issues" below first!). In addition you may set up more feeds for other groups as well.

This constellation has a few "issues":

  • Serviio analyses EACH channel by reading data from it (via ffmpeg). So on the first run, the VDR switches to EACH AND EVERY channel! This occupies the receivers and takes some time (about an hour in my case with about ~80 channels and only one free receiver)... - It may take even longer if the channel list is longer...
  • It looks like Serviio checks those channels later again from time to time, but that did not seem to happen that often nor does it have such a huge impact as the first run.
  • You can currently provide only a name (no icon, ...) for each channel via this RSS interface.
  • Playback of the channels does not work with all clients. XBMC for example fails (if I read the logs right, it expects the server to respond IMMEDIATELY with data, but Serviio/Streamdev seem to need some time to switch and start streaming, so XBMC runs into a timeout - and with the xvdr-plugin there is a much more applealing solution for this case), our Sony Bravia TV fails as well, but the Popcorn Hour player works like a charm...
  • Streaming of the recordings using this plugin does not seem to work (ffmpeg fails to analyse the streams is what I read from the logs and Serviio does not list anything for the feed). And without any additional structure (see http://forum.serviio.org/viewtopic.php?f=22&t=9760) you would end up seeing all recordings in a flat list without thumbnails where the list is updated only once per hour (minimum interval for RSS polls) - this not how I want to browse my library. This is why this plugin simply does not accept recording URLs.

Anyway, it works for me and perhaps helps somebody else as well.

Happy zapping!

Andy
Attachments
vdr-streamdev-channel-rss.groovy
(3.79 KiB) Downloaded 197 times
<<

compi

Serviio newbie

Posts: 17

Joined: Sat Dec 20, 2014 6:00 pm

Post Tue Apr 19, 2016 10:49 am

Re: VDR Streamdev plugin

the plugin shows me only 50 channels. In Serviio unlimited rss-feed is set. I use Serviio 1.6.1

Gesendet von meinem Xperia Z Ultra mit Tapatalk
<<

Paolo

Serviio newbie

Posts: 3

Joined: Wed May 10, 2017 11:31 pm

Post Wed May 10, 2017 11:36 pm

Re: VDR Streamdev plugin

seems hat usefull The java script STREAMDEV2SERVIIO is not working if line are not ending with M3u but are ending with mkv ts mp4
somebody can fix this problem...i'm not able to do it.

Return to Plugin requests

Who is online

Users browsing this forum: Baidu [Spider] and 1 guest

Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group.
Designed by ST Software for PTF.