OSError: MoviePy error: the file guitar.mp4 could not be found
OSError: MoviePy error: the file guitar.mp4 could not be found
我正在使用 React 和 flask/python 开发视频到音频转换器。
我收到了 500 错误消息:
raise IOError(("MoviePy error: the file %s could not be found!\n"
OSError: MoviePy error: the file guitar.mp4 could not be found!
Please check that you entered the correct path.
编辑:如评论中所述,moviepy VideoFileClip 正在寻找路径。根据建议,我现在正尝试将传入的视频文件写入应用程序后端的临时目录。更新的堆栈跟踪显示文件路径打印,但是当呈现给 VideoFileClip 时它仍然不满意。
以下代码段是视频文件上传的 onSubmit:
const onSubmit = async (e) => {
e.preventDefault()
const data = new FormData()
console.log('hopefully the mp4', videoData)
data.append('mp3', videoData)
console.log('hopefully a form object with mp4', data)
const response = await fetch('/api/convert', {
method: "POST",
body: data
})
if (response.ok) {
const converted = await response.json()
setMp3(converted)
console.log(mp3)
} else {
window.alert("something went wrong :(");
}
}
Here is a link to an image depicting the console output of my file upload
来自 init.py
app = Flask(__name__)
app.config.from_object(Config)
app.register_blueprint(convert, url_prefix='/api/convert')
CORS(app)
来自 converter.py
import os
from flask import Blueprint, jsonify, request
import imageio
from moviepy.editor import *
convert = Blueprint('convert', __name__)
@convert.route('', methods=['POST'])
def convert_mp4():
if request.files['mp3'].filename:
os.getcwd()
filename = request.files['mp3'].filename
print('hey its a file again', filename)
safe_filename = secure_filename(filename)
video_file = os.path.join("/temp/", safe_filename)
print('hey its the file path', video_file)
video_clip = VideoFileClip(video_file)
print('hey its the VideoFileClip', video_clip)
audio_clip = video_clip.audio
audio_clip.write_audiofile(os.path.join("/temp/", f"{safe_filename}-converted.mp3"))
video_clip.close()
audio_clip.close()
return jsonify(send_from_directory(os.path.join("/temp/", f"{safe_filename}-converted.mp3")))
else:
return {'error': 'something went wrong :('}
在下面的堆栈跟踪中,您可以看到打印视频名称的文件,我唯一的另一个想法是为什么这可能不起作用是因为它在 post 请求中丢失了,但事实是它是在我的 if file:
支票让我很困惑之后打印的。
hey its a file again guitar.mp4
hey its the file path /temp/guitar.mp4
127.0.0.1 - - [22/Apr/2021 12:12:15] "POST /api/convert HTTP/1.1" 500 -
Traceback (most recent call last):
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 2464, in __call__
return self.wsgi_app(environ, start_response)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/jasondunn/projects/audioconverter/back/api/converter.py", line 20, in convert_mp4
video_clip = VideoFileClip(video_file)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/moviepy/video/io/VideoFileClip.py", line 88, in __init__
self.reader = FFMPEG_VideoReader(filename, pix_fmt=pix_fmt,
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/moviepy/video/io/ffmpeg_reader.py", line 35, in __init__
infos = ffmpeg_parse_infos(filename, print_infos, check_duration,
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/moviepy/video/io/ffmpeg_reader.py", line 270, in ffmpeg_parse_infos
raise IOError(("MoviePy error: the file %s could not be found!\n"
OSError: MoviePy error: the file /temp/guitar.mp4 could not be found!
Please check that you entered the correct path.
提前感谢您接受 look/future 的建议。 Stack Overflow 上的第一位官方 post :)
我认为问题在于您如何使用 file = request.files['mp3'].filename
。
分配给 file
的值不是指向上传文件的指针。它只是文件的名称,一个字符串。只是 request.files['mp3']
是 werkzeug.datastructures.FileStorage
class 记录的实例 here。
您将该字符串传递给的库将其解释为它们应该打开的文件的路径。
由于您没有将文件保存到任何地方,他们的图书馆找不到任何东西。
我不熟悉您正在使用的库,但他们可能有办法直接将内存中的文件数据发送给他们,而无需保存文件然后让他们再次打开它。
如果没有,那么您可能希望将文件保存到某个临时位置,然后打开库并读取文件。
看起来 python 找不到 guitar.mp4
:(
看来您需要在处理之前将文件内容保存在磁盘上。查看docs for MoviePy
需要将文件名或绝对路径传入VideoFileClip
构造函数,此对象会在实例化后打开磁盘上的文件并进行处理。
在请求中保存文件应该很简单。下面的代码应该能够处理这个
file.save(os.path.join("/path/to/some/dir", filename))
现在您可以为文件提供 VideoFileClip
正确的 URI。
video_clip = VideoFileClip(os.path.join("/path/to/some/dir", filename))
这就是我要为 convert_mp4
编写的内容,尽管它没有经过测试。
@convert.route('', methods=["POST"])
def convert_mp4():
if request.files.get("mp3"):
# clean the filename
safe_filename = secure_filename(request.files["mp3"].filename)
# save file to some directory on disk
request.files["mp3"].save(os.path.join("/path/to/some/dir", safe_filename))
video_clip = VideoFileClip(os.path.join("/path/to/some/dir", safe_filename))
audio_clip = video_clip.audio # convert to audio
# you may need to change the name or save to a different directory
audio_clip.write_audiofile(os.path.join("/path/to/some/dir", f"{safe_filename}.mp3"))
# close resources, maybe use a context manager for better readability
video_clip.close()
audio_clip.close()
# responds with data from a specific file
send_from_directory("/path/to/some/dir", f"{safe_filename}.mp3")
else:
return jsonify(error="File 'mp3' does not exist!")
每当你通过 flask 将数据保存到磁盘时,你应该使用 werkzeug 项目内置到 flask 中的 secure_filename
。此函数将清除输入名称,因此攻击者无法创建恶意文件名。
我建议甚至更进一步,也许创建 2 个端点。一个用于提交数据进行处理,第二个用于检索数据。这可以使您的请求保持快速并允许 flask 同时处理其他请求(但是您将需要一些后台进程来处理转换)。
2021 年 4 月 30 日更新
我知道我们在 Discord 上解决了这个问题,但我想记录解决方案。
您的 MP4 数据未使用 save
方法保存到磁盘(参见 this)。你可以查看上面实现这个的代码。
完成后,我们现在知道此数据在哪里,并且可以使用已知文件路径实例化 VideoFileClip
对象,这将允许进行转换,然后您需要保存转换后的文件MP3 文件位于文件系统中的某个位置。
将 MP3 保存到磁盘后,您可以使用 flask send_from_directory
函数在您的响应中发回数据。此响应不能包含 JSON 内容,因为内容类型已根据 MP3 文件内容设置为 audio/mpeg
。
我正在使用 React 和 flask/python 开发视频到音频转换器。 我收到了 500 错误消息:
raise IOError(("MoviePy error: the file %s could not be found!\n"
OSError: MoviePy error: the file guitar.mp4 could not be found!
Please check that you entered the correct path.
编辑:如评论中所述,moviepy VideoFileClip 正在寻找路径。根据建议,我现在正尝试将传入的视频文件写入应用程序后端的临时目录。更新的堆栈跟踪显示文件路径打印,但是当呈现给 VideoFileClip 时它仍然不满意。
以下代码段是视频文件上传的 onSubmit:
const onSubmit = async (e) => {
e.preventDefault()
const data = new FormData()
console.log('hopefully the mp4', videoData)
data.append('mp3', videoData)
console.log('hopefully a form object with mp4', data)
const response = await fetch('/api/convert', {
method: "POST",
body: data
})
if (response.ok) {
const converted = await response.json()
setMp3(converted)
console.log(mp3)
} else {
window.alert("something went wrong :(");
}
}
Here is a link to an image depicting the console output of my file upload 来自 init.py
app = Flask(__name__)
app.config.from_object(Config)
app.register_blueprint(convert, url_prefix='/api/convert')
CORS(app)
来自 converter.py
import os
from flask import Blueprint, jsonify, request
import imageio
from moviepy.editor import *
convert = Blueprint('convert', __name__)
@convert.route('', methods=['POST'])
def convert_mp4():
if request.files['mp3'].filename:
os.getcwd()
filename = request.files['mp3'].filename
print('hey its a file again', filename)
safe_filename = secure_filename(filename)
video_file = os.path.join("/temp/", safe_filename)
print('hey its the file path', video_file)
video_clip = VideoFileClip(video_file)
print('hey its the VideoFileClip', video_clip)
audio_clip = video_clip.audio
audio_clip.write_audiofile(os.path.join("/temp/", f"{safe_filename}-converted.mp3"))
video_clip.close()
audio_clip.close()
return jsonify(send_from_directory(os.path.join("/temp/", f"{safe_filename}-converted.mp3")))
else:
return {'error': 'something went wrong :('}
在下面的堆栈跟踪中,您可以看到打印视频名称的文件,我唯一的另一个想法是为什么这可能不起作用是因为它在 post 请求中丢失了,但事实是它是在我的 if file:
支票让我很困惑之后打印的。
hey its a file again guitar.mp4
hey its the file path /temp/guitar.mp4
127.0.0.1 - - [22/Apr/2021 12:12:15] "POST /api/convert HTTP/1.1" 500 -
Traceback (most recent call last):
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 2464, in __call__
return self.wsgi_app(environ, start_response)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 2450, in wsgi_app
response = self.handle_exception(e)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1867, in handle_exception
reraise(exc_type, exc_value, tb)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 2447, in wsgi_app
response = self.full_dispatch_request()
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1952, in full_dispatch_request
rv = self.handle_user_exception(e)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask_cors/extension.py", line 161, in wrapped_function
return cors_after_request(app.make_response(f(*args, **kwargs)))
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1821, in handle_user_exception
reraise(exc_type, exc_value, tb)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/_compat.py", line 39, in reraise
raise value
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1950, in full_dispatch_request
rv = self.dispatch_request()
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/flask/app.py", line 1936, in dispatch_request
return self.view_functions[rule.endpoint](**req.view_args)
File "/home/jasondunn/projects/audioconverter/back/api/converter.py", line 20, in convert_mp4
video_clip = VideoFileClip(video_file)
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/moviepy/video/io/VideoFileClip.py", line 88, in __init__
self.reader = FFMPEG_VideoReader(filename, pix_fmt=pix_fmt,
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/moviepy/video/io/ffmpeg_reader.py", line 35, in __init__
infos = ffmpeg_parse_infos(filename, print_infos, check_duration,
File "/home/jasondunn/projects/audioconverter/.venv/lib/python3.8/site-packages/moviepy/video/io/ffmpeg_reader.py", line 270, in ffmpeg_parse_infos
raise IOError(("MoviePy error: the file %s could not be found!\n"
OSError: MoviePy error: the file /temp/guitar.mp4 could not be found!
Please check that you entered the correct path.
提前感谢您接受 look/future 的建议。 Stack Overflow 上的第一位官方 post :)
我认为问题在于您如何使用 file = request.files['mp3'].filename
。
分配给 file
的值不是指向上传文件的指针。它只是文件的名称,一个字符串。只是 request.files['mp3']
是 werkzeug.datastructures.FileStorage
class 记录的实例 here。
您将该字符串传递给的库将其解释为它们应该打开的文件的路径。
由于您没有将文件保存到任何地方,他们的图书馆找不到任何东西。
我不熟悉您正在使用的库,但他们可能有办法直接将内存中的文件数据发送给他们,而无需保存文件然后让他们再次打开它。
如果没有,那么您可能希望将文件保存到某个临时位置,然后打开库并读取文件。
看起来 python 找不到 guitar.mp4
:(
看来您需要在处理之前将文件内容保存在磁盘上。查看docs for MoviePy
需要将文件名或绝对路径传入VideoFileClip
构造函数,此对象会在实例化后打开磁盘上的文件并进行处理。
在请求中保存文件应该很简单。下面的代码应该能够处理这个
file.save(os.path.join("/path/to/some/dir", filename))
现在您可以为文件提供 VideoFileClip
正确的 URI。
video_clip = VideoFileClip(os.path.join("/path/to/some/dir", filename))
这就是我要为 convert_mp4
编写的内容,尽管它没有经过测试。
@convert.route('', methods=["POST"])
def convert_mp4():
if request.files.get("mp3"):
# clean the filename
safe_filename = secure_filename(request.files["mp3"].filename)
# save file to some directory on disk
request.files["mp3"].save(os.path.join("/path/to/some/dir", safe_filename))
video_clip = VideoFileClip(os.path.join("/path/to/some/dir", safe_filename))
audio_clip = video_clip.audio # convert to audio
# you may need to change the name or save to a different directory
audio_clip.write_audiofile(os.path.join("/path/to/some/dir", f"{safe_filename}.mp3"))
# close resources, maybe use a context manager for better readability
video_clip.close()
audio_clip.close()
# responds with data from a specific file
send_from_directory("/path/to/some/dir", f"{safe_filename}.mp3")
else:
return jsonify(error="File 'mp3' does not exist!")
每当你通过 flask 将数据保存到磁盘时,你应该使用 werkzeug 项目内置到 flask 中的 secure_filename
。此函数将清除输入名称,因此攻击者无法创建恶意文件名。
我建议甚至更进一步,也许创建 2 个端点。一个用于提交数据进行处理,第二个用于检索数据。这可以使您的请求保持快速并允许 flask 同时处理其他请求(但是您将需要一些后台进程来处理转换)。
2021 年 4 月 30 日更新
我知道我们在 Discord 上解决了这个问题,但我想记录解决方案。
您的 MP4 数据未使用 save
方法保存到磁盘(参见 this)。你可以查看上面实现这个的代码。
完成后,我们现在知道此数据在哪里,并且可以使用已知文件路径实例化 VideoFileClip
对象,这将允许进行转换,然后您需要保存转换后的文件MP3 文件位于文件系统中的某个位置。
将 MP3 保存到磁盘后,您可以使用 flask send_from_directory
函数在您的响应中发回数据。此响应不能包含 JSON 内容,因为内容类型已根据 MP3 文件内容设置为 audio/mpeg
。