[Python] Facebook Reels Upload always failing

Discussão em 'Python' iniciado por Stack, Junho 20, 2025.

  1. Stack

    Stack Membro Participativo

    I'm trying to upload Reels through Facebook Graph API. The video is created with the following ffmpeg command.

    cmd = [
    'ffmpeg',
    '-i', video_path,
    '-i', voice_path,
    '-i', music_path,

    '-filter_complex',
    '[1:a]loudnorm=I=-16:LRA=11:TP=-1.5,adelay=0|0[a1];' +
    '[2:a]volume=0.2,afade=t=in:ss=0:d=0.02,afade=t=out:st=28:d=0.03[a2];' +
    '[a1][a2]amix=inputs=2:duration=first:dropout_transition=0[aout]',

    '-map', '0:v:0',
    '-map', '[aout]',

    '-vf',
    f"subtitles='{str(ass_path)}',format=yuv420p,scale=1080:1920:force_original_aspect_ratio=decrease,pad=1080:1920:(ow-iw)/2:(oh-ih)/2,setsar=1", # Incrustation des sous-titres

    '-r', '30',
    '-g', '60',
    '-keyint_min', '60',
    '-sc_threshold', '0',
    '-x264opts', 'no-scenecut',

    '-c:v', 'libx264',
    '-profile:v', 'baseline',
    '-level', '4.1',
    '-pix_fmt', 'yuv420p',
    '-color_range', 'tv',
    '-colorspace', 'bt709',

    '-b:v', '9500k',
    '-maxrate', '9500k',
    '-bufsize', '19000k',

    '-c:a', 'aac',
    '-b:a', '192k',
    '-ac', '2',
    '-ar', '48000',

    '-movflags', '+faststart',
    '-video_track_timescale', '15360',
    '-max_muxing_queue_size', '9999',

    '-y', self.output_video_path if self.output_video_path else f'{parts[0]}.subtitled.{parts[1]}'
    ]

    subprocess.run(cmd, check=True)


    Here is the class method I use to publish:

    import requests, os, time
    from datetime import datetime, timedelta
    from moviepy.editor import VideoFileClip

    def post_reel(
    self,
    page_id: str,
    page_access_token: str,
    video_file_path: str,
    video_description: str,
    tags: list = None, # type: ignore
    publish_now: bool = True
    ):
    def extract_first_frame(video_path: str, output_image_path: str, time_in_seconds: float = 1):
    """
    Extrait une frame à time_in_seconds et la sauvegarde comme miniature.
    """
    try:
    clip = VideoFileClip(video_path)
    clip.save_frame(output_image_path, t=time_in_seconds)
    print(f"[THUMBNAIL] Frame at {time_in_seconds}s saved to {output_image_path}")
    return output_image_path
    except Exception as e:
    print(f"[ERROR] Could not extract thumbnail: {str(e)}")
    return None

    def wait_for_video_ready(video_id, page_access_token, timeout=300, poll_interval=10):
    """
    Attends que la vidéo soit complètement traitée et publiée.
    """
    status_url = f"{self.BASE_API_URL}/{video_id}"
    params = {
    "access_token": page_access_token,
    "fields": "status"
    }

    start = time.time()
    while time.time() - start < timeout:
    try:
    r = requests.get(url=status_url, params=params)
    r.raise_for_status()
    status = r.json().get("status", {})
    processing = status.get("processing_phase", {}).get("status")
    publishing = status.get("publishing_phase", {}).get("status")
    video_status = status.get("video_status")

    print(f"[WAIT] video_status={video_status}, processing={processing}, publishing={publishing}")

    if processing == "complete" and publishing == "complete":
    print("[READY] Reel processed and published")
    return True
    elif processing == "error":
    print(r.json())

    except Exception as e:
    print(f"[ERROR] during polling: {e}")

    time.sleep(poll_interval)

    print("[TIMEOUT] Video did not finish processing in time.")
    return False

    try:
    # Step 1: Initialize upload
    init_url = f"{self.BASE_API_URL}/{page_id}/video_reels"
    init_params = {"upload_phase": "start"}
    init_payload = {'access_token': page_access_token}

    r = requests.post(url=init_url, data=init_payload, params=init_params)
    r.raise_for_status()
    response = r.json()
    video_id = response["video_id"]
    upload_url = response["upload_url"]
    print(f"[INIT OK] Video ID: {video_id}")

    # Step 2: Upload video
    file_size = os.path.getsize(video_file_path)
    headers = {
    'Authorization': f"OAuth {page_access_token}",
    'offset': "0",
    'file_size': str(file_size),
    }

    with open(video_file_path, 'rb') as f:
    files = {'source': f}
    r = requests.post(url=upload_url, data=files, headers=headers)
    r.raise_for_status()
    upload_response = r.json()

    if not upload_response.get("success"):
    print("[ERROR] Upload failed.")
    return None
    print(f"[UPLOAD OK]")

    # Step 3: Check video status
    status_check_url = f'{self.BASE_API_URL}/{video_id}'
    check_params = {
    "access_token": page_access_token,
    "fields": "status"
    }
    r = requests.get(url=status_check_url, params=check_params)
    r.raise_for_status()
    print(f"[STATUS CHECK] {r.json()}")

    # Step 4: Finalize video
    finalize_params = {
    "video_id": video_id,
    "upload_phase": "finish",
    "published": "true",
    "access_token": page_access_token,
    "video_state": "PUBLISHED" if publish_now else "SCHEDULED",
    "title": video_description,
    "description": video_description
    }

    if not publish_now:
    finalize_params["scheduled_publish_time"] = int((datetime.now() + timedelta(days=1)).timestamp())

    if tags:
    finalize_params["tags"] = ",".join(tags)

    r = requests.post(url=init_url, params=finalize_params, headers=headers)
    r.raise_for_status()
    finalize_response = r.json()
    post_id = finalize_response.get("post_id")
    print(f"[FINALIZE OK] Post ID: {post_id}")

    # WAIT UNTIL PUBLISHED
    if not wait_for_video_ready(video_id, page_access_token):
    print("[ERROR] Reel processing timeout or failure")
    return None

    # Step 5: Extract and upload thumbnail
    thumbnail_path = f"temp_thumb_{video_id}.jpg"
    if extract_first_frame(video_file_path, thumbnail_path):
    thumb_url = f"{self.BASE_API_URL}/{video_id}/thumbnails"
    with open(thumbnail_path, 'rb') as img:
    files = {'source': img}
    thumb_payload = {'access_token': page_access_token}
    r = requests.post(url=thumb_url, files=files, data=thumb_payload)
    r.raise_for_status()
    print("[THUMBNAIL UPLOADED]")
    # Clean up temp file
    os.remove(thumbnail_path)
    print("[THUMBNAIL CLEANED UP]")

    return post_id

    except Exception as e:
    print(f"[ERROR] {str(e)}")
    return None


    Here are the logs I get :

    • [INIT OK] Video ID: 1020853163558419
    • [UPLOAD OK]
    • [STATUS CHECK]

    {
    "status": {
    "video_status": "upload_complete",
    "uploading_phase": {
    "status": "complete",
    "bytes_transferred": 37780189
    },
    "processing_phase": {
    "status": "not_started"
    },
    "publishing_phase": {
    "status": "not_started"
    },
    "copyright_check_status": {
    "status": "in_progress"
    }
    },
    "id": "1020853163558419"
    }

    • [FINALIZE OK] Post ID: 122162302376476425
    • [WAIT] video_status=upload_complete, processing=not_started, publishing=not_started
    • [WAIT] video_status=error, processing=error, publishing=not_started

    {
    "status": {
    "video_status": "error",
    "uploading_phase": {
    "status": "complete",
    "bytes_transferred": 37780189
    },
    "processing_phase": {
    "status": "error",
    "errors": [
    {
    "code": 1363008,
    "message": "Video Creation failed, please try again."
    }
    ]
    },
    "publishing_phase": {
    "status": "not_started"
    },
    "copyright_check_status": {
    "status": "in_progress"
    }
    },
    "id": "1020853163558419"
    }


    It seems the error code 1363008 is related to the video properties format but even after following Facebook Reels video format recommandations, I can't make it work.

    Can you help me with this please ?

    I failed getting usefull help with ChatGPT , and thanks in advance for anyone who answers or comments my question.

    Continue reading...

Compartilhe esta Página