{"id":22226461,"url":"https://github.com/zhw2590582/wfplayer","last_synced_at":"2025-04-04T19:11:45.180Z","repository":{"id":49782298,"uuid":"213881883","full_name":"zhw2590582/WFPlayer","owner":"zhw2590582","description":":ocean: WFPlayer.js is an audio waveform generator","archived":false,"fork":false,"pushed_at":"2024-04-02T06:54:30.000Z","size":20972,"stargazers_count":262,"open_issues_count":6,"forks_count":32,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-09-19T03:24:55.656Z","etag":null,"topics":["audio","audiocontext","canvas","generator","waveform"],"latest_commit_sha":null,"homepage":"https://wfplayer.js.org","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/zhw2590582.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-10-09T09:54:33.000Z","updated_at":"2024-09-11T12:47:47.000Z","dependencies_parsed_at":"2024-06-18T21:16:20.119Z","dependency_job_id":"fb2187c6-88f5-487f-aab0-1d738eba6fb3","html_url":"https://github.com/zhw2590582/WFPlayer","commit_stats":{"total_commits":188,"total_committers":4,"mean_commits":47.0,"dds":"0.015957446808510634","last_synced_commit":"d6be618c109a264a040a5ba31a8abbb6b53ce5ea"},"previous_names":[],"tags_count":1,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhw2590582%2FWFPlayer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhw2590582%2FWFPlayer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhw2590582%2FWFPlayer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/zhw2590582%2FWFPlayer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/zhw2590582","download_url":"https://codeload.github.com/zhw2590582/WFPlayer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247234922,"owners_count":20905854,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["audio","audiocontext","canvas","generator","waveform"],"created_at":"2024-12-03T00:29:09.661Z","updated_at":"2025-04-04T19:11:45.156Z","avatar_url":"https://github.com/zhw2590582.png","language":"JavaScript","funding_links":["https://www.paypal.me/harveyzack"],"categories":[],"sub_categories":[],"readme":"# WFPlayer\n\n![version](https://badgen.net/npm/v/wfplayer)\n![license](https://badgen.net/npm/license/wfplayer)\n![size](https://badgen.net/bundlephobia/minzip/wfplayer)\n\n\u003e WFPlayer.js is an audio waveform generator\n\n![Screenshot](./images/screenshot.png)\n\n## Demo\n\n[Checkout the demo](https://wfplayer.js.org/) from Github Pages\n\n## Features\n\n-   Create waveforms without loading the entire media file\n-   Customize cursor, progress, grid, ruler display and color\n-   Support for loading media urls and loading media dom elements (video tags and audio tags)\n-   Support for real-time change options like color or width etc\n-   Listen to the playback state of media elements for playback animation\n-   Adaptive parent element size and audio data\n-   And more...\n\n## Install\n\nInstall with `npm`\n\n```bash\n$ npm install wfplayer\n```\n\nOr install with `yarn`\n\n```bash\n$ yarn add wfplayer\n```\n\n```js\nimport WFPlayer from 'wfplayer';\n```\n\nOr umd builds are also available\n\n```html\n\u003cscript src=\"path/to/wfplayer.js\"\u003e\u003c/script\u003e\n```\n\nWill expose the global variable to `window.WFPlayer`.\n\n## Usage\n\nHTML\n\n```html\n\u003cdiv id=\"waveform\" style=\"width: 1000px; height: 300px\"\u003e\u003c/div\u003e\n\u003cvideo id=\"video\" src=\"path/to/video.mp4\"\u003e\u003c/video\u003e\n\n\u003c!-- or --\u003e\n\u003caudio id=\"audio\" src=\"path/to/audio.mp3\"\u003e\u003c/audio\u003e\n```\n\nJS\n\n```js\nvar wf = new WFPlayer({\n    container: document.querySelector('#waveform'),\n    mediaElement: document.querySelector('#video'),\n});\n\nwf.load(document.querySelector('#video'));\n\n// or\nwf.load('path/to/audio.mp3');\n```\n\n## API\n\n### Options\n\n```js\nvar wf = new WFPlayer({\n    // Mount the audio waveform of the dom\n    container: '#waveform',\n\n    // Whether to use scroll mode\n    scrollable: false,\n\n    // Media element like: video tag or audio tag\n    mediaElement: null,\n\n    // Whether use web worker\n    useWorker: true,\n\n    // Thw refresh delay time\n    refreshDelay: 50,\n\n    // Whether to display wave\n    wave: true,\n\n    // Waveform color\n    waveColor: 'rgba(255, 255, 255, 0.1)',\n\n    // Background color\n    backgroundColor: 'rgb(28, 32, 34)',\n\n    // Whether to display cursor\n    cursor: true,\n\n    // Cursor color\n    cursorColor: '#ff0000',\n\n    // Whether to display progress\n    progress: true,\n\n    // progress color\n    progressColor: 'rgba(255, 255, 255, 0.5)',\n\n    // Whether to display grid\n    grid: true,\n\n    // Grid color\n    gridColor: 'rgba(255, 255, 255, 0.05)',\n\n    // Whether to display ruler\n    ruler: true,\n\n    // Ruler color\n    rulerColor: 'rgba(255, 255, 255, 0.5)',\n\n    // Whether to display scrollbar\n    scrollbar: true,\n\n    // Scrollbar color\n    scrollbarColor: 'rgba(255, 255, 255, 0.25)',\n\n    // Whether to display ruler at the top\n    rulerAtTop: true,\n\n    // Pixel ratio\n    pixelRatio: window.devicePixelRatio,\n\n    // Which audio channel to render\n    channel: 0,\n\n    // Duration of rendering\n    duration: 10,\n\n    // The ratio of spaces on both sides\n    padding: 5,\n\n    // Waveform height scale ratio\n    waveScale: 0.8,\n\n    // Waveform Size ratio\n    waveSize: 1,\n\n    // Waveform cursor display position, default is center, optional values are: left , center\n    waveAlign: 'center',\n});\n```\n\n### Instance methods and properties\n\nLoad target:\n\n```js\n// The target can be the url address of media or a mediaElement or ArrayBuffer or Audiobuffer\nwf.load(target);\n```\n\nChange Channel:\n\n```js\nwf.changeChannel(1);\n```\n\nJump to a certain time:\n\n```js\nwf.seek(second);\n```\n\nJump to a certain time with smooth:\n\n```js\nwf.smoothSeek(second);\n```\n\nExport image:\n\n```js\nwf.exportImage();\n```\n\nModify option:\n\n```js\nwf.setOptions({\n    // Like change wave color\n    waveColor: 'red',\n});\n```\n\nDestroy instance:\n\n```js\nwf.destroy();\n```\n\n## Common Problem\n\n#### When decoding a video to an audio waveform, it will cause insufficient browser memory.\n\nIf the video volume is too large, it will cause the front-end decoding difficult. Best practice is to use the server's `FFMPEG`, convert the video into audio format `MP3`.\n\n`-ac` is the number of channels, `-ar` is a sample rate:\n\nBack End\n\n```bash\nffmpeg -i path/to/video.mp4 -ac 1 -ar 8000 path/to/audio.mp3\n```\n\nHTML\n\n```html\n\u003cdiv id=\"waveform\" style=\"width: 1000px; height: 300px\"\u003e\u003c/div\u003e\n\u003cvideo id=\"video\" src=\"path/to/video.mp4\"\u003e\u003c/video\u003e\n```\n\nJS\n\n```js\nvar wf = new WFPlayer({\n    container: document.querySelector('#waveform'),\n    mediaElement: document.querySelector('#video'),\n});\n\nwf.load('path/to/audio.mp3');\n\n// or\nfetch('path/to/audio.mp3')\n    .then((res) =\u003e res.arrayBuffer())\n    .then((arrayBuffer) =\u003e {\n        const uint8 = new Uint8Array(arrayBuffer);\n        wf.load(uint8);\n    });\n```\n\n#### If you really don't want to use the server to transfer, I recommend to use `@ffmpeg/ffmpeg`：\n\n```bash\nnpm i -S @ffmpeg/ffmpeg\n```\n\nHTML\n\n```html\n\u003cdiv id=\"waveform\" style=\"width: 1000px; height: 300px\"\u003e\u003c/div\u003e\n\u003cvideo id=\"video\" src=\"path/to/video.mp4\"\u003e\u003c/video\u003e\n\u003cinput type=\"file\" id=\"file\" /\u003e\n```\n\nJS\n\n```js\nimport FFmpeg from '@ffmpeg/ffmpeg';\n\nconst wf = new WFPlayer({\n    container: document.querySelector('#waveform'),\n    mediaElement: document.querySelector('#video'),\n});\n\ndocument.getElementById('file').addEventListener('change', async (event) =\u003e {\n    const file = event.target.files[0];\n    const { createFFmpeg, fetchFile } = FFmpeg;\n    const ffmpeg = createFFmpeg({ log: true });\n    await ffmpeg.load();\n    ffmpeg.FS('writeFile', file.name, await fetchFile(file));\n    await ffmpeg.run('-i', file.name, '-ac', '1', '-ar', '8000', 'audio.mp3');\n    const uint8 = ffmpeg.FS('readFile', 'audio.mp3');\n\n    await wf.load(uint8);\n})\n```\n\n#### How to add a custom event\n\n```js\nvar wf = new WFPlayer({\n    container: document.querySelector('#waveform'),\n    mediaElement: document.querySelector('#video'),\n});\n\nwf.load('path/to/audio.mp3');\n\n// click event\nwf.on('click', (currentTime) =\u003e {\n     wf.seek(currentTime)\n});\n\n// grab event\nwf.on('grabbing', (currentTime) =\u003e {\n    wf.seek(currentTime)\n});\n\n// scroll event\nwf.on('scroll', (deltaY) =\u003e {\n    wf.seek(wf.currentTime + deltaY / 10)\n});\n```\n\n#### How to get currentTime from an event\n\n```js\nvar waveform = document.querySelector('#waveform')\nvar wf = new WFPlayer({\n    container: waveform,\n    mediaElement: document.querySelector('#video'),\n});\n\nwf.load('path/to/audio.mp3');\n\nwaveform.addEventListener('mousemove', event =\u003e {\n    const currentTime = this.getCurrentTimeFromEvent(event);\n    console.log(currentTime);\n})\n\nwaveform.addEventListener('click', event =\u003e {\n    const currentTime = this.getCurrentTimeFromEvent(event);\n    console.log(currentTime);\n})\n```\n\n## Donations\n\nWe accept donations through these channels:\n\n-   [Paypal](https://www.paypal.me/harveyzack)\n-   [WeChat Pay](./images/wechatpay.jpg)\n-   [Alipay](./images/alipay.jpg)\n\n## QQ Group\n\n![QQ Group](./images/qqgroup.png)\n\n## License\n\nMIT © [Harvey Zack](https://sleepy.im/)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzhw2590582%2Fwfplayer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fzhw2590582%2Fwfplayer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fzhw2590582%2Fwfplayer/lists"}