2

我正在尝试创建一个 python 脚本,将音频和视频文件合并到一个(音频+视频)文件中。

我正在使用 ffmpeg 来实现这一点,但它无法正常工作并且我遇到了错误。在运行此脚本时,这是我的脚本。

import os
import subprocess
import time
from datetime import datetime
def merge_all():
    
 global p
 p =subprocess.Popen('ffmpeg -i temp_vid.mp4 -i temp_voice.wav -c:v copy -c:a aac -strict experimental - 
 strftime 1 ' + dt_file_name ,stdin=subprocess.PIPE,creationflags = subprocess.CREATE_NO_WINDOW)
  time.sleep(2)
  print('merging done')
  os.remove('temp_vid.mp4')
  os.remove('temp_voice.wav')
  print('file delete done')>

这是错误

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\kp\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1883, in __call__
    return self.func(*args)

  File "C:\Users\kp\Desktop\test.py", line 179, in change_icon
    merge_all()

  File "C:\Users\kp\Desktop\test.py", line 104, in merge_all
 
p =subprocess.Popen('ffmpeg -i temp_vid.mp4 -i temp_voice.wav -c:v copy -c:a aac -strict experimental -strftime 1 ' + dt_file_name ,stdin=subprocess.PIPE,creationflags = subprocess.CREATE_NO_WINDOW)

  File "C:\Users\kp\AppData\Local\Programs\Python\Python38\lib\subprocess.py", line 854, in __init__
    self._execute_child(args, executable, preexec_fn, close_fds,

  File "C:\Users\kp\AppData\Local\Programs\Python\Python38\lib\subprocess.py", line 1307, in _execute_child

hp, ht, pid, tid = _winapi.CreateProcess(executable, args,
FileNotFoundError: [WinError 2] The system cannot find the file specified
4

4 回答 4

2

你有这一行:

p =subprocess.Popen('ffmpeg -i temp_vid.mp4 -i temp_voice.wav -c:v copy -c:a aac -strict experimental -strftime 1 ' + dt_file_name ,stdin=subprocess.PIPE,creationflags = subprocess.CREATE_NO_WINDOW)

相反,试试这个:

cmd = 'ffmpeg -i temp_vid.mp4 -i temp_voice.wav -c:v copy -c:a aac -strict experimental -strftime 1 ' + dt_file_name 
p = subprocess.Popen(cmd.split(), stdin=subprocess.PIPE, creationflags=subprocess.CREATE_NO_WINDOW)

当然,这是假设这些选项是正确的。

感谢@x00 指出拆分命令的更安全方法是使用shlex.split(). 所以:

cmd = 'ffmpeg -i temp_vid.mp4 -i temp_voice.wav -c:v copy -c:a aac -strict experimental -strftime 1 ' + dt_file_name 
p = subprocess.Popen(shlex.split(cmd), stdin=subprocess.PIPE, creationflags=subprocess.CREATE_NO_WINDOW)

这更安全的原因是因为参数也可以包含空格并且str.split()不会解释这一点。例如:

cmd = 'ffmpeg -i "C:\My long folder name with spaces\temp_vid.mp4"'

这被 正确拆分shlex.split(),但不是str.split()

于 2020-08-04T07:37:34.813 回答
2

文档

将一些参数作为序列传递给外部程序的示例是:

Popen(["/usr/bin/git", "commit", "-m", "Fixes a bug."])

POSIX上,如果args是字符串,则该字符串被解释为要执行的程序的名称或路径。但是,只有在不向程序传递参数的情况下才能做到这一点。

注意如何将 shell 命令分解为一系列参数可能并不明显,尤其是在复杂情况下。shlex.split()可以说明如何确定 args 的正确标记化:

>>> import shlex, subprocess
>>> command_line = input()
/bin/vikings -input eggs.txt -output "spam spam.txt" -cmd "echo '$MONEY'"
>>> args = shlex.split(command_line)
>>> print(args)
['/bin/vikings', '-input', 'eggs.txt', '-output', 'spam spam.txt', '-cmd', "echo '$MONEY'"]
>>> p = subprocess.Popen(args) # Success!

请特别注意,shell 中由空格分隔的选项(例如-input)和参数(例如eggs.txt)位于单独的列表元素中,而在 shell 中使用时需要引用或反斜杠转义的参数(例如包含空格的文件名或echo 命令如上所示)是单个列表元素。

所以正确的调用Popen应该是这样的:

command_line = 'ffmpeg -i temp_vid.mp4 -i temp_voice.wav -c:v copy -c:a aac -strict experimental -strftime 1 ' + dt_file_name
p = subprocess.Popen(shlex.split(command_line), ...)

看起来在您的特定情况下,您可以command_line.split()按照@Grismar 的建议使用,但我会说这是容易出错的方法。

于 2020-08-04T07:42:01.930 回答
2

这是在您的环境中安装 pip install ffmpeg-python 后的 python 代码:

import ffmpeg

input_video = ffmpeg.input('./test_Directory/test.webm')

input_audio = ffmpeg.input('./test_Directory/test.webm')

ffmpeg.concat(input_video, input_audio, v=1, a=1).output('./test_Directory/complete.mp4').run()

或者

video = ffmpeg.input('video.mp4')
audio = ffmpeg.input('audio.wav')
out = ffmpeg.output(video, audio, video_path, vcodec='copy', acodec='aac', strict='experimental')
out.run()

或者

cmd = 'ffmpeg -y -i Audio.wav  -r 30 -i Video.h264  -filter:a aresample=async=1 -c:a flac -c:v copy av.mkv'
subprocess.call(cmd, shell=True)                                    
print('Mixing Done')
于 2020-08-04T12:29:18.637 回答
0

先做pip install ffmpeg-python

然后,您可以使用以下方法组合它们:

import ffmpeg

video = ffmpeg.input('directory_to_video')

audio = ffmpeg.input('directory_to_audio')

ffmpeg.concat(video, audio, v=1, a=1).output('directory_to_save_mp4').run()
于 2020-08-04T07:27:29.543 回答