npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

ffmpeg-fore

v1.0.19-4

Published

ffmpeg+canvas

Readme

音视频编辑工具

npm install ffmpeg-fore
or
pnpm install ffmpeg-fore

集成: main.ts
...
import FF from 'ffmpeg-fore';
corePath: corePath地址,默认为空在线引入
corePath: workerPath,默认为空在线引入
corePath: wasmPath,默认为空在线引入
const ff = new FF(
corePath: '',
workerPath: '',
wasmPath: '',
);
或者:const ff = new FF((res: any) => {
const { ratio, time } = res;
});
const app = createApp(App);
app.config.globalProperties.$ff = ff;
...

本地https环境配置:vite.config.ts
server: ...
host: '0.0.0.0'
https: {
key: resolve(__dirname, 'key.pem'),
cert: resolve(__dirname, 'cert.pem'),
},
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp'
}

使用(demo.vue):

import { getCurrentInstance } from 'vue'
const { appContext } = getCurrentInstance()!;
const ff = appContext.config.globalProperties.$ff;
import { SPACE } from 'ffmpeg-fore';

*来源文件:已存入虚拟缓存的文件/要操作的文件,默认名称: source
*无来源文件:ff.cache存入虚拟缓存 urls: 在线文件无需填写name,本地文件必填name

  • SPACE:

enum SOURCE {
    LOCAL = 'local',
    NETWORK = 'network',
}
interface RESULT {
    startTime?: number | string;
    endTime?: number | string;
    path?: string;
    url?: string;
    subtitles?: SPACE.RESULT[];
    text?: string;
}
  • 上传视频 / 音频 / 图片 至虚拟缓存(来源文件):

/*
* @params {string} url     required 文件地址
* @params {string} name    文件名称 默认source.mp4
* @params {boolean} status  是否加载插件,默认false,单独调用true
* 
* @returns {string} 文件url
* */
el-upload: file => { url: file.url, name: file.name }
const url: string = await ff.cache({
    url: file.url,
    name: `source.${ff.format(file.name)}`,
    status: true,
})
  • 文件下载:

/*
* @params {string} url     required 文件地址
* @params {string} name    文件下载名称
* @params {string} status  下载后是否清除缓存 默认 false
* 
* @returns {boolean} 下载状态提示
* */
const status: boolean = await ff.download({
    url: '',
    name: 'download',
    status: false
});
  • 获取文件格式:

/*
* @params {string} required 文件地址
* 
* @returns {string} 文件格式
* */
const format: string = await ff.format('');
  • 视频剪辑:

/*
* @params {string} startTime   required 开始时间 '00:00:00'
* @params {string} endTime     required 开始时间 '00:00:00'
* @params {string} outputName  剪辑后名称(格式:mp4) 默认名称clip
* @params {string} type 分类 默认:network
* @params type='local' required url 文件地址  el-upload -> file.url 
* @params type='local' name 文件名称  el-upload -> file.name
* @params type='network' required url 文件在线地址
* @params type='network' name 默认为空,无需填写
* 
* @returns {string} 文件url
* */
const url: string = await ff.videoClip({
    startTime: '00:00:00',  
    endTime: '00:00:01', 
    name: '', 
    url: '',
    type: SPACE.SOURCE.NETWORK,
    outputName: 'clip.mp4',
});
  • 音频剪辑:

/*
* @params {string} startTime   required 开始时间 '00:00:00'
* @params {string} endTime     required 开始时间 '00:00:00'
* @params {string} outputName  剪辑后名称(格式:mp3) 默认名称clip
* @params {string} type 分类 默认:network
* @params type='local' required url 文件地址  el-upload -> file.url 
* @params type='local' name 文件名称  el-upload -> file.name
* @params type='network' required url 文件在线地址
* @params type='network' name 默认为空,无需填写
* 
* @returns {string} 文件url
* */
const url: string = await ff.audioClip({
    startTime: '00:00:00',  
    endTime: '00:00:01',
    name: '',
    url: '',
    type: SPACE.SOURCE.NETWORK,
    outputName: 'clip.mp3',
});
  • 视频合成:

/*
* @params {string} type  默认本地文件local,在线文件:network
* @params {string} outputName 合成名称(格式:mp4) 默认名称video-merge.mp4
* @params {string} sws 视频质量,默认bicubic
* @params sws = 'bicubic' :平衡速度与质量
* @params sws = 'lanczos' :高质量,但较慢
* @params sws = 'neighbor' :最快,低质量
* @params {number} width 合成视频宽度 默认0:对比最宽视频
* @params {number} height 合成视频高度 默认0:对比最高视频
* @params width+height同时输入>0有效,单一无效
* @params {<<string>object>[]} urls  required 
* @params {<string>object} type='local' url 文件地址
* @params {<string>object} type='local' name 文件名称  例:test.mp4
* @params {<string>object} type='network' url 文件在线地址

* 
* @returns {string} 文件url
* */
type === 'local':
el-upload: file => { url: file.url, name: file.name }
urls: [{ url: file.url, name: file.name }]

type === 'network':
urls: [ {url: '视频在线地址'} , {url: '视频在线地址'}]

const url: string = await ff.videoMerge({
    urls: [],
    type: SPACE.SOURCE.LOCAL,
})
  • 视频添加字幕:

/*
* @params {<<string>object>[]} drawText  required 
* @params {<string>object} text 字幕内容
* @params {<string>object} fontSize 字体大小,
* @params {<string>object} fontColor 字体颜色,
* @params {<string>object} startTime 开始时间,
* @params {<string>object} endTime 结束时间,
* @params {<string>object} timeType 默认:number,可选string,
* timeType='number': startTime/endTime类型number,例:startTime = 0
* timeType='string': startTime/endTime类型string,例:startTime = '00:00:00'
* @params {<string>object} position 字幕位置,默认bottom, top / center,
* @params {string} fontUrl 字幕字体在线地址或上传的地址
* @params {string} type 分类 默认:network
* @params type='local' required url 文件地址  el-upload -> file.url 
* @params type='local' name 文件名称  el-upload -> file.name
* @params type='network' required url 文件在线地址
* @params type='network' name 默认为空,无需填写
* 
* @returns {string} 文件url
* */
const url: string = await ff.videoAddSubtitles({
    fontUrl: '',
    url: '',
    name: '',
    type: SPACE.SOURCE.NETWORK,
    drawText: [
        { text: 'First Text',fontSize: 24, fontColor: 'yellow', startTime: 0, endTime: 5 },
    ],
})
  • 视频帧:

/*
* @params {string} source  来源文件 默认:source.mp4
* @params {string} dir     虚拟缓存目录 默认:frame
* @params {string} type 分类 默认:network
* @params type='local' required url 文件地址  el-upload -> file.url 
* @params type='local' name 文件名称  el-upload -> file.name
* @params type='network' required url 文件在线地址
* @params type='network' name 默认为空,无需填写
* 
* @returns {<string>[]} 帧地址,格式:jpeg
* */

const urls: string[] = await ff.frames({
    url: '',
    type: SPACE.SOURCE.NETWORK,
})
  • 音频比特率图:

/*
* @params {string} type 分类 默认:network
* @params type='local' required url 文件地址  el-upload -> file.url 
* @params type='local' name 文件名称  el-upload -> file.name
* @params type='network' required url 文件在线地址
* @params type='network' name 默认为空,无需填写
* 
* @returns {<string>[]} 比特率图地址
* */

const urls: string[] = await ff.bitRate({
    url: '',
    type: SPACE.SOURCE.NETWORK,
})
  • 初始化画布轨道(单轨道):

/*
* @params {<string>[]} trackList 帧图片列表
* @params {HTMLDivElement} container 容器DIV
* @params {boolean} baseLineStatus 默认false,基准线,true:显示,false:不显示
* @params {<object>[]} Fn 事件 
* @params {<string>object} type click: 点击事件,scroll: 滑动事件
* @params {<string>object} time type=click 点击的时间节点
* @params {<string>object} path type=click 点击的帧地址
* @params {<string>object} time type=scroll 滑动到基准线的时间节点
* @params {<string>object} path type=scroll 滑动到基准线的帧地址
*
* */

const trackList: string[] = await ff.frames();

ff.initFrame({
    trackList,
    container: container.value,
    Fn: (data: any) => {
        const { path, time, index, type } = data;
        //  TODO OTHER THINGS
    },
});
  • 轨道剪辑(单轨道):

/*
* @params {boolean} status 
* @params status = true 开启
* @params status = false 关闭
* */

await ff.clipFrame({
    status: boolean,
});
  • 轨道剪辑确认(单轨道):

/*
* @returns {<number | string>object} res
* @returns {number} code  0:成功,成功后自动关闭剪辑轨道
* @returns {string} startTime  开始时间
* @returns {string} endTime  结束时间
* @returns {string} msg  提示信息
* */

const res: SPACE.FRAME = await ff.confirmFrame();
const { startTime, endTime, code, msg } = res;
... TODO OTHER THINGS ...
  • 获取视频信息:

/*
* @params {string} 视频地址
* 
* @returns {<number | string>object} 
* @returns {number} width 视频宽 
* @returns {number} height 视频高 
* @returns {number} duration 视频时常/秒, 例: 9.05s
* @returns {string} durationTime 视频时常/时间,例:'00:00:09' 
* */

const { width, height, duration, durationTime  } = await ff.getVideoInfo('')
  • 获取音频信息:

/*
* @params {string} 音频地址
* 
* @returns {<number | string>object} 
* @returns {number} duration 视频时常/秒, 例: 9.05s
* @returns {string} durationTime 视频时常/时间,例:'00:00:09' 
* @returns {string} bitrate 比特率(kbps)
* @returns {string} sampleRate 采样率(Hz)
* @returns {string} channels  声道数
* @returns {string} codec 编码格式(如 mp3、flac)
* */

const { duration, bitrate, sampleRate } = await ff.getAudioInfo('')
  • 视频截图:

/*
* @params {string} time required 截图时间 '00:00:00'
* @params {string} type 分类 默认:network
* @params type='local' required url 文件地址  el-upload -> file.url 
* @params type='local' name 文件名称  el-upload -> file.name
* @params type='network' required url 文件在线地址
* @params type='network' name 默认为空,无需填写
* 
* @returns {string} 文件url
* */
const url: string = await ff.videoCapture({
    time: '00:00:00',
    name: '',
    url: '',
    type: SPACE.SOURCE.NETWORK,
})
  • 音频剥离:

/*
* @params {string} type 分类 默认:network
* @params type='local' required url 文件地址  el-upload -> file.url 
* @params type='local' name 文件名称  el-upload -> file.name
* @params type='network' required url 文件在线地址
* @params type='network' name 默认为空,无需填写
* 
* @returns {string} 文件url,格式:mp3
* */
const url: string = await ff.audioPeel({
    url: '',
    name: '',
    type: SPACE.SOURCE.NETWORK,
})
  • 视频剥离:

/*
* @params {string} type 分类 默认:network
* @params type='local' required url 文件地址  el-upload -> file.url 
* @params type='local' name 文件名称  el-upload -> file.name
* @params type='network' required url 文件在线地址
* @params type='network' name 默认为空,无需填写
* 
* @returns {string} 文件url,无声
* */
const url: string = await ff.videoPeel({
    url: '',
    name: '',
    type: SPACE.SOURCE.NETWORK,
})
  • 音视频合成:

/*
* @params {string} url required  音频在线文件地址
* @params {string} name  音频缓存名称
* @params {string} source 来源文件,默认source.mp4
* @params {string} outputName 合成名称,默认名称av-merge.mp4
* @params {string} type 分类 默认:network
* @params type='local' required audioUrl 音频文件地址  el-upload -> file.url 
* @params type='local' audioName 音频文件名称  el-upload -> file.name
* @params type='local' required videoUrl 视频文件地址  el-upload -> file.url 
* @params type='local' videoName 视频文件名称  el-upload -> file.name
* @params type='network' required audioUrl 音频文件在线地址
* @params type='network' audioName 默认为空,无需填写
* @params type='network' required videoUrl 视频文件在线地址
* @params type='network' videoName 默认为空,无需填写
* 
* @returns {string} 视频url,格式:mp4
* */
const url: string = await ff.avMerge({
    audioUrl: '',
    audioName: 'av-audio.mp3',
    videoUrl: '',
    videoName: 'av-video.mp4',
    type: SPACE.SOURCE.NETWORK,
    outputName: 'av-merge.mp4',
})
  • 音频合成:

/*
* @params {string} outputName 合成名称,默认audio-merge.mp3
* @params {string} type 默认本地文件local,在线文件:network
* @params {<any>[]} urls  required 
* @params {<string>object} type='local' url 文件地址
* @params {<string>object} type='local' name 文件名称  例:test.mp3
* @params {<string>object} type='network' url 文件在线地址
* 
* @returns {string} 音频url,格式:mp3
* */
type === 'local':
el-upload: file => { url: file.url, name: file.name }
urls: [{ url: file.url, name: file.name }]

type === 'network':
urls: [{ url: '音频在线地址' }]

const url: string = await ff.audioMerge({
    urls: [],
    outputName: 'audio-merge.mp3',
    type: SPACE.SOURCE.LOCAL,
})
  • 图生视频:

/*
* @params {number} seconds 每张图片展示时间 默认:1s
* @params {string} type 默认本地文件local,在线文件:network
* @params {<any>[]} urls  required 
* @params {<string>object} type='local' url 文件地址
* @params {<string>object} type='local' name 文件名称  例:test.jpg
* @params {<string>object} type='network' url 文件在线地址
* 
* @returns {string} 视频url,格式:mp4
* */
type === 'local':
el-upload: file => { url: file.url, name: file.name }
urls: [{ url: file.url, name: file.name }]

type === 'network':
urls: [{ url: '图片在线地址'}]

const url: string = await ff.convertImageToVideo({
    urls: [],
    seconds: 1,
    type: SPACE.SOURCE.LOCAL
})
  • 视频添加水印图:

/*
* @params {string} source 来源文件   默认:source.mp4
* @params {string} outputName 合成名称,默认watermark.mp4
* @params {string} position 水印位置,默认TopLeft:左上角
* @params {string} position='TopLeft' 左上角
* @params {string} position='TopRight' 右上角
* @params {string} position='BottomLeft' 左下角
* @params {string} position='BottomRight' 右下角
* @params {string} type 默认在线文件:network,本地文件:local
* @params type='local' watermark/url 水印图/视频地址  el-upload -> file.url 
* @params type='local' watermarkName/name 水印图/视频名称  el-upload -> file.name
* @params type='network' watermark 文件在线地址
* @params type='network' watermarkName 默认为空
* Required:watermark、url
*
* @returns {string} 视频url,格式:源文件格式
* */

const url: string = await ff.videoWatermark({
    url: '',
    name: '',
    watermark: 'source.jpg',
    watermarkName: 'source.jpg',
    position: 'TopLeft',
    type: SPACE.SOURCE.LOCAL
});
  • 图片添加水印图:

/*
* @params {string} source 来源文件  默认:source.mp4
* @params {string} outputName 合成名称,默认watermark.jpeg
* @params {string} position 水印位置,默认TopLeft:左上角
* @params {string} position='TopLeft' 左上角
* @params {string} position='TopRight' 右上角
* @params {string} position='BottomLeft' 左下角
* @params {string} position='BottomRight' 右下角
* @params {string} type 默认在线文件:network,本地文件:local
* @params type='local' watermark/url 水印图/图片地址  el-upload -> file.url 
* @params type='local' watermarkName/name 水印图/图片名称  el-upload -> file.name
* @params type='network' watermark 文件在线地址
* @params type='network' watermarkName 默认为空
* Required:watermark、url
* 
* @returns {string} 图片url
* */

const url: string = await ff.imageWatermark({
    url: '',
    name: '',
    watermark: 'source.jpg',
    watermarkName: 'source.jpg',
    position: 'TopLeft',
    type: SPACE.SOURCE.LOCAL,
});
  • 时间间隔拆分视频:

/*
* @params {number | string} time 时间间隔/秒  默认:10,
* @params {string} type 分类 默认:network
* @params type='local' required url 文件地址  el-upload -> file.url 
* @params type='local' name 文件名称  el-upload -> file.name
* @params type='network' required url 文件在线地址
* @params type='network' name 默认为空,无需填写
*
* @returns {<<string>object>[]} res
* @returns {string} url 视频地址
* @returns {string} startTime 开始时间
* @returns {string} endTime 结束时间
* */

const res: SPACE.RESULT[] = await ff.videoCut({
    url: '',
    name: '',
    type: SPACE.SOURCE.NETWORK,
    time: 10,
});
  • 转场拆分视频:

/*
* @params {string} scene 场景变化阈值  默认:0.5
* @params {string} type 分类 默认:network
* @params type='local' required url 文件地址  el-upload -> file.url 
* @params type='local' name 文件名称  el-upload -> file.name
* @params type='network' required url 文件在线地址
* @params type='network' name 默认为空,无需填写
*
* @returns {<<string>object>[]} res
* @returns {string} url 视频地址
* @returns {string} startTime 开始时间
* @returns {string} endTime 结束时间
* */

const res: SPACE.RESULT[] = await ff.videoTransition({
    url: '',
    name: '',
    type: SPACE.SOURCE.NETWORK,
    scene: '0.5',
});
  • 声音拆分视频:

/*
* @params {number} volume 音量阈值,默认50  默认:1~100
* @params {number} interval  静音持续时长/秒   默认:1
* @params {string} type 分类 默认:network
* @params type='local' required url 文件地址  el-upload -> file.url 
* @params type='local' name 文件名称  el-upload -> file.name
* @params type='network' required url 文件在线地址
* @params type='network' name 默认为空,无需填写
*
* @returns {<<string>object>[]} res
* @returns {string} url 视频地址
* @returns {string} startTime 开始时间
* @returns {string} endTime 结束时间 
* */

const res: SPACE.RESULT[] = await ff.videoSilence({
    url: '',
    name: '',
    type: SPACE.SOURCE.NETWORK,
    volume: 50,
    interval: 1,
});
  • 视频提取字幕(OCR字幕识别不精准):

/*
* @params {string} keywords 关键字  默认:空
* @params {string} type 分类 默认:network
* @params type='local' required url 文件地址  el-upload -> file.url 
* @params type='local' name 文件名称  el-upload -> file.name
* @params type='network' required url 文件在线地址
* @params type='network' name 默认为空,无需填写
*
* @returns {<<string>object>[]} res  秒级
* keywords !== ''时:
* @returns {string} startTime 开始时间
* @returns {string} endTime 持续结束时间 
* @returns {string} url 视频地址
* @returns {<<string>object>[]} subtitles 字幕组,内容如下
* @returns {string} startTime 开始时间
* @returns {string} endTime 结束时间 
* @returns {string} text 字幕内容 
* keywords === ''时:
* @returns {string} url 视频地址
* @returns {string} startTime 开始时间 
* @returns {string} endTime 结束时间 
* @returns {string} text 字幕内容 
* */

const res: SPACE.RESULT[] = await ff.videoExtractSubtitles({
    url: '',
    name: '',
    type: SPACE.SOURCE.NETWORK,
    keywords: '',
});
  • 退出销毁:

await ff.exit();