python - 如何在使用 subprocess.Popen 并同时隐藏 cmd 窗口时设置输出文件?

标签 python python-3.x windows ffmpeg subprocess

我做了一个简单的应用程序,可以使用 FFMpeg 转换视频文件。我将 Kivy 用于 UI。我用了os.system()执行 ffmpeg 命令,但在使用此方法时,总是会弹出一个 cmd 窗口。因此我尝试使用 subprocess.Popen()执行 ffmpeg 命令,但我也想将 ffmpeg 输出保存到文本文件。
我试过了,但没有用:

subprocess.Popen(f"ffmpeg -i {path} -acodec {acodec} {output} > output.txt 2>&1", creationflags = 0x08000000, stdout="output.txt")
FFMpeg 转换视频但没有 output.txt 文件。此代码适用于 os.system()如何在将输出保存到文本文件时隐藏 cmd 窗口?
我的完整python代码:
import os
from signal import SIGINT
import psutil
from time import sleep
from threading import Thread
from kivy.config import Config
Config.set('graphics', 'resizable', False)
Config.set('graphics', 'width', '400')
Config.set('graphics', 'height', '330')
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.core.window import Window
from kivy.uix.popup import Popup
from kivy.properties import ObjectProperty

Window.clearcolor = (1, 1, 1, 1)

desktop = os.path.join(os.path.join(os.path.expanduser('~')), 'Desktop') + "\\"


def cmd(command):
    os.system(command)


def getpid(prcs):
    for proc in psutil.process_iter():
        try:
            pinf = proc.as_dict(attrs=["pid", "name"])
            if prcs.lower() in pinf["name"].lower():
                return pinf["pid"]
        except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
            return False
    return False


# noinspection PyGlobalUndefined
def progress(app, path):
    app.root.prgrss_bar.value = 0
    app.root.prgrss_lbl.text = "Progress: %0"

    if not os.getcwd().endswith("ffmpeg"):
        os.chdir("ffmpeg")

    inputpath = app.root.label.text
    if inputpath.startswith("Choose"):
        return
    audio = app.root.audio.state
    video = app.root.video.state
    both = app.root.both.state

    global line1
    global line2

    if video == "down" or both == "down":
        command = f"ffprobe -v error -select_streams v:0 -show_entries stream=nb_frames -of default=nokey=1:noprint_wrappers=1 {inputpath} > output2.txt 2>&1"
        os.system(command)
        ffprobe = open("output2.txt", "r")
        frames = int(ffprobe.read())

        control = True
        while control:
            sleep(0.5)

            with open(path, "r") as f:
                for last_line in f:
                    pass
                line1 = last_line
            sleep(0.5)

            with open(path, "r") as f:
                for last_line in f:
                    pass
                line2 = last_line
            if line1 == line2:
                app.root.prgrss_bar.value = 100
                app.root.prgrss_lbl.text = "Progress: Finished"
                control = False
            else:
                try:
                    current_frame = int(line2.split("=")[1].split()[0])
                    percentage = int(current_frame / frames * 100)
                    text = f"Progress: %{percentage}"
                    app.root.prgrss_lbl.text = text
                    app.root.prgrss_bar.value = percentage
                    if percentage == 100:
                        control = False
                except ValueError or TypeError:
                    pass

    elif audio == "down":
        command = f"ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 {app.root.label.text} > output2.txt 2>&1"
        os.system(command)
        ffprobe = open("output2.txt", "r")
        duration = round(float(ffprobe.read()), 2)
        control = True
        while control:
            sleep(0.5)
            with open(path, "r") as f:
                for last_line in f:
                    pass
                line1 = last_line
            sleep(0.5)

            with open(path, "r") as f:
                for last_line in f:
                    pass
                line2 = last_line
            if line1 == line2:
                app.root.prgrss_bar.value = 100
                app.root.prgrss_lbl.text = "Progress: Finished"
                control = False
            else:
                try:
                    current = line2.split("=")[2].split()[0].split(":")
                    seconds = round((int(current[0]) * 3600) + (int(current[1]) * 60) + float(current[2]), 2)
                    percentage = int(seconds / duration * 100)
                    text = f"Progress: %{percentage}"
                    app.root.prgrss_lbl.text = text
                    app.root.prgrss_bar.value = percentage
                    if percentage == 100:
                        control = False
                except ValueError or TypeError:
                    pass


class Window(Widget):

    @staticmethod
    def popup_open():
        popup = FolderPopup()
        popup.open()

    @staticmethod
    def exists_open():
        popup = Exists()
        popup.open()

    @staticmethod
    def choose_open():
        popup = ChooseFormat()
        popup.open()

    @staticmethod
    def path_popup():
        popup = ChoosePath()
        popup.open()

    @staticmethod
    def unsupported_audio():
        popup = UnsupportedAudio()
        popup.open()

    @staticmethod
    def no_video_format():
        popup = NoVideoFormat()
        popup.open()

    @staticmethod
    def no_process():
        popup = NoFFMPEGProcess()
        popup.open()

    def start(self, app):
        path = app.root.label.text
        if path.startswith("Choose"):
            self.path_popup()
            return

        outname = app.root.outname.text
        video_f = app.root.spinner.text
        audio_f = app.root.spinner2.text
        video = app.root.video.state
        audio = app.root.audio.state
        both = app.root.both.state

        audio_supported = {"MP4": ["AAC", "MP3", "Opus"],
                           "MKV": ["AAC", "MP3", "Opus"],
                           "MOV": ["AAC", "MP3"],
                           "AVI": ["AAC", "MP3"],
                           "WMV": ["AAC", "MP3"]}

        audio_ce = {"AAC": ["aac", ".m4a"],
                    "MP3": ["libmp3lame", ".mp3"],
                    "Opus": ["libopus", ".opus"],
                    "WAV": ["pcm_u8", ".wav"],
                    "Choose": ["Choose", "Choose"]}

        if not os.getcwd().endswith("ffmpeg"):
            os.chdir("ffmpeg")

        video_ext = video_f.lower()
        acodec = audio_ce[audio_f][0]
        audio_ext = audio_ce[audio_f][1]
        command = ""

        if (video == "normal" and audio == "normal" and both == "normal") or (
                video_f == "Choose" and audio_f == "Choose"):
            self.choose_open()
            return
        elif video == "down":
            if video_f == "Choose":
                self.no_video_format()
                return
            output = f"{desktop}{outname}.{video_ext}"
            if not os.path.exists(output):
                command += f"ffmpeg -i {path} -an {output} > output.txt 2>&1"
            else:
                self.exists_open()
                return
        elif audio == "down":
            output = f"{desktop}{outname}{audio_ext}"
            if not os.path.exists(output):
                command += f"ffmpeg -i {path} -vn -acodec {acodec} {output} > output.txt 2>&1"
            else:
                self.exists_open()
                return
        elif both == "down":
            if video_f == "Choose":
                self.no_video_format()
                return
            elif audio_f == "Choose":
                output = f"{desktop}{outname}.{video_ext}"
                if not os.path.exists(output):
                    command += f"ffmpeg -i {path} {output} > output.txt 2>&1"
                else:
                    self.exists_open()
                    return
            else:
                if audio_f not in audio_supported[video_f]:
                    self.unsupported_audio()
                    return
                else:
                    output = f"{desktop}{outname}.{video_ext}"
                    if not os.path.exists(output):
                        command += f"ffmpeg -i {path} -acodec {acodec} {output} > output.txt 2>&1"
                    else:
                        self.exists_open()
                        return

        thrd = Thread(target=cmd, args=(command,))
        thrd.start()
        print("Thread started.")

    def stop(self):
        pid = getpid("ffmpeg")
        if not pid:
            self.no_process()
        else:
            os.kill(pid, SIGINT)

    def test_open(self, app):
        if not os.getcwd().endswith("ffmpeg"):
            os.chdir("ffmpeg")

        video = app.root.label.text
        if video.startswith("Choose"):
            return self.path_popup()

        command = f"ffplay {video}"
        os.system(command)

    @staticmethod
    def check_progress(app):
        path = os.getcwd() + r"\output.txt"
        chkprgrss = Thread(target=progress, args=(app, path,))
        chkprgrss.start()


class FolderPopup(Popup):
    dosya = ObjectProperty(None)
    desktop = desktop

    @staticmethod
    def no_path_submit():
        popup = NoPathSubmit()
        popup.open()

    def buton(self, app):

        try:
            app.root.label.text = self.dosya.selection[0]
            self.dismiss()
        except:
            self.no_path_submit()


class Exists(Popup):
    def buton(self):
        self.dismiss()


class ChooseFormat(Popup):
    def buton(self):
        self.dismiss()


class ChoosePath(Popup):
    def buton(self):
        self.dismiss()


class UnsupportedAudio(Popup):
    def buton(self):
        self.dismiss()


class NoVideoFormat(Popup):
    def buton(self):
        self.dismiss()


class NoPathSubmit(Popup):
    def buton(self):
        self.dismiss()


class NoFFMPEGProcess(Popup):
    def buton(self):
        self.dismiss()


class GUI(App):
    def build(self):
        return Window()


if __name__ == "__main__":
    GUI().run()

最佳答案

用户发布了答案并删除了,但我根据他/她的答案找到了解决方案。
我使用了这段代码:

with open("output.txt", "w") as output:
    subprocess.run( ["ffmpeg", "-i", "video.mp4", "-acodec", "aac", "namnum.mov"], stdout=output, stderr=output, text=True, check=True, creationflags=0x08000000)

关于python - 如何在使用 subprocess.Popen 并同时隐藏 cmd 窗口时设置输出文件?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66437404/

相关文章:

python - 用电视节目将消息转发给 super 组

python - 细数汉诺塔的 Action

python - 使用python替换json文件中的引号

windows - 无法使用 GNAT Ada 读取 USB com 端口

linux - Windows 操作系统上来自 python 的 Neo4j 服务器 API

python - `in` 运算符链接出现意外结果

python-3.x - python :find a number in a list (smaller but the biggest one)

python - 创建缓存以更快地访问python中的字典列表

asp.net - Microsoft .NET Framework 4.6.2 开发包 Windows 10 Build 1607

来自 CSV 的二维列表中的 Python 组值