云修智能API

该文档指引接入美图云修智能 API 服务,需先申请接口权限后方可接入使用,接口的接入通过 HTTP 异步调用的形式接入。美图云修智能 API 提供的服务均为异步接口(什么是异步接口?),目前提供了 2 种形式来获取结果:消息通知回调、结果查询

接入地址:https://openapi.meitu.com

1. 公共参数

权限

使用前需申请 AccessKey 和 SecretKey,并按照开放平台接口签名完成请求签名。

请求头

名称类型必填描述
Content-Typestring是固定值:"application/json"

请求方法

POST

2. 接口列表

1. 预设 ID 接入

请求地址: https://openapi.meitu.com/yunxiu_api/openapi/realphotolocal_async

请求方法: POST

请求参数(Body参数):

名称类型是否必填描述示例值
media_codestring是预设 ID(什么是预设ID?)MTyunxiu163aa58942
media_datastring是原图URL地址要求
repost_urlstring否结果回调地址,接入侧提供https://httpbin.org/

请求示例:

{
    "media_code": "MTyunxiu163aa58942",
    "media_data": "https://mt-mtyunxiu-static.oss-cn-beijing.aliyuncs.com/material/1680141903114.jpg",
    "repost_url": "https://httpbin.org/"
}

响应参数:

名称类型是否必填描述示例值
codeint是业务状态码0
datastruct是结果数据{ "msg_id": "8547e55f-9492-40a9-ba0d-7041b717ee5a" }
messagestring否提示信息success
request_idstring是请求ID30c2194d-049b-4f69-95f8-0e9b440df2eb

响应示例:

{
    "code": 0,
    "data": {
        "msg_id": "8547e55f-9492-40a9-ba0d-7041b717ee5a"
    },
    "message": "",
    "request_id": "30c2194d-049b-4f69-95f8-0e9b440df2eb"
}

2.2 原始参数接入

请求地址: https://openapi.meitu.com/yunxiu_api/openapi/super_realphotolocal_async

请求方法: POST

请求参数(Body参数):

名称类型是否必填描述示例值
parameterstruct是处理参数查看
media_info_listarray是原图图片地址查看
extrastruct否其他信息{}
  • media_info_list 参数结构
名称类型是否必填描述示例值
media_datastring是原图图片地址(不支持base64,只支持url)https://mt-mtyunxiu-static.oss-cn-beijing.aliyuncs.com/material/1680141903114.jpg
media_extrastruct否资源描述额外信息{}
media_profilesstruct是图片地址的资源描述固定值{"media_data_type":"url","media_data_describe": "src"}
[
    {
        "media_data": "https://mt-mtyunxiu-static.oss-cn-beijing.aliyuncs.com/material/1680141903114.jpg",
        "media_extra": {},
        "media_profiles": {
            "media_data_type": "url",
            "media_data_describe": "src"
        }
    }
]
  • parameter 参数结构:
名称类型是否必填描述示例值
all_paramsstruct是图片处理参数查看
repost_urlstring否结果回调地址,接入侧提供https://httpbin.org/
rsp_mask_versionint是-固定值500
preview_sizeint是-固定值3000
people_typearray是自定义年龄性别属性的数组顺序查看
outputstruct是输出结构查看
  • all_params 参数结构:
客户端模块客户端参数名算法参数类型是否必填范围示例值
AI 画质优化暗图矫正bright_low_dark_image_flagint是0、1默认值 0
AI 画质优化背景锐化highpass_background_coefint是0~100默认值 0
AI 画质优化人像锐化highpass_body_coefint是0~100默认值 0
AI 画质优化颗粒感film_granularityint是0~100默认值 0
AI 智能调色纯色背景祛瑕疵background_detain_alphaint是0~100默认值 0
AI 智能调色智能白平衡_常规背景awb_norm_coefint是0~100默认值 0
AI 智能调色智能白平衡_纯色背景awb_pure_coefint是0~100默认值 0
AI 智能调色智能曝光_常规背景exposure_norm_coefint是0~100默认值 0
AI 智能调色智能曝光_纯色背景exposure_pure_coefint是0~100默认值 0
AI 智能调色智能去雾dehaze_coefint是0~100默认值 0
AI智能调色背景增强radioint是0~100默认值 0
AI智能调色智能曝光开关exposure_flagint是0、1默认值 0
HSL饱和度_橙色hsl_sat_orangeint是-100~100默认值 0
HSL饱和度_红色hsl_sat_redint是-100~100默认值 0
HSL饱和度_黄色hsl_sat_yellowint是-100~100默认值 0
HSL饱和度_蓝色hsl_sat_blueint是-100~100默认值 0
HSL饱和度_绿色hsl_sat_greenint是-100~100默认值 0
HSL饱和度_品红hsl_sat_magentaint是-100~100默认值 0
HSL饱和度_浅绿hsl_sat_aquaint是-100~100默认值 0
HSL饱和度_紫罗兰hsl_sat_violetint是-100~100默认值 0
HSL明亮度_橙色hsl_luma_orangeint是-100~100默认值 0
HSL明亮度_红色hsl_luma_redint是-100~100默认值 0
HSL明亮度_黄色hsl_luma_yellowint是-100~100默认值 0
HSL明亮度_蓝色hsl_luma_blueint是-100~100默认值 0
HSL明亮度_绿色hsl_luma_greenint是-100~100默认值 0
HSL明亮度_品红hsl_luma_magentaint是-100~100默认值 0
HSL明亮度_浅绿hsl_luma_aquaint是-100~100默认值 0
HSL明亮度_紫罗兰hsl_luma_violetint是-100~100默认值 0
HSL色相_橙色hsl_hue_orangeint是-100~100默认值 0
HSL色相_红色hsl_hue_redint是-100~100默认值 0
HSL色相_黄色hsl_hue_yellowint是-100~100默认值 0
HSL色相_品红hsl_hue_magentaint是-100~100默认值 0
HSL色相_紫罗兰hsl_hue_violetint是-100~100默认值 0
HSL色相_蓝色hsl_hue_blueint是-100~100默认值 0
HSL色相_绿色hsl_hue_greenint是-100~100默认值 0
HSL色相_浅绿hsl_hue_aquaint是-100~100默认值 0
基础调整饱和度saturabilityint是-100~100默认值 0
基础调整对比度constrastint是-100~100默认值 0
基础调整高光highlightint是-100~100默认值 0
基础调整白色whitenessint是-100~100默认值 0
基础调整黑色blacknessint是-100~100默认值 0
基础调整色温temperatureint是-100~100默认值 0
基础调整自然饱和度vibranceint是-100~100默认值 0
基础调整曝光exposureint是-500~500默认值 0
基础调整清晰度sharpnessint是-100~100默认值 0
基础调整色调hueint是-100~100默认值 0
基础调整阴影shadowint是-100~100默认值 0
脸部优化AI美颜face_beauty_alphaarray是0~100默认值 0
脸部优化AI修复face_restore_alphaarray是0~100默认值 0
脸部优化祛斑祛痘_脸部fleck_clean_flagarray是0、1默认值 0
脸部优化祛唇纹lip_remove_alphaarray是0~100默认值 0
脸部优化祛法令纹wrinkle_nasolabial_removal_alphaarray是0~100默认值 0
脸部优化祛黑头/脂肪粒black_head_clean_flagarray是0、1默认值 0
脸部优化祛黑眼圈remove_poucharray是0~100默认值 0
脸部优化祛颈纹wrinkle_neck_removal_alphaarray是0~100默认值 0
脸部优化祛面颊纹wrinkle_cheek_removal_alphaarray是0~100默认值 0
脸部优化祛双下巴(旧版)double_chinarray是0、1默认值 0
脸部优化祛双下巴(新版)double_chin_alphaarray是0~100默认值 0
脸部优化祛抬头纹wrinkle_forehead_removal_alphaarray是0~100默认值 0
脸部优化祛眼周纹wrinkle_periorbital_removal_alphaarray是0~100默认值 0
脸部优化祛油光shiny_clean_alphaarray是0~100默认值 0
脸部优化祛痣_脸部nevus_removal_flagarray是0、1默认值 0
脸型调整缩头ai_shrink_headarray是0~100默认值 0
脸型调整额头face_foreheadarray是-100~100默认值 0
脸型调整中庭middle_half_of_facearray是-100~100默认值 0
脸型调整下庭bottom_half_of_facearray是-100~100默认值 0
脸型调整人中philtrum_warparray是-100~100默认值 0
脸型调整脸宽narrow_facearray是大人-200~100,儿童-100~100默认值 0
脸型调整脸部轮廓平滑facial_contourarray是0~100默认值 0
脸型调整颧骨_左cheekbone_leftarray是-100~100默认值 0
脸型调整颧骨_右cheekbone_rightarray是-100~100默认值 0
脸型调整太阳穴_左temple_leftarray是-100~100默认值 0
脸型调整太阳穴_右temple_rightarray是-100~100默认值 0
脸型调整下颌_左mandible_leftarray是-100~100默认值 0
脸型调整下颌_右mandible_rightarray是-100~100默认值 0
脸型调整下巴高度jaw_transarray是-100~100默认值 0
脸型调整下巴宽度face_transarray是-100~100默认值 0
脸型调整对称液化开关(仅适用于1-2人无遮挡的半身照)run_symmetry_listarray是0、1默认值 0
脸型调整五官对称face_symmetryarray是0~100默认值 0
脸型调整上半身对称body_symmetryarray是0~100默认值 0
脸型调整3D塑颜-上下threed_up_downarray是-100~100默认值 0
脸型调整3D塑颜-左右threed_left_rightarray是-100~100默认值 0
滤镜滤镜filterstruct是| 查看
肤色调整智能肤色(同肤色统一互斥)skin_tone_flagarray是0、1默认值 0
肤色调整肤色统一body_dullness_remove_alphaarray是0~100默认值 0
肤色调整明度skin_tone_body_luma_alphaarray是0~100默认值 100
肤色调整色彩skin_tone_body_hue_alphaarray是0~100默认值 100
肤色调整肤色选择skin_color_patharray是0~40:原肤 1:冷调 2:粉瓷 3:暖调 4:小麦默认值 0
肤色调整肤色选择透明度skin_color_hue_skin_alphaarray是0~100默认值 0
肤色调整肤色偏好skin_color_hue_alphaarray是-100~100默认值 0
肤色调整皮肤红润skin_red_alphaarray是0~100默认值 0
肤色调整皮肤美白skin_white_alphaarray是0~100默认值 0
肤色调整皮肤透亮skin_hdr_alphaarray是0~100默认值 0
皮肤磨皮高低频_脸部smooth_face_skin_alphaarray是0~100默认值 0
皮肤磨皮高低频_身体smooth_not_face_skin_alphaarray是0~100默认值 0
皮肤磨皮中性灰_脸部face_balance_alphaarray是0~100默认值 0
皮肤磨皮皮肤纹理_脸部sharpen_alphaarray是0~100默认值 0
全身美型高阶版美型(多人液化)multibody_beautyarray是0~150默认值 0
全身美型基础版丰胸chest_enlargeint是0~100默认值 0
全身美型基础版美胯slim_hipint是-100~100默认值 0
全身美型基础版瘦身slimint是0~100默认值 0
全身美型基础版瘦手臂slim_handint是0~100默认值 0
全身美型基础版瘦腿slim_legint是0~100默认值 0
全身美型基础版瘦腰slim_waistint是0~100默认值 0
全身美型基础版小头shrink_headint是0~100默认值 0
全身美型基础版长腿lengthenint是0~100默认值 0
设置三岁儿童牙齿效果是否开启child_teeth_beauty_flagint是0、1默认值 0
身体优化祛斑祛痘_身体skin_fleck_clean_flagarray是0、1默认值 0
身体优化祛妊娠纹beauty_belly_alphaarray是0、1默认值 0
身体优化身体去瑕疵flaw_clean_alphaarray是0~100默认值 0
身体优化婴幼儿去瑕疵baby_remove_danderarray是0~100默认值 0
头发调整头发蓬松fluffy_hairarray是0~100默认值 0
头发调整发色加深black_hairarray是0~100默认值 0
五官塑造鼻子_鼻尖nasal_tiparray是-100~100默认值 0
五官塑造鼻子_鼻梁bridge_nosearray是-100~100默认值 0
五官塑造鼻子_鼻翼shrink_nosearray是-100~100默认值 0
五官塑造鼻子_大小scale_nosearray是-100~100默认值 0
五官塑造鼻子_长短nose_longerarray是-100~100默认值 0
五官塑造鼻子_山根nasal_rootarray是-100~100默认值 0
五官塑造嘴巴_丰上唇upperlip_enhancearray是-100~100默认值 0
五官塑造嘴巴_丰下唇lowerlip_enhancearray是-100~100默认值 0
五官塑造嘴巴_大小mouth_transarray是-100~100默认值 0
五官塑造嘴巴_高度mouth_higharray是-100~100默认值 0
五官塑造嘴巴_宽度mouth_breadtharray是-100~100默认值 0
五官塑造嘴巴_上下high_moutharray是-100~100默认值 0
五官塑造嘴巴_微笑mouth_smilearray是-100~100默认值 0
五官塑造眼睛_左_上下eye_up_down_leftarray是-100~100默认值 0
五官塑造眼睛_右_上下eye_up_down_rightarray是-100~100默认值 0
五官塑造眼睛_左_大小eye_trans_leftarray是-100~100默认值 0
五官塑造眼睛_右_大小eye_trans_rightarray是-100~100默认值 0
五官塑造眼睛_左_倾斜eye_tilt_leftarray是-100~100默认值 0
五官塑造眼睛_右_倾斜eye_tilt_rightarray是-100~100默认值 0
五官塑造眼睛_左_眼高eye_height_leftarray是-100~100默认值 0
五官塑造眼睛_右_眼高eye_height_rightarray是-100~100默认值 0
五官塑造眼睛_左_眼睑eye_lid_leftarray是-100~100默认值 0
五官塑造眼睛_右_眼睑eye_lid_rightarray是-100~100默认值 0
五官塑造眼睛_左_眼距eye_distance_leftarray是-100~100默认值 0
五官塑造眼睛_右_眼距eye_distance_rightarray是-100~100默认值 0
五官塑造眼睛_左_眼宽eye_width_leftarray是-100~100默认值 0
五官塑造眼睛_右_眼宽eye_width_rightarray是-100~100默认值 0
五官塑造眼睛_左_开眼角inner_eye_corner_leftarray是-100~100默认值 0
五官塑造眼睛_右_开眼角inner_eye_corner_rightarray是-100~100默认值 0
五官塑造眉毛_左_倾斜eyebrow_tilt_leftarray是-100~100默认值 0
五官塑造眉毛_右_倾斜eyebrow_tilt_rightarray是-100~100默认值 0
五官塑造眉毛_左_上下eyebrow_height_leftarray是-100~100默认值 0
五官塑造眉毛_右_上下eyebrow_height_rightarray是-100~100默认值 0
五官塑造眉毛_左_间距eyebrow_distance_leftarray是-100~100默认值 0
五官塑造眉毛_右_间距eyebrow_distance_rightarray是-100~100默认值 0
五官塑造眉毛_左_眉峰eyebrow_ridge_leftarray是-100~100默认值 0
五官塑造眉毛_右_眉峰eyebrow_ridge_rightarray是-100~100默认值 0
五官塑造眉毛_左_粗细eyebrow_size_leftarray是-100~100默认值 0
五官塑造眉毛_右_粗细eyebrow_size_rightarray是-100~100默认值 0
牙齿美化牙齿美白white_teetharray是0~100默认值 0
牙齿美化牙齿修复teeth_beautyarray是0、1默认值 0
智能增高AI增高heightenint是0~100默认值 0
妆容调整唇妆增强lipstick_deepenarray是0~100默认值 0
妆容调整高光立体highlight_alphaarray是0~100默认值 0
妆容调整脸颊加深facial_deepenarray是0~100默认值 0
妆容调整亮眼bright_eyearray是0~100默认值 0
妆容调整眉毛增强eyebrow_deepenarray是0~100默认值 0
妆容调整眼妆增强eyeshadow_deepenarray是0~100默认值 0
妆容调整阴影立体shadow_lightarray是0~100默认值 0
妆容调整妆饰facialdecalsarray是| 查看
妆容调整腮红blusharray是| 查看
妆容调整卧蚕eyesocketarray是| 查看
妆容调整睫毛eyelasharray是| 查看
妆容调整眼影eyeshadowarray是| 查看
妆容调整唇彩moutharray是| 查看
妆容调整眉毛eyebrowarray是| 查看
妆容调整美瞳eyearray是| 查看
妆容调整修容featurearray是| 查看
服饰美化衣服祛褶皱rmw_rinkint是0~100默认值 0

注意:对于参数支持性别和年龄属性的,那么他的数据结构是一个 array,这个 array 总共有 5 个元素,分别对应 people_type 中的 5 种性别/年龄的定义,比如参数值:

beauty_belly_alpha: [10, 20, 30, 40, 50]

然后 people_type 的定义顺序为(注:people_type数组每一个元素的结构是一个对象,这里用字符串是为了方便阅读,具体的数据结构参考推荐配置):

["man", "woman", "child", "oldwoman", "oldman"]

那么表示 beauty_belly_alpha 对应会生效为:

{
    "man": 10,
    "woman": 20,
    "child": 30,
    "oldwoman": 40,
    "oldman": 50
}
  • filter 参数结构:
名称类型是否必填描述范围示例值
filter_idstring否滤镜ID|
filters_lut_alphaint否程度值0~100默认值50
filter_is_blackint否|
  • blush、eyesocket等数组中对象结构:
名称类型是否必填描述示例值
idstring是效果名称,默认值空"luozhuang"
colorstring是颜色值,rgba格式,默认值 0;0;0;0""
alphaint是效果程度,默认值 050
  • people_type 参数结构:

该字段用来定义图片中人物性别和年龄的对应关系,目前支持设置 5 种类型的人物性别。

名称类型是否必填描述示例值
agelist是定义该属性的年龄范围[50, 100]
genderint是性别:1男 0女
keystring是性别属性oldman
namestring否性别属性名称老

推荐配置参数:

[
    {
        "age":[
            15,
            49
        ],
        "gender":1,
        "key":"man",
        "name":"男"
    },
    {
        "age":[
            15,
            49
        ],
        "gender":0,
        "key":"woman",
        "name":"女"
    },
    {
        "age":[
            0,
            14
        ],
        "gender":0,
        "key":"child",
        "name":"儿童"
    },
    {
        "age":[
            50,
            100
        ],
        "gender":0,
        "key":"oldwoman",
        "name":"老年女"
    },
    {
        "age":[
            50,
            100
        ],
        "gender":1,
        "key":"oldman",
        "name":"老年男"
    }
]
  • output 参数结构:
名称类型是否必填描述示例值
formatstring是输出格式,支持jpg和pngjpg
preview_sizestring是原图分割尺寸,推荐30003000
qualityKeyint是输出图质量,范围1~13,数值越大对应的画质越高;默认值12,对应画质9912
resize_heightint是输出图尺寸(高),0表示原图输出,默认0,保留字段暂不支持配置0
resize_widthint是输出图尺寸(宽),0表示原图输出,默认0,保留字段暂不支持配置0
water_markint是是否水印,0无水印 1有水印0
file_size_limitarray否输出图片大小范围,以示例值来说最小不超过原图的0.8,最大不超过原图的1.3[0.8, 1.3]

请求示例:

将下方 params.json 的内容作为请求体提交。

完整请求参数:

params.json

3. 结果查询

1. 消息通知回调

当异步的任务处理完成后,会通过业务侧请求中的 repost_url 参数来回调通知。业务侧在处理完成后,需响应一个状态码为 200 的响应,响应体不做要求。

注意1:目前回调请求只会回调一次,业务方需做好服务保障,如在一段时间没有接收到回调请求后,可以通过主动查询来获取结果。

注意2: 同样的通知可能会多次回调给业务方,业务方的系统必须能够正确处理重复的通知。 推荐的做法是收到通知进行处理时,先检查对应业务数据的状态,并判断该通知是否已经处理。如果未处理,则再进行处理;如果已处理,则直接返回结果成功。

注意3:处理回调的时候切记要判断回调内容是否正确后,再进行后续的业务逻辑处理,避免损失

**通知地址:**业务方提供的 repost_url 参数

**通知请求方法:**POST

**请求头:**Content-Type:application/json

请求参数(Body参数):

名称类型是否必填描述示例值
codeint是业务状态码0
datastruct是结果数据查看
messagestring否提示信息success
  • data 字段结构:
名称类型是否必填描述示例值
msg_idstring是异步任务ID838b1d4a-ba79-44bd-b496-8a5a3b14097e
media_datastring是处理好的效果图地址https://mt-mtyunxiu-static.oss-cn-beijing.aliyuncs.com/material/1680141903114.jpg

请求示例:

{
    "code": 0,
    "data": {
        "msg_id": "8547e55f-9492-40a9-ba0d-7041b717ee5a",
        "media_data": "https://obs-open-platform-photo.obs.cn-north-4.myhuaweicloud.com/mtopen/KxZo7A5mPWTP3FVhVThFu9VlA0s6p59c/MTY5MzE5MTYwMA==/c69a44d6-bace-446e-51e1-2dcd91a606ed.jpeg"
    },
    "message": "success",
    "request_id": "838b1d4a-ba79-44bd-b496-8a5a3b14097e"
}

3.2 轮训请求查询

注意:异步任务的结果只保存 12 个小时,请及时查询并转存效果图图片,过期后该异步任务 ID 将无法查询到结果。请求之后切记要解析响应的 Body 来做结果判断。

请求地址: https://openapi.meitu.com/yunxiu_api/openapi/query

请求方法: POST

请求参数(Body参数):

名称类型是否必填描述示例值
msg_idstring是异步任务ID6aca960e-6669-4f39-805e-9bc69705b82d

请求示例:

{
    "msg_id": "6aca960e-6669-4f39-805e-9bc69705b82d"
}

响应参数:

名称类型是否必填描述示例值
codeint是业务状态码0
datastruct是结果数据参考下文示例
messagestring否提示信息success
request_idstring是请求ID838b1d4a-ba79-44bd-b496-8a5a3b14097e

data 字段结构:

名称类型是否必填描述示例值
msg_idstring是异步任务ID838b1d4a-ba79-44bd-b496-8a5a3b14097e
media_datastring是处理好的效果图地址https://mt-mtyunxiu-static.oss-cn-beijing.aliyuncs.com/material/1680141903114.jpg

响应示例:

{
    "code": 0,
    "data": {
        "msg_id": "8547e55f-9492-40a9-ba0d-7041b717ee5a",
        "media_data": "https://obs-open-platform-photo.obs.cn-north-4.myhuaweicloud.com/mtopen/KxZo7A5mPWTP3FVhVThFu9VlA0s6p59c/MTY5MzE5MTYwMA==/c69a44d6-bace-446e-51e1-2dcd91a606ed.jpeg"
    },
    "message": "success",
    "request_id": "838b1d4a-ba79-44bd-b496-8a5a3b14097e"
}

4. 错误码

错误码错误信息描述
0SUCCESS请求成功
29901NOT_RESULT图片还在处理中,结果还没出来
29902RECORD_NOT_FOUND异步任务 ID 已过期
90002GATEWAY_AUTHORIZED_ERROR接口未授权/密钥错误
11201UNKNOW ERROR用户图片地址下载失败
20001UNKNOW ERROR图片处理失败

5. 常见问题

1. 图片是否会处理失败?

会。目前处理图片的过程中,会偶发出现失败的情况,目前整体的成功率是控制在 99.95%+ 的,业务代码也建议可以多做一步容错处理,code=0 的话就表示是处理成功了,不等于 0 就表示失败了,业务代码可以走重试一下。

5.2 什么是预设 ID ?

预设编码:相当于以下多种效果参数组合而成的集合,可通过预设编码作用于图片。详见 美图云修使用指南,以自定义生成适合业务场景的预设编码。附录部分通用预设以供测试:

  • 婚纱:MTyunxiu163aa58942

  • 儿童:MTyunxiu17616ca0c2

  • 证件照:MTyunxiu1961233973

  • 全家福:MTyunxiu10353b70b3

  • 个人写真:MTyunxiu1ff977e9e3

5.3 输入图片的格式/尺寸/大小有什么限制?

  • 支持格式:jpg、jpeg、png

  • 建议尺寸:不超过12000*12000像素

  • 建议大小:70M以内

图片尺寸或大小过大时,会影响图片的处理速度

5.4 什么是 QPS?

QPS 就是限制每秒能请求的次数,假如设置为 10 的话,那么表示每秒可以发起 10 个请求,每个请求可以提交一张图片处理,后端图片的处理是并行的。

5.5 API效果功能与美图云修客户端是否完全一致?

除以下手动功能不支持外,美图云修智能API效果功能与美图云修Air版客户端完全一致

  • 手动液化

  • 手动裁剪

  • 手动区域保护

  • 换天空

  • 证件照

  • 相册设计

5.6 如需小尺寸预览图接入如何调用?

小尺寸预览图:接入场景主要针对移动端效果快速确认。**视使用场景而定,非必须接入。**小尺寸预览图接口调用价格与原图接入调用价格不同,如有需要可联系商务经理洽谈。

SDK 调用示例

安装对应语言的签名 SDK。Python 还需安装 requests,PHP 需将 signer.php 放在示例同目录,Java 文件名为 Main.java。

填入 AK、SK、预设 ID 和图片地址即可提交任务。查询时使用提交返回的 data.msg_id。

Python

import json
import requests
from sign_sdk import sign
def api_call_example():
    key = "your_access_key"
    secret = "your_secret_key"
    url = "https://openapi.meitu.com/yunxiu_api/openapi/realphotolocal_async"
    method = "POST"
    headers = {
        "Content-Type": "application/json",
        sign.HeaderHost: "openapi.meitu.com",
    }
    payload = {"media_code": "YOUR_PRESET_ID", "media_data": "https://example.com/portrait.jpg"}
    body = json.dumps(payload, ensure_ascii=False)
    signer = sign.Signer(key, secret)
    signed_request = signer.sign(url, method, headers, body)
    with requests.Session() as session:
        response = session.send(signed_request, timeout=60)
        print("Status:", response.status_code)
        print("Response:", response.text)
if __name__ == "__main__":
    api_call_example()

Go

package main

import (
	"fmt"
	"github.com/mtlab/api/signer"
	"io"
	"net/http"
	"time"
)

func main() {
	key := "your_access_key"
	secret := "your_secret_key"
	signObj := signer.NewSigner(key, secret)
	url := "https://openapi.meitu.com/yunxiu_api/openapi/realphotolocal_async"
	headers := make(http.Header)
	headers.Set(signer.HeaderHost, "openapi.meitu.com")
	headers.Set("Content-Type", "application/json")
	body := `{"media_code":"YOUR_PRESET_ID","media_data":"https://example.com/portrait.jpg"}`
	req, err := signObj.Sign(url, http.MethodPost, headers, body)
	if err != nil {
		fmt.Println("Failed to sign request:", err)
		return
	}
	client := &http.Client{Timeout: 60 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Failed to send request:", err)
		return
	}
	defer resp.Body.Close()
	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Failed to read response:", err)
		return
	}
	fmt.Println("Status:", resp.StatusCode)
	fmt.Println("Response:", string(responseBody))
}

PHP

<?php
require_once __DIR__ . '/signer.php';
$key = 'your_access_key';
$secret = 'your_secret_key';
$url = 'https://openapi.meitu.com/yunxiu_api/openapi/realphotolocal_async';
$headers = [
    'Content-Type' => 'application/json',
    'Host' => 'openapi.meitu.com',
];
$payload = ['media_code' => 'YOUR_PRESET_ID', 'media_data' => 'https://example.com/portrait.jpg'];
$body = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
$signer = new Signer($key, $secret);
$curl = $signer->sign($url, 'POST', $headers, $body);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_TIMEOUT, 60);
$response = curl_exec($curl);
if ($response === false) {
    echo 'Error: ' . curl_error($curl);
} else {
    echo 'Status: ' . curl_getinfo($curl, CURLINFO_HTTP_CODE) . PHP_EOL;
    echo 'Response: ' . $response . PHP_EOL;
}
curl_close($curl);

Java

import com.meitu.openai.common.Signer;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
public class Main {
    public static void main(String[] args) throws Exception {
        Signer signer = new Signer("your_access_key", "your_secret_key");
        String url = "https://openapi.meitu.com/yunxiu_api/openapi/realphotolocal_async";
        String method = "POST";
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put(Signer.HeaderHost, "openapi.meitu.com");
        String body = "{\"media_code\": \"YOUR_PRESET_ID\", \"media_data\": \"https://example.com/portrait.jpg\"}";
        Map<String, String> signedHeaders = signer.sign(url, method, headers, body);
        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        try {
            connection.setRequestMethod(method);
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(60000);
            connection.setInstanceFollowRedirects(false);
            for (Map.Entry<String, String> header : signedHeaders.entrySet()) {
                connection.setRequestProperty(header.getKey(), header.getValue());
            }
            connection.setDoOutput(true);
            try (OutputStream output = connection.getOutputStream()) {
                output.write(body.getBytes(StandardCharsets.UTF_8));
            }
            int status = connection.getResponseCode();
            InputStream stream = status >= 400
                    ? connection.getErrorStream()
                    : connection.getInputStream();
            System.out.println("Status: " + status);
            if (stream != null) {
                try (InputStream input = stream;
                     ByteArrayOutputStream output = new ByteArrayOutputStream()) {
                    byte[] buffer = new byte[4096];
                    int length;
                    while ((length = input.read(buffer)) != -1) {
                        output.write(buffer, 0, length);
                    }
                    System.out.println("Response: " + output.toString("UTF-8"));
                }
            }
        } finally {
            connection.disconnect();
        }
    }
}

原始参数提交示例

将上文的完整原始请求体保存为 params.json,替换图片地址和处理参数。

Python

import json
import requests
from sign_sdk import sign
def api_call_example():
    key = "your_access_key"
    secret = "your_secret_key"
    url = "https://openapi.meitu.com/yunxiu_api/openapi/super_realphotolocal_async"
    method = "POST"
    headers = {
        "Content-Type": "application/json",
        sign.HeaderHost: "openapi.meitu.com",
    }
    with open("params.json", encoding="utf-8") as source:
        body = source.read()
    signer = sign.Signer(key, secret)
    signed_request = signer.sign(url, method, headers, body)
    with requests.Session() as session:
        response = session.send(signed_request, timeout=60)
        print("Status:", response.status_code)
        print("Response:", response.text)
if __name__ == "__main__":
    api_call_example()

Go

package main

import (
	"fmt"
	"github.com/mtlab/api/signer"
	"io"
	"net/http"
	"os"
	"time"
)

func main() {
	key := "your_access_key"
	secret := "your_secret_key"
	signObj := signer.NewSigner(key, secret)
	url := "https://openapi.meitu.com/yunxiu_api/openapi/super_realphotolocal_async"
	headers := make(http.Header)
	headers.Set(signer.HeaderHost, "openapi.meitu.com")
	headers.Set("Content-Type", "application/json")
	data, err := os.ReadFile("params.json")
	if err != nil { panic(err) }
	body := string(data)
	req, err := signObj.Sign(url, http.MethodPost, headers, body)
	if err != nil {
		fmt.Println("Failed to sign request:", err)
		return
	}
	client := &http.Client{Timeout: 60 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Failed to send request:", err)
		return
	}
	defer resp.Body.Close()
	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Failed to read response:", err)
		return
	}
	fmt.Println("Status:", resp.StatusCode)
	fmt.Println("Response:", string(responseBody))
}

PHP

<?php
require_once __DIR__ . '/signer.php';
$key = 'your_access_key';
$secret = 'your_secret_key';
$url = 'https://openapi.meitu.com/yunxiu_api/openapi/super_realphotolocal_async';
$headers = [
    'Content-Type' => 'application/json',
    'Host' => 'openapi.meitu.com',
];
$body = file_get_contents(__DIR__ . '/params.json');
if ($body === false) { throw new RuntimeException('Cannot read params.json'); }
$signer = new Signer($key, $secret);
$curl = $signer->sign($url, 'POST', $headers, $body);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_TIMEOUT, 60);
$response = curl_exec($curl);
if ($response === false) {
    echo 'Error: ' . curl_error($curl);
} else {
    echo 'Status: ' . curl_getinfo($curl, CURLINFO_HTTP_CODE) . PHP_EOL;
    echo 'Response: ' . $response . PHP_EOL;
}
curl_close($curl);

Java

import com.meitu.openai.common.Signer;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
public class Main {
    public static void main(String[] args) throws Exception {
        Signer signer = new Signer("your_access_key", "your_secret_key");
        String url = "https://openapi.meitu.com/yunxiu_api/openapi/super_realphotolocal_async";
        String method = "POST";
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put(Signer.HeaderHost, "openapi.meitu.com");
        String body = new String(java.nio.file.Files.readAllBytes(java.nio.file.Paths.get("params.json")), StandardCharsets.UTF_8);
        Map<String, String> signedHeaders = signer.sign(url, method, headers, body);
        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        try {
            connection.setRequestMethod(method);
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(60000);
            connection.setInstanceFollowRedirects(false);
            for (Map.Entry<String, String> header : signedHeaders.entrySet()) {
                connection.setRequestProperty(header.getKey(), header.getValue());
            }
            connection.setDoOutput(true);
            try (OutputStream output = connection.getOutputStream()) {
                output.write(body.getBytes(StandardCharsets.UTF_8));
            }
            int status = connection.getResponseCode();
            InputStream stream = status >= 400
                    ? connection.getErrorStream()
                    : connection.getInputStream();
            System.out.println("Status: " + status);
            if (stream != null) {
                try (InputStream input = stream;
                     ByteArrayOutputStream output = new ByteArrayOutputStream()) {
                    byte[] buffer = new byte[4096];
                    int length;
                    while ((length = input.read(buffer)) != -1) {
                        output.write(buffer, 0, length);
                    }
                    System.out.println("Response: " + output.toString("UTF-8"));
                }
            }
        } finally {
            connection.disconnect();
        }
    }
}

查询结果(Query)

将提交响应中的 data.msg_id 填入以下示例的 YOUR_MSG_ID,签名后发送 POST 请求查询结果。

Python

import json
import requests
from sign_sdk import sign
def api_call_example():
    key = "your_access_key"
    secret = "your_secret_key"
    url = "https://openapi.meitu.com/yunxiu_api/openapi/query"
    method = "POST"
    headers = {
        "Content-Type": "application/json",
        sign.HeaderHost: "openapi.meitu.com",
    }
    payload = {"msg_id": "YOUR_MSG_ID"}
    body = json.dumps(payload, ensure_ascii=False)
    signer = sign.Signer(key, secret)
    signed_request = signer.sign(url, method, headers, body)
    with requests.Session() as session:
        response = session.send(signed_request, timeout=60)
        print("Status:", response.status_code)
        print("Response:", response.text)
if __name__ == "__main__":
    api_call_example()

Go

package main

import (
	"fmt"
	"github.com/mtlab/api/signer"
	"io"
	"net/http"
	"time"
)

func main() {
	key := "your_access_key"
	secret := "your_secret_key"
	signObj := signer.NewSigner(key, secret)
	url := "https://openapi.meitu.com/yunxiu_api/openapi/query"
	headers := make(http.Header)
	headers.Set(signer.HeaderHost, "openapi.meitu.com")
	headers.Set("Content-Type", "application/json")
	body := `{"msg_id":"YOUR_MSG_ID"}`
	req, err := signObj.Sign(url, http.MethodPost, headers, body)
	if err != nil {
		fmt.Println("Failed to sign request:", err)
		return
	}
	client := &http.Client{Timeout: 60 * time.Second}
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Failed to send request:", err)
		return
	}
	defer resp.Body.Close()
	responseBody, err := io.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Failed to read response:", err)
		return
	}
	fmt.Println("Status:", resp.StatusCode)
	fmt.Println("Response:", string(responseBody))
}

PHP

<?php
require_once __DIR__ . '/signer.php';
$key = 'your_access_key';
$secret = 'your_secret_key';
$url = 'https://openapi.meitu.com/yunxiu_api/openapi/query';
$headers = [
    'Content-Type' => 'application/json',
    'Host' => 'openapi.meitu.com',
];
$payload = ['msg_id' => 'YOUR_MSG_ID'];
$body = json_encode($payload, JSON_UNESCAPED_SLASHES | JSON_THROW_ON_ERROR);
$signer = new Signer($key, $secret);
$curl = $signer->sign($url, 'POST', $headers, $body);
curl_setopt($curl, CURLOPT_HEADER, false);
curl_setopt($curl, CURLOPT_TIMEOUT, 60);
$response = curl_exec($curl);
if ($response === false) {
    echo 'Error: ' . curl_error($curl);
} else {
    echo 'Status: ' . curl_getinfo($curl, CURLINFO_HTTP_CODE) . PHP_EOL;
    echo 'Response: ' . $response . PHP_EOL;
}
curl_close($curl);

Java

import com.meitu.openai.common.Signer;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.HashMap;
import java.util.Map;
public class Main {
    public static void main(String[] args) throws Exception {
        Signer signer = new Signer("your_access_key", "your_secret_key");
        String url = "https://openapi.meitu.com/yunxiu_api/openapi/query";
        String method = "POST";
        Map<String, String> headers = new HashMap<>();
        headers.put("Content-Type", "application/json");
        headers.put(Signer.HeaderHost, "openapi.meitu.com");
        String body = "{\"msg_id\":\"YOUR_MSG_ID\"}";
        Map<String, String> signedHeaders = signer.sign(url, method, headers, body);
        HttpURLConnection connection = (HttpURLConnection) new URL(url).openConnection();
        try {
            connection.setRequestMethod(method);
            connection.setConnectTimeout(10000);
            connection.setReadTimeout(60000);
            connection.setInstanceFollowRedirects(false);
            for (Map.Entry<String, String> header : signedHeaders.entrySet()) {
                connection.setRequestProperty(header.getKey(), header.getValue());
            }
            connection.setDoOutput(true);
            try (OutputStream output = connection.getOutputStream()) {
                output.write(body.getBytes(StandardCharsets.UTF_8));
            }
            int status = connection.getResponseCode();
            InputStream stream = status >= 400
                    ? connection.getErrorStream()
                    : connection.getInputStream();
            System.out.println("Status: " + status);
            if (stream != null) {
                try (InputStream input = stream;
                     ByteArrayOutputStream output = new ByteArrayOutputStream()) {
                    byte[] buffer = new byte[4096];
                    int length;
                    while ((length = input.read(buffer)) != -1) {
                        output.write(buffer, 0, length);
                    }
                    System.out.println("Response: " + output.toString("UTF-8"));
                }
            }
        } finally {
            connection.disconnect();
        }
    }
}