# @chatoctopus/timeline 中文文档

规范地址：https://npmcn.com/package/%40chatoctopus/timeline/

版本：0\.3\.0
npm 元数据更新时间：2026-06-24T12:30:56.039Z
中文译文更新时间：2026-11-09T21:20:05.072Z
软件包许可：MIT

本文由上游 README 翻译，可能存在偏差，请结合原文核对 API、命令与配置。版权与许可归原作者所有。

原始 npm 页面：https://www.npmjs.com/package/%40chatoctopus/timeline
原文对照：https://npmcn.com/package/%40chatoctopus/timeline/?lang=original
项目主页：https://github.com/ChatOctopus/timeline#readme
源码仓库：https://github.com/ChatOctopus/timeline

## 关键信息（来自 npm 元数据）

- 包体积（解压后）：416 kB，98 个文件
- 模块格式：ES Module
- TypeScript 类型：包内自带
- Node.js 要求：\>=18\.0\.0
- 运行依赖：1 个
- 首次发布：2026-03-07T05:53:55.999Z
- 最新版本发布：2026-06-24T12:30:55.915Z
- 近 30 天下载量：1723（2026-10-10 至 2026-11-08，npm 官方下载统计）
- 已发布版本数：4（近 12 个月 4 个）

## 中文简介

Adobe Premiere Pro、 DaVinci Resolution 和 OpenTimelineIO 的导入和导出视频编辑时间表

## 安装

```sh
npm install @chatoctopus/timeline
```

也可以使用：`pnpm add @chatoctopus/timeline`、`yarn add @chatoctopus/timeline`、`bun add @chatoctopus/timeline`

## README

# @ chatoctopus/ 时间线

Adobe Premiere Pro、DaVinci Resolution和OpenTimelineIO的视频编辑时间表.

生成造型良好的FCPXML 1.8 (Final Cut Pro),FCP7 XML / xmeml v5 (Primiere, Resolution),和 OTIO (OpenTimelineIO) 有帧精确的理性时间数学——没有浮点漂移.

## 安装

```bash
npm install @chatoctopus/timeline
```

需要节点.js QQ 18. 一揽子措施仅限无害环境管理。 对于 `buildTimelineFromFiles()` 或者说 `probeMediaReference()`, (中文(简体) ), [FFmpeg/FF探测器](https://ffmpeg.org/) 必须在您的路径上安装 。 格式之间的转换不需要FFmpeg/FFprobe.

## 国 际

包裹船装有 `timeline` CLI专注于格式转换和验证:

```bash
npx @chatoctopus/timeline convert ./edit.fcpxml --to otio --out ./edit.otio
npx @chatoctopus/timeline validate ./edit.xml
npx @chatoctopus/timeline validate ./edit.otio --json
```

### 图标

| 命令 | 说明 |
| --- | --- |
| `convert <input> --to <fcpx|premiere|resolve|otio> [--out <path>]` | 自动检测输入格式,转换为目标编辑格式,并写入文件(`--out`)或作取出. 进口和亏损出口警告会写到stderr. |
| `validate <input> [--json]` | 验证时间段完整性和框架对齐性;在硬错误上输出非零 |
| `sanitize <input> [--out <path>]` | 重写中性占位符的绝对媒体路径, 这样一个工程文件就可以安全地作为测试固定共享 。 逐一审查项目/剪接名称和标记文本. |

## 快速启动

### 从已存在的工程文件导入

自动检测FCPXML,xmeml,或OTIO格式.

```ts
import { importTimeline, exportTimeline } from "@chatoctopus/timeline"
import { readFileSync, writeFileSync } from "fs"

// Read a Final Cut Pro project
const fcpxml = readFileSync("project.fcpxml", "utf-8")
const { timeline, warnings } = importTimeline(fcpxml)

console.log(`Imported "${timeline.name}" with ${timeline.tracks.length} tracks`)
if (warnings.length > 0) console.warn("Warnings:", warnings)

// Convert to Premiere Pro format
writeFileSync("project.xml", exportTimeline(timeline, "premiere"))
```

### 格式转换

```ts
import { importTimeline, exportTimeline } from "@chatoctopus/timeline"
import { readFileSync, writeFileSync } from "fs"

// Premiere XML -> Final Cut Pro
const premiereXml = readFileSync("edit.xml", "utf-8")
const { timeline } = importTimeline(premiereXml)
writeFileSync("edit.fcpxml", exportTimeline(timeline, "fcpx"))

// Final Cut Pro -> DaVinci Resolve
const fcpxml = readFileSync("edit.fcpxml", "utf-8")
const { timeline: tl } = importTimeline(fcpxml)
writeFileSync("edit-resolve.xml", exportTimeline(tl, "resolve"))

// OTIO -> Final Cut Pro
const otio = readFileSync("project.otio", "utf-8")
const { timeline: tl2 } = importTimeline(otio)
writeFileSync("project.fcpxml", exportTimeline(tl2, "fcpx"))

// Any format -> OTIO
const anyFile = readFileSync("timeline.fcpxml", "utf-8")
const { timeline: tl3 } = importTimeline(anyFile)
writeFileSync("timeline.otio", exportTimeline(tl3, "otio"))
```

### 从媒体文件中建立时间表

最简单的路径:提供文件路径和可选修剪点. 元数据通过 FF Probe 自动提取到内置 `ExternalReference` 对象.

`buildTimelineFromFiles()` 严格验证修剪输入 : `startAt` 财务报告和审定财务报表 `duration` 必须是有限、非负数, `0` 图像需要明确 `duration`,而混合帧率的剪接如果不能始终如一地得到代表,则可能被拒绝.

```ts
import { buildTimelineFromFiles, exportTimeline } from "@chatoctopus/timeline"
import { writeFileSync } from "fs"

const timeline = await buildTimelineFromFiles("Wedding Highlights", [
  { path: "/footage/ceremony.mp4", startAt: 30, duration: 10 },
  { path: "/footage/reception.mp4", duration: 15 },
  { path: "/footage/speeches.mp4", startAt: 120, duration: 20 },
  { path: "/slides/title-card.png", duration: 3 },
])

// Final Cut Pro
writeFileSync("wedding.fcpxml", exportTimeline(timeline, "fcpx"))

// Adobe Premiere Pro
writeFileSync("wedding.xml", exportTimeline(timeline, "premiere"))

// DaVinci Resolve
writeFileSync("wedding.xml", exportTimeline(timeline, "resolve"))

// OpenTimelineIO (universal interchange)
writeFileSync("wedding.otio", exportTimeline(timeline, "otio"))
```

### 手动构建时长

为了全面控制,建造OTIO-第一 `Timeline` 模式直接。 所有时间使用 `Rational` 数字(`{ num, den }`保持帧对齐.

```ts
import {
  exportTimeline,
  rational,
  ZERO,
  FRAME_RATES,
} from "@chatoctopus/timeline"
import type { Timeline } from "@chatoctopus/timeline"
import { writeFileSync } from "fs"

const timeline: Timeline = {
  name: "My Edit",
  format: {
    width: 1920,
    height: 1080,
    frameRate: FRAME_RATES["29.97"], // { num: 30000, den: 1001 }
    audioRate: 48000,
    colorSpace: "1-1-1 (Rec. 709)",
  },
  tracks: [
    {
      kind: "video",
      name: "V1",
      items: [
        {
          kind: "clip",
          name: "interview",
          mediaReference: {
            type: "external",
            name: "interview.mp4",
            targetUrl: "file:///footage/interview.mp4",
            mediaKind: "video",
            availableRange: {
              startTime: ZERO,
              duration: rational(9000 * 1001, 30000), // 9000 frames at 29.97fps
            },
          },
          sourceRange: {
            startTime: rational(300 * 1001, 30000), // start from frame 300 in source
            duration: rational(150 * 1001, 30000), // 150 frames = ~5 seconds
          },
          metadata: {
            role: "dialogue",
          },
        },
      ],
    },
  ],
}

writeFileSync("output.otio", exportTimeline(timeline, "otio"))
writeFileSync("output.fcpxml", exportTimeline(timeline, "fcpx"))
```

`Timeline` 是OTIO,FCPXML和xmeml工作流程的API.

## API 参考

### 高级别职能

| 函数 | 说明 |
| --- | --- |
| `exportTimeline(timeline, editor, options?)` | 导出a `Timeline`。 。 。 . `editor` 实值 `"fcpx"`, (中文(简体) ), `"premiere"`, (中文(简体) ), `"resolve"`,或 `"otio"`。 。 。 . |
| `importTimeline(content)` | 将 FCPXML、 xmeml 或 OTIO 分析为 `Timeline`。 。 。 . |
| `buildTimelineFromFiles(name, files)` | 使用 FF 检测和构建线性文件 `Timeline` 与内置媒体引用. |
| `createTimeline(options)` | 创建一个 `Timeline` 带有用于合成或程序编辑的默认格式值. |

### 格式 - 特定函数

| 函数 | 说明 |
| --- | --- |
| `writeFCPXML(timeline, options?)` | 生成 FCPXML 1. 8 字符串 `Timeline` |
| `readFCPXML(xmlString)` | 将 FCPXML 分析为 `Timeline` |
| `writeXMEML(timeline, options?)` | 生成 xmeml v5 字符串 `Timeline` |
| `readXMEML(xmlString)` | 将 x meml 分析为 `Timeline` |
| `writeOTIO(timeline)` | 生成 OTIO JSON 从 `Timeline` |
| `readOTIO(jsonString)` | 将OTIO JSON分析为 `Timeline` |

丢失的导出注释 :

```ts
exportTimeline(timeline, "fcpx", {
  onWarning(message) {
    console.warn(message)
  },
})
```

使用 `onWarning` 如果您想要在切换、标记、元数据、缺失的引用或其他只使用核心字段时得到通知,则导出到 FCPXML 或 xmeml .

过渡是核心模型中的重叠项目. `computeTimelineDuration()` 说明这种重叠,而目前的FCPXML和xmeml则输出平整的向枪托切换并警告,因为这些适配器尚未释放出本土的过渡元素.

### 时间公用事业

所有时间使用 `Rational` (单位:千美元)`{ num: number, den: number }`)来避免浮点漂移.

| 函数 | 说明 |
| --- | --- |
| `rational(num, den)` | 创建简化的合理数字 |
| `add(a, b)` | 添加两个理性 |
| `subtract(a, b)` | 减法( 缩略语为零) |
| `toSeconds(r)` | 将理性转换为浮动秒 |
| `toFCPString(r)` | 格式为 FCP 时间字符串(`"1001/24000s"`(中文(简体) ) |
| `parseFCPString(s)` | 解析 FCP 时间字符串回到理性 |
| `secondsToFrameAligned(secs, frameRate)` | 转换秒, 折叠到最近的框架边界 |
| `toFrames(duration, frameDuration)` | 转换合理到帧数 |
| `parseTimecode(tc, frameRate)` | 解析 SMPTE 时码( S)`"01:00:00;00"`),并有下限支持 |
| `FRAME_RATES` | 常见预设 : `"23.976"`, (中文(简体) ), `"24"`, (中文(简体) ), `"25"`, (中文(简体) ), `"29.97"`, (中文(简体) ), `"30"`, (中文(简体) ), `"50"`, (中文(简体) ), `"59.94"`, (中文(简体) ), `"60"` |

### 验证

| 函数 | 说明 |
| --- | --- |
| `validateTimeline(timeline)` | 返回数组 `ValidationError` (检查介质对比,源范围,帧对齐,维度) |
| `hasErrors(results)` | `true` 如果有重大错误(不仅仅是警告) |
| `computeTimelineDuration(timeline)` | 从所有音轨项目计算总持续时间 |

### 探测

| 函数 | 说明 |
| --- | --- |
| `probeMediaReference(filePath)` | 在文件上运行FFprobe并返回一个人口稠密的 `ExternalReference` 用于视频、音频或图像媒体 |

## 类型

```ts
interface Timeline {
  name: string
  format: NLEFormat
  tracks: Track[]
  metadata?: Record<string, unknown>
  markers?: Marker[]
  globalStartTime?: Rational
}

interface NLEFormat {
  width: number
  height: number
  frameRate: Rational // e.g. { num: 30000, den: 1001 } for 29.97fps
  audioRate: number // e.g. 48000
  audioChannels?: number
  audioLayout?: string
  colorSpace?: string
}

type TrackItem = Clip | Gap | Transition

interface Track {
  kind: "video" | "audio"
  name?: string
  items: TrackItem[]
  metadata?: Record<string, unknown>
  markers?: Marker[]
  enabled?: boolean
}

interface Clip {
  kind: "clip"
  name: string
  mediaReference: MediaReference
  sourceRange?: TimeRange
  metadata?: Record<string, unknown>
  markers?: Marker[]
  enabled?: boolean
}

interface Gap {
  kind: "gap"
  sourceRange: TimeRange
  metadata?: Record<string, unknown>
  enabled?: boolean
}

interface Transition {
  kind: "transition"
  name?: string
  transitionType?: string
  inOffset: Rational
  outOffset: Rational
  metadata?: Record<string, unknown>
}

interface TimeRange {
  startTime: Rational
  duration: Rational
}

type MediaReference = ExternalReference | MissingReference

interface ExternalReference {
  type: "external"
  targetUrl: string
  name?: string
  mediaKind?: "video" | "audio" | "image" | "unknown"
  availableRange?: TimeRange
  metadata?: Record<string, unknown>
  streamInfo?: StreamInfo
}

interface MissingReference {
  type: "missing"
  name?: string
  metadata?: Record<string, unknown>
}

interface StreamInfo {
  hasVideo?: boolean
  hasAudio?: boolean
  width?: number
  height?: number
  frameRate?: Rational
  audioRate?: number
  audioChannels?: number
  colorSpace?: string
}

type NLEEditor = "fcpx" | "premiere" | "resolve" | "otio"
```

仍然将图像建模为 `ExternalReference` 对象为 `mediaKind: "image"` 在正常的视频轨道。 片段通过 `sourceRange`,以及 `buildTimelineFromFiles()` 将包含一个 `availableRange` 在规定明确期限时.

构建器输入 :

```ts
interface TimelineFileInput {
  path: string
  startAt?: number
  duration?: number
  track?: number
  kind?: "video" | "audio"
}

interface CreateTimelineOptions {
  name: string
  format?: Partial<NLEFormat>
  tracks?: Track[]
  metadata?: Record<string, unknown>
  markers?: Marker[]
  globalStartTime?: Rational
}
```

## 支持的格式

| 格式 | 延长 | 编辑器/工具 | 读取 | 写入 |
| --- | --- | --- | --- | --- |
| FCPXML 1 | `.fcpxml` | 最终剪接Pro | 对 | 对 |
| xmeml v5 数据 | `.xml` | Adobe Primiere Pro, DaVinci 决议 | 对 | 对 |
| 开放时间线IO | `.otio` | 18+、Hiero、rv和OTIO生态系统 | 对 | 对 |

FCPXML 导入封面 `asset-clip`\- 风格的脊椎 -- DaVinci 解析输出和这个软件包产生的东西。 最后切口的集装箱要素`<clip>`, (中文(简体) ), `<sync-clip>`, (中文(简体) ), `<mc-clip>`, (中文(简体) ), `<ref-clip>`, (中文(简体) ), `<audition>`, (中文(简体) ), `<title>`尚未解析的,将用一个警告而省略.

## 核查

运行测试套件 :

```bash
npm test
```

从 NLEs 导出的真实工程文件存在 `tests/fixtures/`。所有文件都会自动被扫描 `tests/fixtures.test.ts`:导入,验证,导出到所有格式,并进行往返. 要扩大报道范围,请从编辑器中导出一个时间表,对媒体路径进行消毒,然后将文件放入--不需要测试代码.

Fixture测试证明包读取了编辑器所写的. 反之 -- -- 编辑者接受生成的文件 -- -- 在发布前仍需要在目标应用程序中进行人工导入检查.

进行覆盖测试 :

```bash
npm run test:coverage
```

类型检查而不排放 :

```bash
npm run lint
```

构建 :

```bash
npm run build
```

### 快速烟雾测试

```bash
node --input-type=module -e "
import { exportTimeline, rational, ZERO, FRAME_RATES } from './dist/index.js';

const timeline = {
  name: 'Smoke Test',
  format: {
    width: 1920, height: 1080,
    frameRate: FRAME_RATES['29.97'],
    audioRate: 48000,
  },
  tracks: [{
    kind: 'video',
    items: [{
      kind: 'clip',
      name: 'clip',
      mediaReference: {
        type: 'external',
        name: 'clip.mp4',
        targetUrl: 'file:///tmp/clip.mp4',
        mediaKind: 'video',
        availableRange: {
          startTime: ZERO,
          duration: rational(300 * 1001, 30000),
        },
      },
      sourceRange: {
        startTime: ZERO,
        duration: rational(150 * 1001, 30000),
      },
    }],
  }],
};

const fcpxml = exportTimeline(timeline, 'fcpx');
const xmeml = exportTimeline(timeline, 'premiere');
const otio = exportTimeline(timeline, 'otio');

console.log('FCPXML:', fcpxml.includes('<fcpxml') ? 'OK' : 'FAIL');
console.log('xmeml:', xmeml.includes('<xmeml') ? 'OK' : 'FAIL');
console.log('OTIO:', otio.includes('Timeline.1') ? 'OK' : 'FAIL');
console.log('Done.');
"
```

## 建筑

```
src/
├── index.ts           Public API: exportTimeline, importTimeline, createTimeline, buildTimelineFromFiles
├── types.ts           OTIO-first core types
├── time.ts            Rational arithmetic, frame alignment, SMPTE timecode parsing
├── probe.ts           FFprobe -> ExternalReference probing
├── media-kind.ts      Shared file-extension media kind inference
├── builders.ts        Core-native timeline construction helpers
├── validate.ts        Core validation and duration computation
├── fcpxml/
│   ├── writer.ts      FCPXML 1.8 generation
│   └── reader.ts      FCPXML parsing
├── xmeml/
│   ├── writer.ts      xmeml v5 generation (Premiere / Resolve)
│   └── reader.ts      xmeml parsing
└── otio/
    ├── writer.ts      OpenTimelineIO JSON generation
    └── reader.ts      OpenTimelineIO JSON parsing
```

## 如何运作

**合理时间数学** 是图书馆的核心。 所有NLE软件在内部使用帧相通的时点——将持续时间表示为理性分数,如 `1001/30000s` (29.97fps的一个帧). 使用浮点秒会导致帧漂移和"不在编辑帧边界上""最终剪接Pro"出错.

每个剪辑持续时间和抵消时间都经过 `secondsToFrameAligned()` 与两者的行为相匹配 [黄油剪接](https://github.com/barefootford/buttercut) (鲁比)和 [切开器](https://github.com/andrewarrow/cutlass) (去)这个图书馆的取自.

**三种交换格式** 涵盖所有主要编辑和工具:

-   **FCPXML 1** 最终剪接 Pro -- -- 无轨磁性时间线 `<asset-clip>` a 内的元素 `<spine>`
-   **xmeml v5 数据** 以音轨为基础,并与链接 `<clipitem>` 视频和音频元素
-   **开放时间线IO** (单位:千美元)`.otio`) -- 由Academy软件基金会支持的行业标准JSON交换格式. OTIO充当了通用的中枢:任何能说OTIO的工具都可以从任何其他格式获得即时访问时间. 在这个包中,OTIO现在直接向核心模型映射,包括明显的缺口,过渡,标记,元数据,以及内置媒体参考.

## 捐款

最有用的贡献是: **从编辑器导出真实的时间线** - 说吧 特别是锻炼适配器的特性 还没有完全覆盖 (过渡、标记、多相机、下帧时间码、混合帧率、, 嵌入式/组合式剪辑,标题). 每个文件在 `tests/fixtures/` 自动 导入、验证、导出到所有格式,并绕行,从而固定 不需要测试代码 .

**分享前先放卫生.** 真实输出嵌入了绝对介质路径( 您的 用户名、驱动器、客户端/项目名称)。 先擦擦他们:

```bash
npx @chatoctopus/timeline sanitize ./your-export.fcpxml --out ./your-export.sanitized.fcpxml
```

此重写每条媒体路径到中性占位符 。 项目名称, 夹片 名称和标记文本为 **没有** 被洗干净了 手边检查一下 然后打开一个 将文件添加到 `tests/fixtures/`,或打开 a [共享时间表文件](https://npmcn.com/package/issues/new?template=timeline-file.yml) 问题和 随附相接. 见 [捐款额](https://npmcn.com/package/%40chatoctopus/timeline/CONTRIBUTING.md) 以全向导.

## 承认

这个项目借鉴了来自 [`buttercut`](https://github.com/barefootford/buttercut) 财务报告和审定财务报表 [`cutlass`](https://github.com/andrewarrow/cutlass)我们感激地承认这些项目是上游的灵感.

## 商标

Final Cut Pro是苹果公司的一个商标. Adobe Premiere Pro是Adobe的商标. DaVinci Resolution是黑魔设计Pty有限公司的商标. 其他产品名称,标志,品牌均为各自所有者的财产.

## 许可证

麻省理工学院

## 常见问题

### @chatoctopus/timeline 是什么？

Adobe Premiere Pro、 DaVinci Resolution 和 OpenTimelineIO 的导入和导出视频编辑时间表

### 如何安装 @chatoctopus/timeline？

在项目目录运行 npm install @chatoctopus/timeline，或使用 pnpm add / yarn add / bun add。它还提供命令行工具 timeline，可以用 npx timeline 直接运行。

### @chatoctopus/timeline 支持 TypeScript 吗？

支持。包内自带 TypeScript 类型声明（package\.json 声明了 types 入口），安装后即可获得类型提示，无需再安装 @types 包。

### @chatoctopus/timeline 支持 ESM 还是 CommonJS？

以 ES Module 形式发布，推荐使用 import 引入。在 CommonJS 项目中，Node\.js 20\.19\+ / 22\.12\+ 可以直接 require\(\) 不含顶层 await 的 ES Module，更早的版本需要改用动态 import\(\)。

### @chatoctopus/timeline 需要什么版本的 Node\.js？

package\.json 的 engines 字段要求 Node\.js \>=18\.0\.0。版本不符时 npm 默认只给出警告，开启 engine-strict 后会拒绝安装。

### @chatoctopus/timeline 可以商用吗？

@chatoctopus/timeline 使用 MIT 许可。宽松许可：允许商业使用、修改和再分发，通常只需在分发时保留原版权与许可声明。以上为概括，不构成法律意见，请以许可原文为准。

### @chatoctopus/timeline 的下载量有多少？

根据 npm 官方下载统计，@chatoctopus/timeline 在 2026/10/10 – 2026/11/08 这 30 天内被下载 1,723 次，日均约 57 次。下载量会把 CI 构建、镜像同步和作为其他包依赖的安装一并计入，适合横向比较热度，不能直接等同于使用人数。

### @chatoctopus/timeline 还在维护吗？

最新版本 0\.3\.0 发布于 2026/06/24（4 个月前）；至今共发布 4 个版本，其中过去 12 个月发布了 4 个；首次发布于 2026/03/07。发布频率只是参考信号：功能稳定的工具可能很少需要更新，建议结合源码仓库的 issue 和提交记录判断。

