@iflyrpa/actions 4.1.0-beta.5 → 4.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -38,9 +38,9 @@ export declare const SearchAccountInfoParamsSchema: z.ZodObject<{
38
38
  token: z.ZodOptional<z.ZodUnion<readonly [z.ZodString, z.ZodNumber]>>;
39
39
  platform: z.ZodEnum<{
40
40
  baijiahao: "baijiahao";
41
+ xiaohongshu: "xiaohongshu";
41
42
  douyin: "douyin";
42
43
  toutiao: "toutiao";
43
- xiaohongshu: "xiaohongshu";
44
44
  weixin: "weixin";
45
45
  shipinhao: "shipinhao";
46
46
  }>;
@@ -1,5 +1,13 @@
1
1
  import type { CommonAction } from "@iflyrpa/share";
2
2
  import { z } from "zod";
3
+ /**
4
+ * 内容声明标注类型,对应发布体 `tagInfo.tagType`
5
+ *
6
+ * 取值来自 `post/finder_get_object_tag_list` 实测响应:
7
+ * 0=无需标注、1=含AI生成内容、2=内容包含营销广告、3=内容为虚构剧情仅供娱乐、
8
+ * 5=内容为自行拍摄、7=内容为转载、8=个人观点仅供参考
9
+ */
10
+ export declare const ShipinhaoDeclareTagTypes: readonly [0, 1, 2, 3, 5, 7, 8];
3
11
  export declare const ShipinhaoPublishVideoParamsSchema: z.ZodObject<{
4
12
  id: z.ZodOptional<z.ZodString>;
5
13
  userAgent: z.ZodOptional<z.ZodString>;
@@ -35,14 +43,50 @@ export declare const ShipinhaoPublishVideoParamsSchema: z.ZodObject<{
35
43
  saveType: z.ZodOptional<z.ZodString>;
36
44
  uid: z.ZodOptional<z.ZodString>;
37
45
  videoPath: z.ZodString;
46
+ videoMetadata: z.ZodObject<{
47
+ duration: z.ZodNumber;
48
+ width: z.ZodNumber;
49
+ height: z.ZodNumber;
50
+ fileSize: z.ZodNumber;
51
+ path: z.ZodOptional<z.ZodString>;
52
+ fileName: z.ZodString;
53
+ }, z.core.$strip>;
38
54
  coverPath: z.ZodString;
55
+ verticalCoverPath: z.ZodOptional<z.ZodString>;
39
56
  description: z.ZodString;
40
57
  title: z.ZodOptional<z.ZodString>;
41
- scheduleTime: z.ZodOptional<z.ZodNumber>;
58
+ scheduledTime: z.ZodOptional<z.ZodNumber>;
59
+ isImmediatelyPublish: z.ZodOptional<z.ZodBoolean>;
60
+ topics: z.ZodOptional<z.ZodArray<z.ZodString>>;
61
+ mentionedUsers: z.ZodOptional<z.ZodArray<z.ZodObject<{
62
+ nickname: z.ZodString;
63
+ }, z.core.$strip>>>;
64
+ collection: z.ZodOptional<z.ZodObject<{
65
+ collectionId: z.ZodString;
66
+ collectionName: z.ZodString;
67
+ }, z.core.$strip>>;
68
+ event: z.ZodOptional<z.ZodObject<{
69
+ eventTopicId: z.ZodString;
70
+ eventName: z.ZodString;
71
+ eventCreatorNickname: z.ZodOptional<z.ZodString>;
72
+ }, z.core.$strip>>;
73
+ link: z.ZodOptional<z.ZodObject<{
74
+ link: z.ZodString;
75
+ title: z.ZodString;
76
+ urlType: z.ZodDefault<z.ZodNumber>;
77
+ }, z.core.$strip>>;
78
+ tagInfo: z.ZodOptional<z.ZodObject<{
79
+ /** 标注类型,取值见 ShipinhaoDeclareTagTypes */
80
+ tagType: z.ZodNumber;
81
+ }, z.core.$loose>>;
82
+ originalFlag: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<0>, z.ZodLiteral<1>]>>;
83
+ postWithMemberZoneLink: z.ZodOptional<z.ZodUnion<readonly [z.ZodLiteral<0>, z.ZodLiteral<1>]>>;
42
84
  location: z.ZodOptional<z.ZodObject<{
43
85
  latitude: z.ZodNumber;
44
86
  longitude: z.ZodNumber;
45
87
  city: z.ZodString;
88
+ poiName: z.ZodOptional<z.ZodString>;
89
+ address: z.ZodOptional<z.ZodString>;
46
90
  poiClassifyId: z.ZodOptional<z.ZodString>;
47
91
  }, z.core.$strip>>;
48
92
  }, z.core.$strip>;
@@ -0,0 +1,70 @@
1
+ /**
2
+ * post_create 发布体构建
3
+ *
4
+ * 字段结构以真实浏览器请求为准(见同目录 real.js,以及
5
+ * scripts/api-explorer/shipinhao-video-upload/dist/network-logs1.json 里捕获的 post_create 请求体)。
6
+ *
7
+ * 两次独立抓包一致的关键点:
8
+ * - 顶层 latitude/longitude/feedLatitude/feedLongitude 恒为 0,真实坐标只写在 objectDesc.location
9
+ * - objectDesc.shortTitle 是数组 `[{ shortTitle }]`,不是字符串
10
+ * - media[].md5sum 填 UUID 而非真实 md5(服务端不校验)
11
+ * - report 里的 width/height/duration/fileSize 是转码**前**的原始视频信息
12
+ */
13
+ import type { ShipinhaoPublishVideoParams } from "./index";
14
+ /** 描述文案中的话题片段:正文 → 话题 → @用户,与前端插入顺序一致 */
15
+ export declare function buildDescription(params: {
16
+ description: string;
17
+ topics?: string[];
18
+ mentionedUsers?: Array<{
19
+ nickname: string;
20
+ }>;
21
+ }): string;
22
+ /** mentionedUser[].nickname:实测昵称后带一个普通空格 */
23
+ export declare function buildMentionedUser(mentionedUsers?: Array<{
24
+ nickname: string;
25
+ }>): Array<{
26
+ nickname: string;
27
+ }>;
28
+ /**
29
+ * 构建 finderTopicInfo XML
30
+ *
31
+ * value 节点按其在文案中出现的顺序排列:正文(非空时)为纯 CDATA,
32
+ * 话题为 `<topic><![CDATA[#name#]]></topic>`(注意首尾都有 #),
33
+ * @用户为 `@nickname` + U+2005 的 CDATA。
34
+ * `<style><at>` 指向第一个 @用户所在的 value 序号,没有 @用户时为空。
35
+ *
36
+ * ⚠️ `description` 传的必须是**原始正文**,不是 buildDescription 拼接后的结果 ——
37
+ * 拼接结果里已经含话题与 @用户,再进 value0 会重复一遍。
38
+ */
39
+ export declare function buildTopicXml(params: {
40
+ description: string;
41
+ topics?: string[];
42
+ mentionedUsers?: Array<{
43
+ nickname: string;
44
+ }>;
45
+ }): string;
46
+ /** objectDesc.location:无位置时下发全 0 占位,与前端一致 */
47
+ export declare function buildLocation(location?: ShipinhaoPublishVideoParams["location"]): Record<string, unknown>;
48
+ /**
49
+ * objectDesc.topic:话题 XML + 合集信息合并在同一对象里
50
+ *
51
+ * `description` 同样要传原始正文,见 buildTopicXml 的说明。
52
+ */
53
+ export declare function buildTopic(params: {
54
+ description: string;
55
+ topics?: string[];
56
+ mentionedUsers?: Array<{
57
+ nickname: string;
58
+ }>;
59
+ collection?: ShipinhaoPublishVideoParams["collection"];
60
+ }): Record<string, unknown>;
61
+ /** objectDesc.event:未参与活动时为空对象 */
62
+ export declare function buildEvent(event?: ShipinhaoPublishVideoParams["event"]): Record<string, unknown>;
63
+ /** objectDesc.extReading:无链接时也要带全字段占位(实测前端行为) */
64
+ export declare function buildExtReading(link?: ShipinhaoPublishVideoParams["link"]): Record<string, unknown>;
65
+ /**
66
+ * 顶层 tagInfo:原样透传调用方传入的对象,只补上实时 tagKey
67
+ *
68
+ * tagKey 由服务端每次下发且带时效,必须用当次取到的值,所以这里始终覆盖调用方传的同名字段。
69
+ */
70
+ export declare function buildTagInfo(tagInfo: NonNullable<ShipinhaoPublishVideoParams["tagInfo"]>, tagKey: string): Record<string, unknown>;
@@ -8,6 +8,23 @@
8
8
  * 数据来源:network-logs.json (8/20) + network-logs1.json (8/19)
9
9
  */
10
10
  import type { Http } from "../../utils/http";
11
+ /**
12
+ * 上传超时调优参数
13
+ *
14
+ * 上传对网络远比普通接口敏感:8MB 分片在慢网下几十秒才走完一片,
15
+ * 撞上过短的超时只会触发无意义的重试并把整体时间拖长,
16
+ * 所以三个阶段统一给 3 分钟的宽松上限。每片独立计时,总时长不设上限。
17
+ */
18
+ export interface UploadTuning {
19
+ /** 元数据请求(applyupload)超时 */
20
+ metaTimeout?: number;
21
+ /** 单分片上传超时 */
22
+ partTimeout?: number;
23
+ /** 单分片重试次数(PartNumber + Content-MD5 幂等,重试安全) */
24
+ partRetries?: number;
25
+ /** completepart 超时:服务端要落盘拼装整个文件,大视频天然慢 */
26
+ completeTimeout?: number;
27
+ }
11
28
  export interface UploadOptions {
12
29
  filePath: string;
13
30
  /** filetype: 20302=视频, 20304=封面 */
@@ -19,6 +36,8 @@ export interface UploadOptions {
19
36
  info: (msg: string) => void;
20
37
  error: (msg: string, ...args: any[]) => void;
21
38
  };
39
+ /** 超时调优,不传则用 DEFAULT_TUNING */
40
+ tuning?: UploadTuning;
22
41
  }
23
42
  export interface UploadResult {
24
43
  /** completepart 返回的 DownloadURL */
@@ -1,21 +1,31 @@
1
1
  /**
2
- * 从 MP4 文件解析视频元数据(宽高、时长)
2
+ * 从 MP4 文件解析视频元数据(宽高、时长、编码)
3
3
  *
4
4
  * 算法来源:scripts/api-explorer/shipinhao-video-upload/mp4-parse-poc.mjs
5
5
  * 已通过合成样本 8/8 + 真实 Chrome 编码视频交叉验证(见该 PoC)。
6
6
  *
7
- * 只读 ISO BMFF box 头部做跳转,不解码帧数据,内存占用与文件大小无关。
7
+ * 只读 ISO BMFF box 头做定位,元数据 box(moov / moof)才单独读进内存,
8
+ * 媒体数据(mdat)直接跳过 —— 实测 78MB 视频只读 14.64KB(占全文 0.018%)。
9
+ * 因此内存占用与文件大小无关,也不受 fs.readFileSync 的 2GiB 上限约束
10
+ * (早先的实现整文件载入,2GB 以上必然抛 RangeError 并被误报成「格式不支持」)。
8
11
  * 支持 MP4(ISO base media file format),不支持 AVI/MKV/FLV。
9
12
  *
10
- * @param filePath 本地视频文件路径
11
- * @returns {width, height, duration, rotation, fileSize} 或 null(解析失败)
13
+ * 时长按四级回退取值:mvhd 视频轨 mdhd → stts 累加 → moof/trun 累加。
14
+ * 分片 MP4(fMP4,moov 里带 mvex/trex)的 mvhd/mdhd/stts 全为 0,
15
+ * 真实时长只存在于各 moof 分片中,必须走最后一级才能拿到。
12
16
  */
13
17
  export interface VideoMeta {
14
18
  width: number;
15
19
  height: number;
16
20
  /** 时长(秒,浮点数) */
17
21
  duration: number;
18
- /** 旋转角度(0/90/180/270),手机竖屏视频常为 90 */
22
+ /**
23
+ * 旋转角度(0/90/180/270),手机竖屏视频常为 90
24
+ *
25
+ * 仅用于把 tkhd 里的横屏尺寸换算成显示尺寸,不写进发布体。
26
+ * 由 buildVideoMetaFromParams 组装时恒为 0:浏览器给出的 videoWidth/videoHeight
27
+ * 已经是应用过旋转的显示尺寸,再换算一次会把宽高交换错。
28
+ */
19
29
  rotation: number;
20
30
  fileSize: number;
21
31
  /**
@@ -25,3 +35,31 @@ export interface VideoMeta {
25
35
  codec: string | null;
26
36
  }
27
37
  export declare function parseVideoMeta(filePath: string): VideoMeta | null;
38
+ /** 调用方传入的视频元数据(浏览器 <video> + File 侧采集) */
39
+ export interface VideoMetadataInput {
40
+ duration: number;
41
+ width: number;
42
+ height: number;
43
+ fileSize: number;
44
+ }
45
+ /**
46
+ * 只读视频轨编码格式,不解析其余字段
47
+ *
48
+ * 供「宽高时长由调用方给出,仅编码需要本地确认」的场景使用。
49
+ * 浏览器没有暴露编码格式的 API(canPlayType/MediaCapabilities 只能回答
50
+ * 「给定 MIME 能否播放」,无法反查文件实际编码),所以这一项只能读文件。
51
+ * 走的是同一套分段读,成本是几 KB。
52
+ *
53
+ * @returns fourcc(小写,如 avc1/hvc1),读不到时 null
54
+ */
55
+ export declare function parseVideoCodec(filePath: string): string | null;
56
+ /**
57
+ * 用调用方传入的元数据组装 VideoMeta,编码格式仍从文件读取
58
+ *
59
+ * 宽高时长直接采用传入值:浏览器的 videoWidth/videoHeight 是**已应用旋转**的显示尺寸,
60
+ * 正是发布体需要的值,所以 rotation 固定为 0,不再做二次换算(换算会把竖屏宽高交换错)。
61
+ *
62
+ * codec 读取失败不影响发布 —— validateShipinhaoVideo 对 codec=null 会跳过编码校验,
63
+ * 退化为由服务端判断,与文件解析不出编码时的既有行为一致。
64
+ */
65
+ export declare function buildVideoMetaFromParams(filePath: string, metadata: VideoMetadataInput): VideoMeta;
@@ -13,8 +13,10 @@ export declare const MAX_FILE_SIZE: number;
13
13
  export declare const ALLOWED_EXTENSIONS: readonly [".mp4"];
14
14
  /** 视频轨编码白名单(ISO BMFF sample entry fourcc):H.264 */
15
15
  export declare const ALLOWED_CODECS: readonly ["avc1", "avc3"];
16
- /** 标题最少字符数 */
16
+ /** 标题最少字符数(填了才校验) */
17
17
  export declare const MIN_TITLE_LENGTH = 6;
18
+ /** 标题最多字符数 */
19
+ export declare const MAX_TITLE_LENGTH = 16;
18
20
  /**
19
21
  * 校验视频是否满足视频号限制
20
22
  *
@@ -26,7 +28,7 @@ export declare function validateShipinhaoVideo(filePath: string, meta: VideoMeta
26
28
  /**
27
29
  * 校验标题是否满足视频号限制
28
30
  *
29
- * 标题为可选参数:未传时不校验;传了就必须满足最少字符数。
31
+ * 标题为可选参数:未传或为空白时不校验;填了就必须在 6-16 个字符之间。
30
32
  * 按 Unicode 码点计数,避免 emoji 等字符被算成多个。
31
33
  *
32
34
  * @param title 标题,可为空