ขอ URL อัปโหลดไฟล์ — POST /presigned-url

มีไฟล์อยู่ในเครื่อง ไม่มี URL สาธารณะ? ใช้ endpoint นี้ขอ ลิงก์อัปโหลดชั่วคราว (presigned URL) ก่อน — ระบบจะตอบกลับ upload_url สำหรับ PUT ไฟล์ขึ้นไป และ source_url สำหรับนำไปใช้ส่งงานถอดเสียงได้ทันที

POST https://api.lomasub.ai/presigned-url

ขั้นตอนการใช้งานมี 3 จังหวะ: ขอลิงก์ → PUT ไฟล์ → ส่งงานด้วย source_url

Headers

Header ค่า จำเป็น
Authorization Bearer <API_KEY> ต้องระบุ
Content-Type application/json ต้องระบุ

Request Body

personal key และ session ต้องระบุ size_bytes เป็นขนาดไฟล์ที่จะอัปโหลดจริง shared secret ภายในยังส่ง {} ได้ แต่แนะนำให้ระบุขนาด, filename และ content_type เสมอ

ฟิลด์ ชนิด จำเป็น คำอธิบาย
filename string — ชื่อไฟล์ต้นทาง — ระบบใช้เฉพาะนามสกุล: นามสกุลที่ตรงกับ ^[A-Za-z0-9]{1,10}$ จะถูกแปลงเป็นตัวพิมพ์เล็กแล้วต่อท้าย key สุ่ม 12 ตัวอักษร นามสกุลอื่นจะไม่มีนามสกุลเลย
content_type string — MIME type ของไฟล์ เช่น audio/mpeg — ค่าเริ่มต้นคือ application/octet-stream ค่านี้ฝังอยู่ในลายเซ็นและถูกส่งกลับใน headers จึงต้องใช้ค่าเดียวกันนี้ตอน PUT ไฟล์ สตริงว่างตอบ 422
duration_seconds number ≥ 0 — ความยาวสื่อ (วินาที) ตรวจโควตาล่วงหน้าของ personal key และ session ไม่ถูกเก็บ และไม่มีผลกับ shared secret ภายใน — ให้ส่งอีกครั้งตอน /new-transcribe ซึ่งเป็นที่ที่ค่านี้ถูกบันทึก
size_bytes integer > 0 ผู้ใช้ ขนาดไฟล์เสียงจริงเป็น bytes — เกิน tier ตอบ 413; ค่านี้ฝังในลายเซ็น Content-Length จึงอัปโหลดจำนวน bytes อื่นไม่ได้

ตัวอย่าง Request

curl -X POST "https://api.lomasub.ai/presigned-url" \
  -H "Authorization: Bearer $LOMA_API_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "filename": "audio.mp3",
    "content_type": "audio/mpeg",
    "size_bytes": 123456
  }'

Response — 200 OK

{
  "method": "PUT",
  "upload_url": "https://lomafastsrt.sgp1.digitaloceanspaces.com/loma-fastsrt-results/tmpupload/aK3mZ9qLx2Wd.mp3?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Expires=86400&...",
  "headers": {
    "Content-Type": "audio/mpeg",
    "x-amz-acl": "public-read"
  },
  "object_key": "loma-fastsrt-results/tmpupload/aK3mZ9qLx2Wd.mp3",
  "source_url": "https://lomafastsrt.sgp1.digitaloceanspaces.com/loma-fastsrt-results/tmpupload/aK3mZ9qLx2Wd.mp3",
  "expires_in_seconds": 86400
}
ฟิลด์ ชนิด คำอธิบาย
method string HTTP method ที่ต้องใช้อัปโหลด — เป็น PUT เสมอ
upload_url string (URL) ลิงก์อัปโหลดชั่วคราว ใช้ PUT ตัวไฟล์ขึ้นไปโดยตรง
headers object Headers ที่ต้องแนบตอน PUT ให้ครบทุกตัว (เช่น Content-Type, x-amz-acl) มิฉะนั้นลายเซ็นไม่ผ่านและถูกปฏิเสธ
object_key string ตำแหน่งไฟล์ในระบบจัดเก็บ ให้ไว้เพื่อทราบเท่านั้น ไม่ต้องส่งกลับ — production เก็บผลลัพธ์ไว้ใต้ prefix ใน Space จึงมีชื่อ bucket เป็น path ส่วนแรก ให้ถือว่าเป็นค่าทึบ (opaque)
source_url string (URL) URL สาธารณะสำหรับอ่านไฟล์เดียวกัน — ส่งต่อโดยไม่แก้ไขเป็น source_url ใน POST /new-transcribe หลัง PUT เสร็จ
expires_in_seconds int อายุของ upload_url (PRESIGNED_URL_TTL_SECONDS ค่าเริ่มต้น 86400 วินาที = 24 ชั่วโมง)

ขั้นตอนที่ 2 — PUT ไฟล์ขึ้น upload_url

แนบ headers ทุกตัวจาก response แล้ว PUT ตัวไฟล์เป็น request body

จำนวน bytes ต้องตรงกับ size_bytes ที่ขอลายเซ็น browser ใช้ Blob.size และส่ง Content-Length ให้อัตโนมัติ — อย่าตั้ง header นี้เองใน JavaScript และห้ามใช้ multipart แทน body ไฟล์

curl -X PUT "<upload_url>" \
  -H "Content-Type: audio/mpeg" \
  -H "x-amz-acl: public-read" \
  --data-binary @audio.mp3

การ PUT ไปยัง upload_url ไม่ต้องใช้ Authorization header — สิทธิ์ฝังอยู่ในลายเซ็นของ URL แล้ว

ขั้นตอนที่ 3 — ส่งงานถอดเสียงด้วย source_url

curl -X POST "https://api.lomasub.ai/new-transcribe" \
  -H "Authorization: Bearer $LOMA_API_SECRET_KEY" \
  -H "Content-Type: application/json" \
  -d '{
    "source_url": "<source_url จาก response>",
    "language": "th"
  }'

ตัวอย่างสคริปต์ Python แบบครบวงจร

อัปโหลดไฟล์ในเครื่องแล้วส่งงานถอดเสียงต่อทันที (ใช้เฉพาะ standard library)

import json
import os
import urllib.request

API_BASE = "https://api.lomasub.ai"
API_KEY = os.environ["LOMA_API_SECRET_KEY"]
LOCAL_FILE = "audio.mp3"

def call_api(path, payload):
    req = urllib.request.Request(
        f"{API_BASE}{path}",
        data=json.dumps(payload).encode(),
        method="POST",
        headers={
            "Authorization": f"Bearer {API_KEY}",
            "Content-Type": "application/json",
        },
    )
    with urllib.request.urlopen(req) as resp:
        return json.loads(resp.read())

# 1) ขอลิงก์อัปโหลด
signed = call_api("/presigned-url", {
    "filename": os.path.basename(LOCAL_FILE),
    "content_type": "audio/mpeg",
    "size_bytes": os.path.getsize(LOCAL_FILE),
})

# 2) PUT ไฟล์ขึ้นไปพร้อม headers ที่กำหนด
with open(LOCAL_FILE, "rb") as f:
    put_req = urllib.request.Request(
        signed["upload_url"], data=f.read(), method="PUT",
        headers=signed["headers"],
    )
    urllib.request.urlopen(put_req)

# 3) ส่งงานถอดเสียงด้วย source_url ที่ได้
job = call_api("/new-transcribe", {
    "source_url": signed["source_url"],
    "language": "th",
})
print("job created:", job["job_id"])

เคล็ดลับ: ไฟล์วิดีโอหรือไฟล์เสียงขนาดใหญ่ ควรแปลงเป็น MP3 โมโน 16 kHz bitrate ต่ำ (เช่น 32 kbps) ก่อนอัปโหลด — คุณภาพการถอดเสียงไม่ต่างกัน แต่อัปโหลดเร็วขึ้นมาก เช่น ffmpeg -i video.mp4 -vn -ac 1 -ar 16000 -b:a 32k audio.mp3

ข้อผิดพลาดที่อาจพบ

สถานะ สาเหตุ
401 Unauthorized ไม่มีหรือ API key ไม่ถูกต้อง (ตอนเรียก /presigned-url)
403 Forbidden (ตอน PUT) แนบ headers ไม่ครบ/ไม่ตรงกับที่ระบบกำหนด หรือ upload_url หมดอายุ
422 Unprocessable Entity รูปแบบ body ไม่ถูกต้อง เช่น content_type เป็นสตริงว่าง

results matching ""

    No results matching ""