@chatoctopus/timeline

中文文档
0.3.0发布于 2026/06/24MITTypeScriptES Module近 30 天下载 1723

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

中文使用文档
文档目录24 节
  1. 安装
  2. 国 际
  3. 图标
  4. 快速启动
  5. 从已存在的工程文件导入
  6. 格式转换
  7. 从媒体文件中建立时间表
  8. 手动构建时长
  9. API 参考
  10. 高级别职能
  11. 格式 - 特定函数
  12. 时间公用事业
  13. 验证
  14. 探测
  15. 类型
  16. 支持的格式
  17. 核查
  18. 快速烟雾测试
  19. 建筑
  20. 如何运作
  21. 捐款
  22. 承认
  23. 商标
  24. 许可证

@ chatoctopus/ 时间线

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

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

安装

npm install @chatoctopus/timeline

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

国 际

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

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格式.

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"))

格式转换

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,而混合帧率的剪接如果不能始终如一地得到代表,则可能被拒绝.

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 }保持帧对齐.

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

丢失的导出注释 :

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 用于视频、音频或图像媒体

类型

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 在规定明确期限时.

构建器输入 :

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 数据.xmlAdobe Primiere Pro, DaVinci 决议对对
开放时间线IO.otio18+、Hiero、rv和OTIO生态系统对对

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

核查

运行测试套件 :

npm test

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

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

进行覆盖测试 :

npm run test:coverage

类型检查而不排放 :

npm run lint

构建 :

npm run build

快速烟雾测试

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() 与两者的行为相匹配 黄油剪接 (鲁比)和 切开器 (去)这个图书馆的取自.

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

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

捐款

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

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

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

此重写每条媒体路径到中性占位符 。 项目名称, 夹片 名称和标记文本为 没有 被洗干净了 手边检查一下 然后打开一个 将文件添加到 tests/fixtures/,或打开 a 共享时间表文件 问题和 随附相接. 见 捐款额 以全向导.

承认

这个项目借鉴了来自 buttercut 财务报告和审定财务报表 cutlass我们感激地承认这些项目是上游的灵感.

商标

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

许可证

麻省理工学院

版本与发布记录

@chatoctopus/timeline 共发布 4 个版本,首次发布于 2026/03/07;过去 12 个月发布了 4 个版本。

版本发布日期距今
0.3.0latest2026/06/244 个月前
0.2.02026/03/197 个月前
0.1.12026/03/078 个月前
0.1.02026/03/078 个月前

关于 @chatoctopus/timeline 的常见问题

@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 和提交记录判断。