틱톡 초안 자동 업로드 파이썬 구현: init부터 인박스 전송까지 3단계 (2026년 9월 기준)

어제 올린 틱톡 자동 업로드 3가지 경로 비교에서 “앱 심사 없이도 초안(드래프트) 업로드는 가능하다”고 정리했는데, 오늘은 그 경로를 실제로 돌아가는 파이썬 코드로 구현합니다. 영상 파일을 틱톡 앱의 받은편지함(인박스)으로 밀어 넣으면, 크리에이터가 앱에서 커버·제목만 확인하고 게시하는 구조입니다. 전 과정은 init 호출 → 청크 업로드 → 상태 확인, 딱 3단계입니다. 모든 스펙은 2026년 9월 기준 틱톡 공식 개발자 문서로 확인했습니다.

준비물: video.upload 스코프 토큰

틱톡 개발자 포털에서 앱을 만들고 Content Posting API를 추가한 뒤, video.upload 스코프로 사용자 인증(OAuth)을 받아야 합니다. 토큰 발급 엔드포인트는 https://open.tiktokapis.com/v2/oauth/token/이고, 액세스 토큰은 발급 후 24시간, 리프레시 토큰은 365일 유효합니다. 리프레시 시 새 리프레시 토큰이 내려오면 반드시 새것으로 교체해야 합니다. 인증 코드 받는 절차 자체는 표준 OAuth authorization_code 방식이라 이 글에서는 토큰이 이미 있다고 가정합니다.

1단계: 업로드 초기화 (init)

먼저 파일 크기와 청크 구성을 신고하고 업로드 URL을 받습니다. 규칙이 의외로 까다로운데, 청크는 5MB~64MB 사이여야 하고(마지막 청크만 최대 128MB 허용), total_chunk_count는 video_size ÷ chunk_size를 내림한 값이어야 합니다. 나머지 바이트는 마지막 청크에 합쳐 보내는 방식입니다. 64MB 이하 파일이라면 청크 1개로 통째로 보내는 게 가장 안전합니다. init 호출은 사용자 토큰당 분당 6회로 제한됩니다.

import os, requests

ACCESS_TOKEN = "act.xxxx"          # video.upload 스코프 사용자 토큰
VIDEO_PATH = "final_short.mp4"     # 최대 4GB, MP4 권장

video_size = os.path.getsize(VIDEO_PATH)

if video_size <= 64 * 1024 * 1024:
    chunk_size = video_size        # 64MB 이하는 청크 1개가 안전
    total_count = 1
else:
    chunk_size = 10 * 1024 * 1024  # 10MB
    total_count = video_size // chunk_size   # 내림 — 나머지는 마지막 청크에 합침

init = requests.post(
    "https://open.tiktokapis.com/v2/post/publish/inbox/video/init/",
    headers={"Authorization": "Bearer " + ACCESS_TOKEN,
             "Content-Type": "application/json"},
    json={"source_info": {
        "source": "FILE_UPLOAD",
        "video_size": video_size,
        "chunk_size": chunk_size,
        "total_chunk_count": total_count,
    }},
).json()

publish_id = init["data"]["publish_id"]
upload_url = init["data"]["upload_url"]    # 발급 후 1시간만 유효

2단계: 청크 PUT 업로드

받은 upload_url로 청크를 순서대로 PUT 하면 됩니다. 핵심은 Content-Range 헤더 형식(bytes 시작-끝/전체크기)입니다. 중간 청크가 정상 접수되면 206, 마지막 청크까지 끝나면 201이 돌아옵니다. upload_url이 1시간 뒤 만료되니 대용량 파일은 청크 크기를 넉넉히 잡아 시간 안에 끝내야 합니다.

with open(VIDEO_PATH, "rb") as f:
    sent = 0
    for i in range(total_count):
        is_last = (i == total_count - 1)
        size = (video_size - sent) if is_last else chunk_size
        r = requests.put(
            upload_url,
            headers={"Content-Type": "video/mp4",
                     "Content-Length": str(size),
                     "Content-Range": "bytes {}-{}/{}".format(
                         sent, sent + size - 1, video_size)},
            data=f.read(size),
        )
        sent += size
        # 중간 청크 206, 마지막 청크 201이면 정상

3단계: 상태 확인

업로드가 끝나면 publish_id로 처리 상태를 조회합니다. 이 엔드포인트는 분당 30회까지 허용되니 5~10초 간격 폴링이면 충분합니다.

status = requests.post(
    "https://open.tiktokapis.com/v2/post/publish/status/fetch/",
    headers={"Authorization": "Bearer " + ACCESS_TOKEN,
             "Content-Type": "application/json"},
    json={"publish_id": publish_id},
).json()
print(status["data"]["status"])
# PROCESSING_UPLOAD → SEND_TO_USER_INBOX 이면 성공

SEND_TO_USER_INBOX가 뜨면 크리에이터의 틱톡 앱 알림함에 초안이 도착한 상태입니다. 앱에서 열어 편집·게시하면 끝입니다.

주의할 제한 3가지

첫째, 24시간 안에 대기 상태로 둘 수 있는 초안은 최대 5개입니다. 앱에서 게시(소진)하지 않고 쌓아두면 6번째 업로드가 막힙니다. 둘째, 영상 스펙은 최대 4GB·10분, 해상도 360~4096px, 23~60FPS 범위여야 합니다. 셋째, 심사(audit) 전 앱은 어제 글에서 정리한 공통 제한(비공개 계정, 24시간 5명 노출)이 그대로 적용되니, 본계정 운영 자동화로 쓰려면 결국 심사를 통과해야 합니다. 그 전까지는 “업로드·검수까지 자동, 게시 버튼만 수동”인 반자동 파이프라인으로 쓰는 게 현실적입니다.

다음 행동

이 코드의 앞단, 즉 영상을 자동으로 만들어 final_short.mp4까지 뽑는 과정이 궁금하다면 얼굴 없는 채널 자동화 파이프라인 글을 참고하세요. 생성→편집→업로드 초안까지 한 줄로 이어지면, 하루 1개 업로드 루틴에서 사람 손이 가는 건 게시 버튼 하나만 남습니다.

Leave a Comment