apoastron commited on
Commit
d6dd38f
·
verified ·
1 Parent(s): 51b5f61

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +27 -27
app.py CHANGED
@@ -4,47 +4,41 @@ import subprocess
4
  import io
5
  import os
6
  from typing import Optional
 
7
 
8
- app = FastAPI(title="FFmpeg API for n8n")
9
-
10
- @app.get("/")
11
- async def health_check():
12
- return {"status": "online", "service": "FFmpeg Image Processor"}
13
 
14
  @app.post("/process")
15
  async def process_image(
16
  file: Optional[UploadFile] = File(None),
17
  url: Optional[str] = Form(None),
18
- options: Optional[str] = Form("-vf scale=800:-1") # 默认缩小到800宽
 
19
  ):
20
- """
21
- 支持两种输入方式:
22
- 1. file: 上传二进制图片文件
23
- 2. url: 远程图片地址
24
- """
25
  input_source = ""
26
  input_data = None
27
 
 
28
  if file:
29
  input_data = await file.read()
30
  input_source = "pipe:0"
 
 
 
31
  elif url:
32
  input_source = url
 
 
 
 
 
33
  else:
34
- raise HTTPException(status_code=400, detail="需提供 file 或 url 参数")
35
 
36
- # 构建命令
37
- # 默认输出为 .jpg 格式,你可以根据需要调整
38
- command = [
39
- 'ffmpeg',
40
- '-i', input_source,
41
- ]
42
-
43
- # 解析 options 参数并加入命令
44
  if options:
45
  command.extend(options.split())
46
-
47
- # 强制输出为图像流
48
  command.extend(['-f', 'image2', 'pipe:1'])
49
 
50
  try:
@@ -54,13 +48,19 @@ async def process_image(
54
  stdout=subprocess.PIPE,
55
  stderr=subprocess.PIPE
56
  )
57
-
58
  out, err = process.communicate(input=input_data)
59
 
60
- if process.returncode != 0:
61
- return {"error": err.decode()}
62
-
63
- return StreamingResponse(io.BytesIO(out), media_type="image/jpeg")
 
 
 
 
 
 
 
64
 
65
  except Exception as e:
66
  raise HTTPException(status_code=500, detail=str(e))
 
4
  import io
5
  import os
6
  from typing import Optional
7
+ from urllib.parse import urlparse
8
 
9
+ app = FastAPI()
 
 
 
 
10
 
11
  @app.post("/process")
12
  async def process_image(
13
  file: Optional[UploadFile] = File(None),
14
  url: Optional[str] = Form(None),
15
+ options: Optional[str] = Form("-q:v 2"),
16
+ filename: Optional[str] = Form(None) # 新增:支持自定义文件名
17
  ):
 
 
 
 
 
18
  input_source = ""
19
  input_data = None
20
 
21
+ # 1. 确定输入源
22
  if file:
23
  input_data = await file.read()
24
  input_source = "pipe:0"
25
+ # 如果没传 filename,则使用上传文件的原始名,但后缀改为 .jpg
26
+ if not filename:
27
+ filename = os.path.splitext(file.filename)[0] + ".jpg"
28
  elif url:
29
  input_source = url
30
+ # 如果没传 filename,从 URL 中解析文件名,后缀改为 .jpg
31
+ if not filename:
32
+ path = urlparse(url).path
33
+ base_name = os.path.basename(path) or "downloaded_image"
34
+ filename = os.path.splitext(base_name)[0] + ".jpg"
35
  else:
36
+ raise HTTPException(status_code=400, detail="Missing source")
37
 
38
+ # 2. 执行 FFmpeg 转换 (PNG -> JPG)
39
+ command = ['ffmpeg', '-i', input_source]
 
 
 
 
 
 
40
  if options:
41
  command.extend(options.split())
 
 
42
  command.extend(['-f', 'image2', 'pipe:1'])
43
 
44
  try:
 
48
  stdout=subprocess.PIPE,
49
  stderr=subprocess.PIPE
50
  )
 
51
  out, err = process.communicate(input=input_data)
52
 
53
+ # 3. 构建响应,添加 Content-Disposition Header
54
+ # 这会让 n8n 和浏览器识别出文件名
55
+ headers = {
56
+ 'Content-Disposition': f'attachment; filename="{filename}"'
57
+ }
58
+
59
+ return StreamingResponse(
60
+ io.BytesIO(out),
61
+ media_type="image/jpeg",
62
+ headers=headers
63
+ )
64
 
65
  except Exception as e:
66
  raise HTTPException(status_code=500, detail=str(e))