Seite 1 von 1

korrekter Befehl wird inkorrekt an CMD übergeben

Verfasst: Donnerstag 7. Mai 2020, 15:57
von Space
Hallo,
zu erstmal ich bin neu hier im Forum und wusste nicht wo genau das Thema hingehört daher habe ich es hier eingeordnet.
Desweiteren bin ich noch nicht allzu erfahren im Programmieren. Daher wären mir Tipps zu dem Script willkommen.

Nun zu dem Problem(en). Ich habe als mein erstes größeres Projekt versucht einen Youtube-Downloader zu programmieren. Für die GUI habe ich Kivy genommen und für den Download etc. Pytube
Da die Heruntergeladene Datei meist nicht in dem Gewünschten Format, also mp3 für Audio und mp4 für Video vorliegt, habe ich mich für ffmpeg entschieden um die Dateien umzuwandeln/mergen. Nach einigem herumbasteln habe ich es auch geschafft.
Wenn ich allerdings die Dateien in den nicht genutzten Format per CMD Befehl löschen möchte dann erhalte ich eine Fehlermeldung. Lasse ich mir den Befehl in Python ausgeben und kopiere in in die cmd dann wird er korrekt ausgeführt. Der Befehl wird per subprocess.call()
ausgeführt. CMD gibt aus dass es die angegebene Datei nicht finden kann. Der Befehl würde die Umwandlung per FFmpeg funktioniert aber einwandfrei. Kennt da jemand eine Lösung?

Code: Alles auswählen


import kivy
import pytube
from pytube import YouTube
from pydub import AudioSegment
from kivy.app import App
from kivy.uix.button import Button
from kivy.uix.label import Label
from kivy.uix.textinput import TextInput
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty
from kivy.uix.dropdown import DropDown
from kivy.uix.boxlayout import BoxLayout
from kivy.uix.gridlayout import GridLayout
from kivy.base import runTouchApp
import ffmpeg
from kivy.uix.checkbox import CheckBox
from kivy.uix.floatlayout import FloatLayout
from kivy.uix.popup import Popup
import sys
import os
import re
import subprocess







class P(FloatLayout):
    pass

class MyGrid(Widget):
    introlabel = ObjectProperty(None)
    auswahllabel = ObjectProperty(None)
    linkinput = ObjectProperty(None)
    downloadbutton = ObjectProperty(None)
    speicherort = ObjectProperty(None)
    dropdownmenue = ObjectProperty(Button())
    confirmbutton = ObjectProperty(None)
    inhalt = ObjectProperty(None)
    checkboxmp3 = ObjectProperty(None)
    checkboxvideo = ObjectProperty(None)

#Nur ein Feld aktivieren
    def uncheck(self, value):
        if value == "video":
            self.checkboxmp3.active = False
        else:
            self.checkboxvideo.active = False

#Exeption PopUp
    def raise_exception(self):
        show = P()
        popupWindow = Popup(title="Warnung", content=show, size_hint=(None, None), size=(400, 400))
        popupWindow.open()


#Link überprüfen und Inhaltslabel anzeigen
    def verifizieren(self):
        if self.linkinput.text == "":
            self.raise_exception()
        else:
            self.yt = YouTube(self.linkinput.text)
            inhalt = str(self.yt.title)
            self.inhalt.text = inhalt

#Unterscheidung mp3 oder video download
    def unterscheiden(self):
        if self.inhalt.text == "":
            self.raise_exception()
        else:
            if self.checkboxmp3.active == True:
                inhalt_liste = []
                inhalt_liste.append( self.yt.streams.filter(only_audio=True).first())
                self.dropdown_mp3(inhalt_liste)
                self.Download_Art = "mp3"

            elif self.checkboxvideo.active == True:
                self.dropdown_video()
                self.Download_Art= "Video"
            else:
                self.raise_exception()


#Abfrage was gedownloadet werden soll.
    def download(self):
        if self.Download_Art =="mp3":
            self.download_mp3()
        else:
            self.download_video()

#Generierung Dropdownmenue und dessen Inhalt
    def dropdown_mp3(self, Dropdown_inhalt):
        dropdown = DropDown()
        for x in Dropdown_inhalt:
            btn = Button(text = str("mp3 ITAG: ")+str(x.itag), size_hint_y=None, height=44)
            btn.bind(on_release=lambda btn: dropdown.select(btn.text))
            dropdown.add_widget(btn)
        self.dropdownmenue.bind(on_release=dropdown.open)
        dropdown.bind(on_select=lambda instance, x: setattr(self.dropdownmenue, "text", x))

    def dropdown_video(self):
        dropdown = DropDown()
        for x in self.yt.streams.filter(only_audio=False):
            btn = Button(text=str(x.resolution) + " ITAG: "+ str(x.itag), size_hint_y=None, height=44)
            btn.bind(on_release=lambda btn: dropdown.select(btn.text))
            dropdown.add_widget(btn)
        self.dropdownmenue.bind(on_release=dropdown.open)
        dropdown.bind(on_select=lambda instance, x: setattr(self.dropdownmenue, "text", x))

    def destination(self):
        if self.speicherort.text == "":
            return r"E:\YoutubeDownloads"
        else:
            return self.speicherort.text

    def download_mp3(self):
        print("download mp3")
        list = self.dropdownmenue.text.split(": ")
        self.zielstream = self.yt.streams.get_by_itag(list[1])
        self.zielstream.download(self.destination(), self.yt.title)
        old_version = str(str(self.destination()) + "\\" + str(self.yt.title) + "." + str("mp4"))
        new_version = str(str(self.destination()) + "\\" + str(self.yt.title) + ".mp3")
        print(old_version)
        print(new_version)
        print("befor Befehl")
        replace_string = (".", ",")
        title = self.yt.title
        for x in replace_string:
            title = title.replace((x), "")
        befehl = "ffmpeg -i " + "\""+self.destination() + "\\" + self.yt.title +".mp4"+"\"" + " " + "\""+self.destination() + "\\"+ self.yt.title + ".mp3"+"\""
        del_befehl = "del \"" + old_version + "\""
        print(del_befehl)
        wiedergabewert_convert = subprocess.call(befehl, shell=False)
        wiedergabewert_del = subprocess.call(del_befehl, shell=False)
        print(wiedergabewert_convert, wiedergabewert_del)
        if wiedergabewert_convert and wiedergabewert_del == 0:
            print("success")


# Videodownload, bei hoherauflösung mergen
    def download_video(self):
        print("download video")
        print(self.destination())

        tag = self.dropdownmenue.text.split(": ")[-1]
        self.zielstream = self.yt.streams.get_by_itag(tag)
        if self.zielstream in self.yt.streams.filter(progressive = True):
            self.yt.streams.get_by_itag(tag).download(self.destination(), self.yt.title)
        elif self.zielstream in self.yt.streams.filter(adaptive=True):
            self.yt.streams.filter(only_audio=True).first().download(self.destination(), self.yt.title + "_audio")
            self.yt.streams.get_by_itag(tag).download(self.destination(), self.yt.title + "_video")
            alle_Elemente = os.listdir(self.destination())
            for Element in alle_Elemente:
                if self.yt.title and "_audio" in Element:
                    alte_Endung_audio = Element.split(".")[-1]
                elif self.yt.title and "_video" in Element:
                    alte_endung_video = Element.split(".")[-1]
            replace_string = (".",",", "|", ":")
            title = self.yt.title
            for x in replace_string:
                title = title.replace((x), "")
            video_download = str("\"" + self.destination() + "\\" + title + "_video." + alte_endung_video +"\"")
            audio_download = str("\""+self.destination() + "\\" + title + "_audio." + alte_Endung_audio +"\"")
            print("video and Audio download", video_download, audio_download)
            befehl_mergen = "ffmpeg -i " + video_download + " -i " + audio_download +" -c:v copy -c:a aac " + "\"" + self.destination() + "\\" + title + ".mp4" + "\""
            befehl_del_1 = "del " + video_download
            befehl_del_2 = "del " + audio_download
            print("Befehle:")
            print(befehl_mergen)
            print(befehl_del_1)
            print(befehl_del_2)

            mergen = subprocess.call(befehl_mergen, shell=False)
            print("##", mergen)

            löschen_audio = subprocess.call(befehl_del_2, shell=False)
            löschen_video = subprocess.call(befehl_del_1, shell=False)
        else:
            self.raise_exception()








class MyApp(App):
    def build(self):
        return MyGrid()


if __name__ == "__main__":
    MyApp().run()
    
Das hier ist der Code. Wenn ich irgendetwas wichtiges noch nicht erwähnt habe einfach nachfragen.
Hier noch die .kv Datei

Code: Alles auswählen


    GridLayout:
        cols: 1
        size: root.width, root.height

        GridLayout:
            cols: 2

            Label:
                id: introlabel
                text: "Link einfügen"

            TextInput:
                id: linkinput
                text_hint: "Link"
                multiline: False

        GridLayout:
            cols: 2
            Label:
                text:"mp3"
            Label:
                text:"video"

            CheckBox:
                id: checkboxmp3
                text: "mp3"
                on_press: root.uncheck("mp3")
                color: 1,1,1,1

            CheckBox:
                id: checkboxvideo
                status: "video"
                on_press: root.uncheck("video")
                color: 1,1,1,1


        Button:
            id: confirmbutton
            text: "Link verifizieren - Dauert kurz"
            on_press: root.verifizieren()

        Label:
            id: inhalt
            text:""

        GridLayout:
            cols:2

            Label:
                id: auswahllabel
                text: "Wähle das Format"

            Button:
                id: dropdownmenue
                text: "Format"
                on_press: root.unterscheiden()


        TextInput:
            id: speicherort
            multiline: False
        Button:
            id: downloadbutton
            text: "Download"
            on_press: root.download()

<P>:
    Label
        text:"Bitte füge einen Link ein"
        size_hint: 0.6,0.2
        pos_hint:{"x":0.2, "top":1}

    Label
        text: "Bitte wähle ein Fromat aus"
        size_hint: 0.8,0.2
        pos_hint:{"x":0.1, "y":0.3}
Meine Zweite Frage ist: Wenn eine Datei per FFMpeg gemergt werden soll und der neue Dateiname schon vergeben ist, dann Fragt CMD mittels einer [y/n] Frage ob man diese Überschreiben möchte. Lässt sich dass an Python weiterleiten so dass auf diese Meldung eine Funktion ausgeführt wird welche beispielsweise ein Dialogfeld öffnet und die gleiche Frage stellt?

Ich hoffe es ist verständlich was ich mit den beiden Fragen meine.....
MFG Space

Re: korrekter Befehl wird inkorrekt an CMD übergeben

Verfasst: Donnerstag 7. Mai 2020, 17:58
von __blackjack__
@Space: Pfadteile setzt man nicht mit ``+`` zusammen sondern mit dem `pathlib`-Modul. Und Du musst den Befehl als Liste aus den Bestandteilen die im anderen Prozess dann `argv` ausmachen übergeben und nicht als *eine* Zeichenkette. Denn das wird nicht inkorrekt an CMD übergeben sondern *gar nicht*. Warum würde man da eine unnütze CMD zwischen den beiden Programmen haben wollen? ``shell=False`` ist der Defaultwert, muss also nicht angegeben werden.

Was soll das `My` im Namen `MyGrid`? Gibt es auch ein `OurGrid` oder ein `TheirGrid`? Und warum `Grid`?

Re: korrekter Befehl wird inkorrekt an CMD übergeben

Verfasst: Donnerstag 7. Mai 2020, 20:49
von Space
Danke erstmal für die schnelle Antwort,
das mit pathlib wusste ich nicht werde ich mir aber anschauen.
MyGrid, ist einfach nur aus einem Tutorial übernommen.

Super vielen Dank für die Info.
Einen schönen Abend noch.