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