Ошибка 422 Unprocessible Entity при отправке списка данных формы через документы Swagger UI с использованием FastAPIPython

Программы на Python
Ответить Пред. темаСлед. тема
Anonymous
 Ошибка 422 Unprocessible Entity при отправке списка данных формы через документы Swagger UI с использованием FastAPI

Сообщение Anonymous »

Я создал API с использованием FastAPI для перекодирования видеофайлов, например с адаптивным битрейтом YouTube. В настоящее время я пытаюсь установить значения разрешения для каждого файла. Но всякий раз, когда я передаю несколько разрешений в виде списка данных формы через автодокументацию пользовательского интерфейса Swagger, я получаю ошибку 422 необрабатываемого объекта.
Вот мой код:

Код: Выделить всё

async def transcode_video(input_path, output_folder, res, unique_id, total_files, pbar):
# Use asyncio for command execution with progress bar
output_path = os.path.join(output_folder, f"{res}p.m3u8")

# Calculate the target size
target_size = calculate_target_size(input_path)

cmd_duration = f"ffprobe -v error -show_entries format=duration -of default=noprint_wrappers=1:nokey=1 {input_path}"
total_duration = float(subprocess.check_output(cmd_duration, shell=True, text=True).strip())

cmd = (
f"ffmpeg -i {input_path} -vf scale=-2:{res} -c:a aac -b:a 128k "
f"-g 50 -hls_time 1 -hls_list_size 0 "
f"-crf 23 -b:v 100k -fs {target_size} "
f"-hls_segment_filename \"{output_path.replace('.m3u8', '_%03d.ts')}\" "
f"{output_path}"
)

process = await asyncio.create_subprocess_shell(
cmd,
stdout=asyncio.subprocess.PIPE,
stderr=asyncio.subprocess.PIPE
)

while True:
line = await process.stderr.readline()
if not line:
break
line = line.decode().strip()
if "time="  in line:
# Extracting the time progress from FFmpeg output
time_str = line.split("time=")[1].split()[0]
current_time = sum(x * float(t) for x, t in zip([3600, 60, 1], time_str.split(":")))
progress = (current_time / total_duration) * 100
pbar.update(progress - pbar.n)

# Wait for the transcoding process to complete
await process.wait()

if process.returncode != 0:
raise HTTPException(status_code=500, detail="Video transcoding failed.")
pbar.close()

# Increment the total number of transcoded files
total_files[0] += 1

@app.post("/transcode/")
async def transcode_video_endpoint(files: List[UploadFile] = File(...), resolutions: List[int] = None):
# Counters for transcoded videos
total_files = [0]

# Iterate over each file
for file in files:
# Check if the file is a valid video file based on its extension
valid_video_extensions = {".mp4", ".avi", ".mkv", ".mov", ".wmv", ".flv"}
if not any(file.filename.lower().endswith(ext) for ext in valid_video_extensions):
print(f"Skipping non-video file: {file.filename}")
continue

# Assign a unique ID for each file
unique_id = str(uuid.uuid4())

# Log the filename and unique ID
print(f"Processing file: {file.filename} with unique ID: {unique_id}")

# Create a folder for the unique ID
unique_id_folder = os.path.join(OUTPUT_FOLDER, unique_id)
Path(unique_id_folder).mkdir(parents=True, exist_ok=True)

# Save the uploaded file
input_path = os.path.join(UPLOAD_FOLDER, file.filename)
with open(input_path, "wb") as video_file:
video_file.write(file.file.read())

# Check if the file is a valid video file using ffprobe
try:
subprocess.run(
["ffprobe", "-v", "error", "-select_streams", "v:0", "-show_entries", "stream=codec_type", "-of", "csv=p=0", input_path],
check=True, capture_output=True
)
except subprocess.CalledProcessError:
print(f"Skipping non-video file: {file.filename}")
continue

# Determine the resolutions to transcode based on the provided or default resolution
resolutions_to_transcode = [res for res in [240, 360, 480, 720] if resolutions is None or res in resolutions]

# If resolutions is not exactly 360, 480, 720, or 1080, transcode to the nearest lower resolution
if resolutions is not None:
resolutions_to_transcode = [get_closest_lower_resolution(res) for res in resolutions]

# Transcode the video into the specified resolutions
for res in resolutions_to_transcode:
output_folder = os.path.join(unique_id_folder, f"{res}p")
Path(output_folder).mkdir(parents=True, exist_ok=True)

# Call the transcode_video function with tqdm progress bar
with tqdm(total=100, desc=f"Transcoding {res}p", position=0, leave=True) as pbar:
await transcode_video(input_path, output_folder, res, unique_id, total_files, pbar)

# Create index.m3u8 file after transcoding all resolutions
create_index_m3u8(unique_id, resolutions_to_transcode)

return JSONResponse(content={"message": f"{total_files[0]} videos transcoded."})
Если я укажу только одно значение разрешения, оно будет работать нормально. Но если я предоставлю список разрешений для всех загруженных видео, я получу ошибку 422, как показано ниже:

Код: Выделить всё

Code    Details
422
Error: Unprocessable Entity

Response body
Download
{
"detail": [
{
"loc": [
"body",
"resolutions",
0
],
"msg": "value is not a valid integer",
"type": "type_error.integer"
}
]
}
Я использую Python 3.8.18. Не могли бы вы мне помочь, пожалуйста? Я пробовал использовать list, объект, но всегда получал ошибку. Мой формат ввода показан ниже:
Изображение


Подробнее здесь: https://stackoverflow.com/questions/778 ... swagger-ui
Реклама
Ответить Пред. темаСлед. тема

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

  • Похожие темы
    Ответы
    Просмотры
    Последнее сообщение

Вернуться в «Python»