跳转至

媒体上传 API

x-api-rs 的 Web 上传能力位于 client.upload。图片和视频共用同一组入口,媒体类别决定上传流程。

Python 快速开始

from x_api_rs.web import Client

client = await Client.create(cookies)

# 从内存上传图片
with open("image.jpg", "rb") as file:
    result = await client.upload.upload_from_bytes(
        data=file.read(),
        category="tweet_image",
    )

# 从文件上传视频;无需也不能传 duration_ms
video = await client.upload.upload_file(
    "video.mp4",
    category="amplify_video",
)

成功结果通过 media_id_string 关联到帖子或私信:

tweet = await client.posts.create_tweet(
    text="带视频的帖子",
    media_ids=[video.media_id_string],
)

Python 接口

upload_from_bytes

from typing import Optional
from x_api_rs.web import ApiResult

class UploadClient:
    async def upload_from_bytes(
        self,
        data: bytes,
        category: str = "tweet_image",
        proxy_url: Optional[str] = None,
        disable_proxy: bool = False,
    ) -> ApiResult: ...

upload_file

from typing import Optional
from x_api_rs.web import ApiResult

class UploadClient:
    async def upload_file(
        self,
        path: str,
        category: str = "tweet_image",
        proxy_url: Optional[str] = None,
        disable_proxy: bool = False,
    ) -> ApiResult: ...

upload_multiple_times

仅用于图片。每次上传会生成不同的媒体数据,以获得多个独立的 media_id_string

result = await client.upload.upload_multiple_times(
    data=image_bytes,
    category="dm_image",
    count=3,
)

set_media_metadata

必须在发帖前调用,用于设置内容警告、AI 生成声明和下载策略:

await client.upload.set_media_metadata(
    media_id=result.media_id_string,
    warnings=["other"],
    ai_generated=True,
    block_grok_edit=True,
    allow_download=False,
)

媒体类别

类别 用途 时长处理
tweet_image 帖子图片 不解析
dm_image 私信图片 不解析
banner_image 头像或横幅图片 不解析
amplify_video 帖子视频 自动解析 MP4
dm_video 私信视频 自动解析 MP4

只有视频类别会自动解析时长。普通 MP4 优先采用最长媒体轨道的时长,缺少有效媒体轨时回退到容器时长;fragmented MP4(fMP4)必须在 mehd 中提供可用的静态总时长。空文件、损坏文件、零时长文件,以及无法可靠确定静态总时长的 fMP4,会在发起上传请求前抛出 InvalidArgumentError

调用方不应自行计算或传递 duration_ms;该值只作为上传协议的内部字段发送。

单次代理覆盖

  • 默认继承创建 Client 时配置的代理。
  • proxy_url="http://host:port":仅本次上传使用指定代理。
  • disable_proxy=True:仅本次上传直连。

proxy_urldisable_proxy=True 同时出现时,以禁用代理为准。

Rust 接口

use x_api_core::web::api::upload::{MediaCategory, UploadService};

let image = std::fs::read("image.jpg")?;
let image_result = client
    .upload()
    .upload_from_bytes(image, MediaCategory::TweetImage, None)
    .await?;

let video = std::fs::read("video.mp4")?;
let video_result = client
    .upload()
    .upload_from_bytes(video, MediaCategory::AmplifyVideo, None)
    .await?;

UploadOptionsduration_ms 仅作为 3.x Rust 源码兼容字段保留,上传流程不再读取它;新代码只需配置处理超时和代理覆盖策略。

返回值与错误

单次上传结果常用字段:

  • success:上传流程是否成功。
  • media_id / media_id_string:后续帖子、私信或用户资料接口使用的媒体 ID。
  • error_msg:协议上传或处理失败信息。
  • processing_info:视频处理状态;图片通常为 None

MP4 结构或时长无效属于参数错误,会抛出 Python InvalidArgumentError;网络、协议 INIT/APPEND/FINALIZE/STATUS 等阶段的失败按现有上传结果或异常语义返回。任何日志和错误都不会包含视频字节或解析器内部细节。