YoutubeLoader No. 7342 < Jetzt mit GUI :) >



  • Hallo hallo,
    nach langem Warten ist endlich auch das GUI fertig 😃
    Zudem wurden an der Klasse selbst auch einige (teilweise ziemlich dumme) Bugs behoben, aber ich denke mal dass die jetzt halbwegs Fehlerlos ist.
    Ich bin mir durchaus bewusst dass der Code des GUIs nicht sonderlich schön ist, aber na ja.. er tut halt seinen Zweck. Falls ihr euch also die Mühe machen wollt und Code lest, führt euch lieber die YoutubeLoader-Klasse selbst zu Gemüte, daran habt ihr wahrscheinlich mehr Spass 🙂
    Ansonsten freue ich mich aber natürlich wie immer über Anmerkungen, Anregungen, Wünsche, Danksagungen, Lobesreden, etc. sowohl zum Code als auch zum Programm selbst.

    Patentstreitigkeiten sei Dank, darf ich aber keinen MP3-Encoder verteilen. Im Release-Ordner steckt aber eine Textdatei, in welcher ausführlich beschrieben wird wie man ffmpeg MP3-fähig kompiliert.

    Sowohl die YoutubeLoader-Klasse als auch das Beispielprogramm sollten vollständig Systemunabhängig sein, falls jemand da Probleme mit hat -> melden 🙂
    Das GUI besteht fast nur aus WinAPI und ist somit nicht wirklich Systemunabhänig.

    Ich würde mal sagen, zusammen mit ffmpeg ist das der momentan angenehmste Youtube-To-WasWeißIch Converter.

    Genug geschwafelt, hier ist das Paket:
    http://www33.zippyshare.com/v/59955982/file.html

    Edit:
    Zufällig hat sich jemand bereit erklärt eine fertige Version von ffmpeg bei meinem Lieblingshoster hochzuladen, für die ganz Faulen also:
    http://www53.zippyshare.com/v/14534214/file.html

    <---------- alter Post ---------->

    Moin 😉

    Bei meinen ersten zarten Schritten in Richtung C++ ist eine nette kleine Klasse mit der man Videos von Youtube laden kann entstanden, diese möchte ich hier vorstellen.
    Grundaufbau:
    - Man erstellt eine Instanz der Klasse.
    - Man weist dieser Instanz eine callback Funktion zu.
    - (optional) Man weist der Instanz einen void* userdata (an dieser Stelle freundliche Grüße an hustbaer :p) zu, welcher dann bei jedem callback Aufruf wieder übergeben wird.
    - Man ruft die Funktion "Load(std::string& url)" auf - und wartet 😉

    Was macht "Load()"?
    - URL parsen. (Host und Ressource für HTTP-GET)
    - HTTP-request schicken und auf eine Antwort warten.
    - Die Antwort parsen und je nach dem
    - Reconnect verarbeiten.
    - Flashplayer Zeugs (oder was das auch immer sein soll ;)) verarbeiten.
    - Video laden.

    -- Das Video wird nicht direkt auf der Platte gespeichert, sondern die empfangenen Blöcke werden der callback Funktion übergeben.

    Die gesamte Klasse sollte Plattformunabhängig sein (sofern man die WinSock2.h mit seinen Socket Dateien austauscht, und die richtigen libs linkt).
    Es wird "automatisch" das Video in der besten verfügbaren Qualität ausgesucht - man kann also auch Problemlos full-HD laden.
    Die Klasse steht unter der GPL v2 (^^).
    Die Klasse sollte (was eine Überraschung) vollständig Multithreading fähig sein.

    Ich habe zudem ein kleines (Text-)Programm geschrieben dass man zum testen nutzen kann. Ein GUI für Windows wird noch folgen 😉

    Falls sich also jemand dafür interessiert kann er sich gerne dieses Paket laden:
    http://www15.zippyshare.com/v/41359372/file.html
    EDIT: (!) Mir ist aufgefallen dass die exception Klasse (class YTException, deklariert in Zeile 96, ytdl.h) einen groben, gravierenden Fehler hat. Der Member m_what muss vom Typ std::string und nicht vom Typ const char* sein. Ich bastel gerade noch an einem GUI, sobald das fertig ist wird auch eine gefixte Version hochgeladen.
    Inhalt:
    - Source der Klasse und dem Beispielprogramm
    - Als .lib kompilierte Klasse (W32)
    - Kompiliertes (und gelinktes) Beispielprogramm (W32)

    Ich freue mich natürlich gleichermaßen über Anmerkungen zum Code und zum Programm selbst 🙂

    ..:
    - Vergesst nicht beim Aufrufen des Beispielprogramms Anführungszeichen um den Link zu machen.
    - Ich suche immer noch eine gute Methode den flv Container (MPEG4 (H264) / AAC) in Formate wie mp3 und/oder ogg umzuwandeln.
    Der eigentliche Plan war hier das ganze mit ffmpeg zu machen, doch das ist leider gar nicht so einfach.
    Ich bin für jede Unterstützung in dieser Richtung dankbar!

    Beste Grüße
    cooky451

    Edit: Nachrichtendoku:
    YTDL_THREADSTATUS: param = 0, buf = 0; (Zur Überprüfung ob der Thread enden soll)
    YTDL_START: param = 0, buf = "Initializing"; (Wird einmalig am Anfang gesendet)
    YTDL_SEND_REQUEST: param = 0, buf = "Send HTTP-request"; (Wird vor jeder HTTP-request geschickt)
    YTDL_HTTP_REQUEST: param = strlen(buf), buf = request; (Wird nach jeder HTTP-request geschickt; buf enthält die geschickte Anfrage)
    YTDL_RECV_RESPONSE: param = 0, buf = "Receive HTTP-response"; (Wird vor dem Empfangen einer HTTP-response gesendet)
    YTDL_HTTP_RESPONSE: param = strlen(buf), buf = response; (Wird nach jeder erfolgreich empfangenen HTTP-response gesendet; buffer enthält die erhaltene Antwort)
    YTDL_REDIRECTED: param = 0, buf = "Redirected"; (Wird vor dem parsen einer Weiterleitung geschickt)
    YTDL_RECV_FLASHDATA: param = 0, buf = "Receive flashdata"; (Wird vor dem Empfangen des Flashplayer Zeugs geschickt)
    YTDL_FLASHDATA: param = strlen(buf), buf = Flashplayer Zeugs; (Wird nach dem erfolgreichen Empfangen des Flashplayer Zeugs geschickt)
    YTDL_PARSE_FLASHDATA: param = 0, buf = "Parse flashdata"; (Wird vor dem parsen des Flashplayer Zeugs geschickt)
    YTDL_TITLE: param = 0, buf = Titel des Videos; (Sollte man abfangen um den Dateinamen zu generieren)
    YTDL_STREAMLOCATION_HOST: param = 0, buf = Streamhost; (Braucht man nicht abfangen, aber wenn es jemanden interessiert.. - wird in der aktuellen Version auch noch nicht gesendet. Steht sonst aber auch eh in der YTDL_HTTP_REQUEST)
    YTDL_STREAMLOCATION_RESOURCE: param = 0, buf = Resource; (Siehe YTDL_STREAMLOCATION_HOST)
    YTDL_VIDEOSIZE: param = videosize, buf = 0; (Sollte abgefangen werden wenn man eine Art Progressbar bauen will)
    YTDL_START_DOWNLOAD: param = 0, buf = "Loading.."; (Wird vor dem Laden des Videos gesendet)
    YTDL_DOWNLOAD_STATUS: param = Paketgröße, buf = Paket; (Wichtigste Nachricht, wird gesendet wenn ein Videopaket empfangen wurde. Dieses kann man dann zB. in eine Datei schreiben)
    YTDL_COMPLETE: param = 0, buf = "->End<-"; (Ich bin mir hier noch nicht so ganz einig wann und wo es gesendet werden soll. Momentan wird es nach einem vollständig heruntergeladenen Video gesendet.)

    Edit:
    Jetzt auch mit Linux Headern + Titel bug gefixt 😉



  • Hi cooky451,

    sehr schönes Projekt! Ich wollte sowas auch in nächster Zeit mal machen, habe mich aber darum gedrückt mich selber mit dem Download des Videos zu beschäftigen und lieber ein fertiges Skript genommen, um dann nur mein Frontend darum zu bauen.
    Leider läuft deine Lib wegen WinSock nicht sofort unter Linux, sonst würde ich das Skript sofort durch dein Programm austauschen. Mal sehen, ob ich mir mal die Mühe mache dein Programm auf boost Sockets zu erweitern.
    Gute Arbeit auf jeden Fall!

    mfG
    KaPtainCugel



  • Vielen Dank für dein Feedback, freut mich dass das Ganze so gut ankommt!
    Allerdings muss ich zugeben dass ich nicht mal wirklich damit gerechnet hatte dass die Klasse jemand nutzt - ich werde also mal eben die Nachrichten dokumentieren.

    --
    Ein Bug hat die Klasse auch noch:
    Wenn im Videotitel ein "&" steht wird dieses als "&amp" geschickt. Das muss ich noch aus dem Titel schneiden 😉



  • Das funktioniert ja wunderbar - vielen Dank für deine Arbeit!



  • püsh 🙂



  • Der Member m_what muss vom Typ std::string und nicht vom Typ const char* sein.

    Noch besser wäre std::shared_ptr<std::string> .
    Exceptions sollten immer no-throw kopierbar sein.



  • hustbaer schrieb:

    Der Member m_what muss vom Typ std::string und nicht vom Typ const char* sein.

    Noch besser wäre std::shared_ptr<std::string> .
    Exceptions sollten immer no-throw kopierbar sein.

    Wie gesagt, das ist der alte Post. Ich habe mich zwischenzeitlich dazu entschieden einfach std::exception zu kapseln; die aktuelle exception Klasse sieht also so aus:

    namespace ex
    {
      class exception
      {
      public:
        exception(const char* what, int ex_id);
        const char* what();
        int error();
        const std::exception m_exception;
        const int m_ex_id;
      };
    }
    

    Ich bin mir nicht ganz sicher was "no-throw kopierbar" heißt, bin aber immer offen für hilfreiche Links!



  • Ich habe mich zwischenzeitlich dazu entschieden einfach std::exception zu kapseln;

    std::exception ist eigentlich zur Vererbung gedacht ( std::exception::what() ist virtual), sodass es reicht die Basisklasse zu fangen. Natürlich geht dein Ansatz auch, aber dann muss der Benutzer sowohl ex::exception als auch std::exception fangen.

    Ich bin mir nicht ganz sicher was "no-throw kopierbar" heißt, bin aber immer offen für hilfreiche Links!

    no-throw kopierbar heißt einfach, dass beim Kopieren eines Exception Objekts keine Exception fliegt. Aus diesem Grund ist es keine gute Idee einen std::string als Member zu haben, da dieser beim Kopieren werfen kann.



  • Guybrush™ schrieb:

    Ich habe mich zwischenzeitlich dazu entschieden einfach std::exception zu kapseln;

    std::exception ist eigentlich zur Vererbung gedacht ( std::exception::what() ist virtual), sodass es reicht die Basisklasse zu fangen. Natürlich geht dein Ansatz auch, aber dann muss der Benutzer sowohl ex::exception als auch std::exception fangen.

    Ich bin mir nicht ganz sicher was "no-throw kopierbar" heißt, bin aber immer offen für hilfreiche Links!

    no-throw kopierbar heißt einfach, dass beim Kopieren eines Exception Objekts keine Exception fliegt. Aus diesem Grund ist es keine gute Idee einen std::string als Member zu haben, da dieser beim Kopieren werfen kann.

    Dass man ex::exception und std::exception fangen muss finde ich eigentlich gar nicht schlecht, wird so eine std::exception geworfen weiß man das irgendetwas ziemlich schief läuft 🙂

    Ah ok, dann sollte das kopier Zeug mit std::exception ja geregelt sein, danke!



  • cooky451 schrieb:

    Dass man ex::exception und std::exception fangen muss finde ich eigentlich gar nicht schlecht, wird so eine std::exception geworfen weiß man das irgendetwas ziemlich schief läuft 🙂

    das kannst du doch auch mit Vererbung erreichen

    try {
       ...
    } catch (myexception &e) {
       ...
    } catch (std::exception &e) {
       // PANIC
    }
    


  • std::exception hat keinen vom Standard garantierten Konstruktor bei dem man einen String mitgeben könnte.
    Nimm lieber std::runtime_error .



  • hustbaer schrieb:

    std::exception hat keinen vom Standard garantierten Konstruktor bei dem man einen String mitgeben könnte.
    Nimm lieber std::runtime_error .

    Ok, werde ich denn wohl so machen 🙂


Anmelden zum Antworten