Showing preview only (1,177K chars total). Download the full file or copy to clipboard to get everything.
Repository: ffmpegwasm/ffmpeg.wasm
Branch: main
Commit: f876f907c7e9
Files: 265
Total size: 1.1 MB
Directory structure:
gitextract_a_xgwnzo/
├── .gitattributes
├── .github/
│ ├── FUNDING.yml
│ ├── ISSUE_TEMPLATE/
│ │ ├── bug_report.md
│ │ └── feature_request.md
│ ├── SECURITY.md
│ └── workflows/
│ └── CI.yml
├── .gitignore
├── .gitmodules
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── Dockerfile
├── LICENSE
├── Makefile
├── README.md
├── apps/
│ ├── angular-app/
│ │ ├── .editorconfig
│ │ ├── .gitignore
│ │ ├── .vscode/
│ │ │ ├── extensions.json
│ │ │ ├── launch.json
│ │ │ └── tasks.json
│ │ ├── README.md
│ │ ├── angular.json
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── app/
│ │ │ │ ├── app.component.css
│ │ │ │ ├── app.component.html
│ │ │ │ ├── app.component.spec.ts
│ │ │ │ ├── app.component.ts
│ │ │ │ ├── app.config.ts
│ │ │ │ └── app.routes.ts
│ │ │ ├── assets/
│ │ │ │ └── .gitkeep
│ │ │ ├── index.html
│ │ │ ├── main.ts
│ │ │ └── styles.css
│ │ ├── tsconfig.app.json
│ │ ├── tsconfig.json
│ │ └── tsconfig.spec.json
│ ├── nextjs-app/
│ │ ├── .eslintrc.json
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── app/
│ │ │ ├── Home.tsx
│ │ │ ├── NoSSRWrapper.tsx
│ │ │ ├── globals.css
│ │ │ ├── layout.tsx
│ │ │ └── page.tsx
│ │ ├── next.config.js
│ │ ├── package.json
│ │ ├── postcss.config.js
│ │ ├── tailwind.config.ts
│ │ └── tsconfig.json
│ ├── react-vite-app/
│ │ ├── .eslintrc.cjs
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── index.html
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── App.tsx
│ │ │ ├── index.css
│ │ │ ├── main.tsx
│ │ │ └── vite-env.d.ts
│ │ ├── tsconfig.json
│ │ ├── tsconfig.node.json
│ │ └── vite.config.ts
│ ├── solidstart-app/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── app.config.ts
│ │ ├── package.json
│ │ ├── postcss.config.cjs
│ │ ├── src/
│ │ │ ├── app.css
│ │ │ ├── app.tsx
│ │ │ ├── entry-client.tsx
│ │ │ ├── entry-server.tsx
│ │ │ ├── global.d.ts
│ │ │ └── routes/
│ │ │ └── index.tsx
│ │ ├── tailwind.config.cjs
│ │ └── tsconfig.json
│ ├── sveltekit-app/
│ │ ├── .eslintignore
│ │ ├── .eslintrc.cjs
│ │ ├── .gitignore
│ │ ├── .npmrc
│ │ ├── .prettierignore
│ │ ├── .prettierrc
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── playwright.config.ts
│ │ ├── src/
│ │ │ ├── app.d.ts
│ │ │ ├── app.html
│ │ │ ├── index.test.ts
│ │ │ ├── lib/
│ │ │ │ ├── FFmpegDemo.svelte
│ │ │ │ └── index.ts
│ │ │ └── routes/
│ │ │ └── +page.svelte
│ │ ├── svelte.config.js
│ │ ├── tests/
│ │ │ └── test.ts
│ │ ├── tsconfig.json
│ │ └── vite.config.ts
│ ├── vanilla-app/
│ │ ├── .gitignore
│ │ ├── README.md
│ │ ├── package.json
│ │ ├── public/
│ │ │ ├── concatDemuxer.html
│ │ │ ├── style.css
│ │ │ ├── transcode-mt.esm.html
│ │ │ ├── transcode-mt.html
│ │ │ ├── transcode.esm.html
│ │ │ ├── transcode.html
│ │ │ └── trim.html
│ │ └── server.js
│ ├── vue-vite-app/
│ │ ├── .eslintrc.cjs
│ │ ├── .gitignore
│ │ ├── .prettierrc.json
│ │ ├── .vscode/
│ │ │ └── extensions.json
│ │ ├── README.md
│ │ ├── env.d.ts
│ │ ├── index.html
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── App.vue
│ │ │ ├── assets/
│ │ │ │ ├── base.css
│ │ │ │ └── main.css
│ │ │ ├── components/
│ │ │ │ └── FFmpegDemo.vue
│ │ │ └── main.ts
│ │ ├── tsconfig.app.json
│ │ ├── tsconfig.json
│ │ ├── tsconfig.node.json
│ │ └── vite.config.ts
│ └── website/
│ ├── .gitignore
│ ├── README.md
│ ├── assets/
│ │ ├── angular.xcf
│ │ ├── background.xcf
│ │ ├── ffmpegwasm-arch.drawio
│ │ ├── nextjs.xcf
│ │ ├── react-vite.xcf
│ │ ├── solidstart-vite.xcf
│ │ ├── sveltekit-vite.xcf
│ │ ├── vanilla.xcf
│ │ └── vue-vite.xcf
│ ├── babel.config.js
│ ├── blog/
│ │ ├── 2023-07-26-release-ffmpeg.wasm-0.12.0.mdx
│ │ └── authors.yml
│ ├── deploy.sh
│ ├── docs/
│ │ ├── contribution/
│ │ │ ├── core.md
│ │ │ ├── ffmpeg.md
│ │ │ └── util.md
│ │ ├── faq.md
│ │ ├── getting-started/
│ │ │ ├── examples.md
│ │ │ ├── installation.md
│ │ │ └── usage.md
│ │ ├── migration.md
│ │ ├── overview.md
│ │ ├── performance.md
│ │ └── privacy-policy.md
│ ├── docusaurus.config.js
│ ├── netlify.toml
│ ├── package.json
│ ├── sidebars.js
│ ├── src/
│ │ ├── components/
│ │ │ ├── ExternalLibraries/
│ │ │ │ ├── index.tsx
│ │ │ │ └── styles.module.css
│ │ │ ├── HomepageFeatures/
│ │ │ │ ├── index.tsx
│ │ │ │ └── styles.module.css
│ │ │ ├── Playground/
│ │ │ │ ├── CoreDownloader.tsx
│ │ │ │ ├── CoreSwitcher.tsx
│ │ │ │ ├── Workspace/
│ │ │ │ │ ├── Editor.tsx
│ │ │ │ │ ├── FileSystemManager.tsx
│ │ │ │ │ ├── MoreButton.tsx
│ │ │ │ │ ├── index.tsx
│ │ │ │ │ └── types.tsx
│ │ │ │ ├── const.ts
│ │ │ │ └── index.tsx
│ │ │ └── common/
│ │ │ ├── ExampleCard.tsx
│ │ │ ├── LinearProgressWithLabel.tsx
│ │ │ ├── MuiThemeProvider/
│ │ │ │ └── index.tsx
│ │ │ ├── ThemedButton/
│ │ │ │ └── index.tsx
│ │ │ └── ThemedIconButton/
│ │ │ └── index.tsx
│ │ ├── css/
│ │ │ └── custom.css
│ │ ├── pages/
│ │ │ ├── index.module.css
│ │ │ ├── index.tsx
│ │ │ └── playground.md
│ │ ├── theme/
│ │ │ └── ReactLiveScope/
│ │ │ └── index.js
│ │ └── util.ts
│ ├── static/
│ │ ├── .nojekyll
│ │ └── ads.txt
│ └── tsconfig.json
├── build/
│ ├── aom.sh
│ ├── ffmpeg-wasm.sh
│ ├── ffmpeg.sh
│ ├── freetype2.sh
│ ├── fribidi.sh
│ ├── harfbuzz.sh
│ ├── lame.sh
│ ├── libass.sh
│ ├── libvpx.sh
│ ├── libwebp.sh
│ ├── ogg.sh
│ ├── opus.sh
│ ├── theora.sh
│ ├── vorbis.sh
│ ├── wavpack.sh
│ ├── x264.sh
│ ├── x265.sh
│ ├── zimg.sh
│ └── zlib.sh
├── package.json
├── packages/
│ ├── core/
│ │ ├── .gitignore
│ │ └── package.json
│ ├── core-mt/
│ │ ├── .gitignore
│ │ └── package.json
│ ├── ffmpeg/
│ │ ├── .eslintignore
│ │ ├── .eslintrc.cjs
│ │ ├── .gitignore
│ │ ├── package.json
│ │ ├── src/
│ │ │ ├── classes.ts
│ │ │ ├── const.ts
│ │ │ ├── empty.mts
│ │ │ ├── errors.ts
│ │ │ ├── index.ts
│ │ │ ├── types.ts
│ │ │ ├── utils.ts
│ │ │ └── worker.ts
│ │ ├── tsconfig.esm.json
│ │ ├── tsconfig.json
│ │ └── webpack.config.js
│ ├── types/
│ │ ├── package.json
│ │ └── types/
│ │ └── index.d.ts
│ └── util/
│ ├── .eslintrc.cjs
│ ├── .gitignore
│ ├── package.json
│ ├── src/
│ │ ├── const.ts
│ │ ├── errors.ts
│ │ ├── index.ts
│ │ └── types.ts
│ ├── tests/
│ │ ├── .eslintrc
│ │ ├── constants.js
│ │ ├── ffmpeg.test.html
│ │ └── ffmpeg.test.js
│ ├── tsconfig.cjs.json
│ ├── tsconfig.esm.json
│ ├── tsconfig.json
│ └── webpack.config.cjs
├── scripts/
│ └── download-assets.js
├── src/
│ ├── bind/
│ │ ├── .eslintrc.cjs
│ │ └── ffmpeg/
│ │ ├── bind.js
│ │ ├── export-runtime.js
│ │ └── export.js
│ └── fftools/
│ ├── Makefile
│ ├── cmdutils.c
│ ├── cmdutils.h
│ ├── ffmpeg.c
│ ├── ffmpeg.h
│ ├── ffmpeg_filter.c
│ ├── ffmpeg_hw.c
│ ├── ffmpeg_mux.c
│ ├── ffmpeg_opt.c
│ ├── ffplay.c
│ ├── ffprobe.c
│ ├── fopen_utf8.h
│ ├── opt_common.c
│ └── opt_common.h
├── tests/
│ ├── .eslintrc.json
│ ├── ffmpeg-core-mt.test.html
│ ├── ffmpeg-core-st.test.html
│ ├── ffmpeg-core.test.js
│ ├── ffmpeg-mt.test.html
│ ├── ffmpeg-st.test.html
│ ├── ffmpeg.test.js
│ ├── index.html
│ ├── test-helper-browser.js
│ ├── test-helper-mt.js
│ ├── test-helper-st.js
│ └── util.js
└── tsconfig.json
================================================
FILE CONTENTS
================================================
================================================
FILE: .gitattributes
================================================
. !text !filter !merge !diff
================================================
FILE: .github/FUNDING.yml
================================================
# These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: ffmpegwasm
ko_fi: # Replace with a single Ko-fi username
tidelift: # Remove
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
otechie: # Replace with a single Otechie username
custom:
================================================
FILE: .github/ISSUE_TEMPLATE/bug_report.md
================================================
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Please provide a GitHub link or code snippet.
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
**Smartphone (please complete the following information):**
- Device: [e.g. iPhone6]
- OS: [e.g. iOS8.1]
- Browser [e.g. stock browser, safari]
- Version [e.g. 22]
**Additional context**
Add any other context about the problem here.
================================================
FILE: .github/ISSUE_TEMPLATE/feature_request.md
================================================
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.
================================================
FILE: .github/SECURITY.md
================================================
## Security contact information
To report a security vulnerability, please use the
[Tidelift security contact](https://tidelift.com/security).
Tidelift will coordinate the fix and disclosure.
================================================
FILE: .github/workflows/CI.yml
================================================
name: CI
on:
push:
branches:
- main
pull_request:
branches:
- main
jobs:
build-core:
runs-on: ubuntu-latest
steps:
- name: Checkout Source Code
uses: actions/checkout@v2
- name: Update pkg-config database
run: sudo ldconfig
- name: Setup Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2
- name: Cache build
id: cache-build
uses: actions/cache@v4
with:
path: build-cache-st
key: build-cache-st-v1-${{ hashFiles('Dockerfile', 'Makefile', 'build/*') }}
restore-keys: |
build-cache-st-v1-
- name: Build ffmpeg-core
run: make prd EXTRA_ARGS="--cache-from=type=local,src=build-cache-st --cache-to=type=local,dest=build-cache-st,mode=max"
- name: Upload core
uses: actions/upload-artifact@v4
with:
name: ffmpeg-core
path: packages/core/dist/*
build-core-mt:
runs-on: ubuntu-latest
steps:
- name: Checkout Source Code
uses: actions/checkout@v2
- name: Setup Docker Buildx
id: buildx
uses: docker/setup-buildx-action@v2
- name: Cache build
id: cache-build
uses: actions/cache@v4
with:
path: build-cache-mt
key: build-cache-mt-v1-${{ hashFiles('Dockerfile', 'Makefile', 'build/*') }}
restore-keys: |
build-cache-v1-
- name: Build ffmpet-core-mt
run: make prd-mt EXTRA_ARGS="--cache-from=type=local,src=build-cache-mt --cache-to=type=local,dest=build-cache-mt,mode=max"
- name: Upload core-mt
uses: actions/upload-artifact@v4
with:
name: ffmpeg-core-mt
path: packages/core-mt/dist/*
tests:
runs-on: ubuntu-latest
needs:
- build-core
- build-core-mt
steps:
- name: Checkout Source Code
uses: actions/checkout@v2
- name: Download ffmpeg-core
uses: actions/download-artifact@v4
with:
name: ffmpeg-core
path: packages/core/dist
- name: Download ffmpeg-core-mt
uses: actions/download-artifact@v4
with:
name: ffmpeg-core-mt
path: packages/core-mt/dist
- name: Use Node.js 18
uses: actions/setup-node@v2
with:
node-version: 18.x
- name: Cache dependencies
id: cache-dependencies
uses: actions/cache@v4
with:
path: node_modules
key: node-modules-${{ hashFiles('package-lock.json') }}
restore-keys: |
node-modules-
- name: Install dependencies
run: npm install
- name: Install Chrome
uses: browser-actions/setup-chrome@latest
with:
chrome-version: stable
- name: Run tests
env:
CHROME_HEADLESS: 1
CHROME_PATH: chrome
CHROME_FLAGS: "--headless --disable-gpu --no-sandbox --enable-features=SharedArrayBuffer,CrossOriginIsolation"
HEADERS: '{"Cross-Origin-Opener-Policy": "same-origin", "Cross-Origin-Embedder-Policy": "require-corp"}'
run: |
# Start test server with proper headers for all tests
npm run serve -- --headers "$HEADERS" &
# Increase wait time to ensure server is ready
sleep 15
# Verify headers and isolation status
echo "Checking security headers and isolation status..."
curl -v http://localhost:3000/tests/ffmpeg-core-st.test.html 2>&1 | grep -i "cross-origin"
# Run verification script first
echo "Verifying browser environment..."
cat << EOF > verify-browser.html
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Cross-Origin-Opener-Policy" content="same-origin">
<meta http-equiv="Cross-Origin-Embedder-Policy" content="require-corp">
</head>
<body>
<script>
console.log('SharedArrayBuffer available:', typeof SharedArrayBuffer !== 'undefined');
console.log('crossOriginIsolated:', window.crossOriginIsolated);
if (!window.crossOriginIsolated || typeof SharedArrayBuffer === 'undefined') {
throw new Error('Browser environment not properly configured for SharedArrayBuffer');
}
</script>
</body>
</html>
EOF
# Run single-threaded tests first
echo "Running single-threaded tests..."
npx mocha-headless-chrome \
--args="$CHROME_FLAGS" \
-a no-sandbox \
-f http://localhost:3000/tests/ffmpeg-core-st.test.html 2>&1 | tee st-core-test.log
npx mocha-headless-chrome \
--args="$CHROME_FLAGS" \
-a no-sandbox \
-f http://localhost:3000/tests/ffmpeg-st.test.html 2>&1 | tee st-test.log
# Run multi-threaded tests
echo "Running multi-threaded tests..."
# Create a test script to verify browser environment
cat << EOF > verify-browser.html
<!DOCTYPE html>
<html>
<head>
<title>Browser Environment Test</title>
</head>
<body>
<script>
console.log('SharedArrayBuffer available:', typeof SharedArrayBuffer !== 'undefined');
console.log('crossOriginIsolated:', window.crossOriginIsolated);
</script>
</body>
</html>
EOF
# Run the verification in Chrome
echo "Verifying browser environment..."
npx mocha-headless-chrome \
--args="$CHROME_FLAGS --enable-features=SharedArrayBuffer,CrossOriginIsolation" \
-a no-sandbox \
-f http://localhost:3000/verify-browser.html
# Run MT tests with verified configuration
npx mocha-headless-chrome \
--args="$CHROME_FLAGS --enable-features=SharedArrayBuffer,CrossOriginIsolation" \
-a no-sandbox \
-f http://localhost:3000/tests/ffmpeg-core-mt.test.html 2>&1 | tee mt-core-test.log
npx mocha-headless-chrome \
--args="$CHROME_FLAGS --enable-features=SharedArrayBuffer,CrossOriginIsolation" \
-a no-sandbox \
-f http://localhost:3000/tests/ffmpeg-mt.test.html 2>&1 | tee mt-test.log
# Display all logs for debugging
echo "=== Test Logs ==="
for log in *-test.log; do
echo "Contents of $log:"
cat $log
done
================================================
FILE: .gitignore
================================================
node_modules
dist
/.nyc_output
.DS_Store
# ide
.idea/
# Local Netlify folder
.netlify
================================================
FILE: .gitmodules
================================================
[submodule "testdata"]
path = testdata
url = https://github.com/ffmpegwasm/testdata
================================================
FILE: CODE_OF_CONDUCT.md
================================================
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at jeromewus@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
================================================
FILE: CONTRIBUTING.md
================================================
Check https://ffmpegwasm.netlify.app/docs/contribution/core
================================================
FILE: Dockerfile
================================================
# syntax=docker/dockerfile-upstream:master-labs
# Base emsdk image with environment variables.
FROM emscripten/emsdk:3.1.40 AS emsdk-base
ARG EXTRA_CFLAGS
ARG EXTRA_LDFLAGS
ARG FFMPEG_ST
ARG FFMPEG_MT
ENV INSTALL_DIR=/opt
# We cannot upgrade to n6.0 as ffmpeg bin only supports multithread at the moment.
ENV FFMPEG_VERSION=n5.1.4
ENV CFLAGS="-I$INSTALL_DIR/include $CFLAGS $EXTRA_CFLAGS"
ENV CXXFLAGS="$CFLAGS"
ENV LDFLAGS="-L$INSTALL_DIR/lib $LDFLAGS $CFLAGS $EXTRA_LDFLAGS"
ENV EM_PKG_CONFIG_PATH=$EM_PKG_CONFIG_PATH:$INSTALL_DIR/lib/pkgconfig:/emsdk/upstream/emscripten/system/lib/pkgconfig
ENV EM_TOOLCHAIN_FILE=$EMSDK/upstream/emscripten/cmake/Modules/Platform/Emscripten.cmake
ENV PKG_CONFIG_PATH=$PKG_CONFIG_PATH:$EM_PKG_CONFIG_PATH
ENV FFMPEG_ST=$FFMPEG_ST
ENV FFMPEG_MT=$FFMPEG_MT
RUN apt-get update && \
apt-get install -y pkg-config autoconf automake libtool ragel
# Build x264
FROM emsdk-base AS x264-builder
ENV X264_BRANCH=4-cores
ADD https://github.com/ffmpegwasm/x264.git#$X264_BRANCH /src
COPY build/x264.sh /src/build.sh
RUN bash -x /src/build.sh
# Build x265
FROM emsdk-base AS x265-builder
ENV X265_BRANCH=3.4
ADD https://github.com/ffmpegwasm/x265.git#$X265_BRANCH /src
COPY build/x265.sh /src/build.sh
RUN bash -x /src/build.sh
# Build libvpx
FROM emsdk-base AS libvpx-builder
ENV LIBVPX_BRANCH=v1.13.1
ADD https://github.com/ffmpegwasm/libvpx.git#$LIBVPX_BRANCH /src
COPY build/libvpx.sh /src/build.sh
RUN bash -x /src/build.sh
# Build lame
FROM emsdk-base AS lame-builder
ENV LAME_BRANCH=master
ADD https://github.com/ffmpegwasm/lame.git#$LAME_BRANCH /src
COPY build/lame.sh /src/build.sh
RUN bash -x /src/build.sh
# Build ogg
FROM emsdk-base AS ogg-builder
ENV OGG_BRANCH=v1.3.4
ADD https://github.com/ffmpegwasm/Ogg.git#$OGG_BRANCH /src
COPY build/ogg.sh /src/build.sh
RUN bash -x /src/build.sh
# Build theora
FROM emsdk-base AS theora-builder
COPY --from=ogg-builder $INSTALL_DIR $INSTALL_DIR
ENV THEORA_BRANCH=v1.1.1
ADD https://github.com/ffmpegwasm/theora.git#$THEORA_BRANCH /src
COPY build/theora.sh /src/build.sh
RUN bash -x /src/build.sh
# Build opus
FROM emsdk-base AS opus-builder
ENV OPUS_BRANCH=v1.3.1
ADD https://github.com/ffmpegwasm/opus.git#$OPUS_BRANCH /src
COPY build/opus.sh /src/build.sh
RUN bash -x /src/build.sh
# Build vorbis
FROM emsdk-base AS vorbis-builder
COPY --from=ogg-builder $INSTALL_DIR $INSTALL_DIR
ENV VORBIS_BRANCH=v1.3.3
ADD https://github.com/ffmpegwasm/vorbis.git#$VORBIS_BRANCH /src
COPY build/vorbis.sh /src/build.sh
RUN bash -x /src/build.sh
# Build zlib
FROM emsdk-base AS zlib-builder
ENV ZLIB_BRANCH=v1.2.11
ADD https://github.com/ffmpegwasm/zlib.git#$ZLIB_BRANCH /src
COPY build/zlib.sh /src/build.sh
RUN bash -x /src/build.sh
# Build libwebp
FROM emsdk-base AS libwebp-builder
COPY --from=zlib-builder $INSTALL_DIR $INSTALL_DIR
ENV LIBWEBP_BRANCH=v1.3.2
ADD https://github.com/ffmpegwasm/libwebp.git#$LIBWEBP_BRANCH /src
COPY build/libwebp.sh /src/build.sh
RUN bash -x /src/build.sh
# Build freetype2
FROM emsdk-base AS freetype2-builder
ENV FREETYPE2_BRANCH=VER-2-10-4
ADD https://github.com/ffmpegwasm/freetype2.git#$FREETYPE2_BRANCH /src
COPY build/freetype2.sh /src/build.sh
RUN bash -x /src/build.sh
# Build fribidi
FROM emsdk-base AS fribidi-builder
ENV FRIBIDI_BRANCH=v1.0.9
ADD https://github.com/fribidi/fribidi.git#$FRIBIDI_BRANCH /src
COPY build/fribidi.sh /src/build.sh
RUN bash -x /src/build.sh
# Build harfbuzz
FROM emsdk-base AS harfbuzz-builder
ENV HARFBUZZ_BRANCH=5.2.0
ADD https://github.com/harfbuzz/harfbuzz.git#$HARFBUZZ_BRANCH /src
COPY build/harfbuzz.sh /src/build.sh
RUN bash -x /src/build.sh
# Build libass
FROM emsdk-base AS libass-builder
COPY --from=freetype2-builder $INSTALL_DIR $INSTALL_DIR
COPY --from=fribidi-builder $INSTALL_DIR $INSTALL_DIR
COPY --from=harfbuzz-builder $INSTALL_DIR $INSTALL_DIR
ENV LIBASS_BRANCH=0.15.0
ADD https://github.com/libass/libass.git#$LIBASS_BRANCH /src
COPY build/libass.sh /src/build.sh
RUN bash -x /src/build.sh
# Build zimg
FROM emsdk-base AS zimg-builder
ENV ZIMG_BRANCH=release-3.0.5
RUN apt-get update && apt-get install -y git
RUN git clone --recursive -b $ZIMG_BRANCH https://github.com/sekrit-twc/zimg.git /src
COPY build/zimg.sh /src/build.sh
RUN bash -x /src/build.sh
# Base ffmpeg image with dependencies and source code populated.
FROM emsdk-base AS ffmpeg-base
RUN embuilder build sdl2 sdl2-mt
ADD https://github.com/FFmpeg/FFmpeg.git#$FFMPEG_VERSION /src
COPY --from=x264-builder $INSTALL_DIR $INSTALL_DIR
COPY --from=x265-builder $INSTALL_DIR $INSTALL_DIR
COPY --from=libvpx-builder $INSTALL_DIR $INSTALL_DIR
COPY --from=lame-builder $INSTALL_DIR $INSTALL_DIR
COPY --from=opus-builder $INSTALL_DIR $INSTALL_DIR
COPY --from=theora-builder $INSTALL_DIR $INSTALL_DIR
COPY --from=vorbis-builder $INSTALL_DIR $INSTALL_DIR
COPY --from=libwebp-builder $INSTALL_DIR $INSTALL_DIR
COPY --from=libass-builder $INSTALL_DIR $INSTALL_DIR
COPY --from=zimg-builder $INSTALL_DIR $INSTALL_DIR
# Build ffmpeg
FROM ffmpeg-base AS ffmpeg-builder
COPY build/ffmpeg.sh /src/build.sh
RUN bash -x /src/build.sh \
--enable-gpl \
--enable-libx264 \
--enable-libx265 \
--enable-libvpx \
--enable-libmp3lame \
--enable-libtheora \
--enable-libvorbis \
--enable-libopus \
--enable-zlib \
--enable-libwebp \
--enable-libfreetype \
--enable-libfribidi \
--enable-libass \
--enable-libzimg
# Build ffmpeg.wasm
FROM ffmpeg-builder AS ffmpeg-wasm-builder
COPY src/bind /src/src/bind
COPY src/fftools /src/src/fftools
COPY build/ffmpeg-wasm.sh build.sh
# libraries to link
ENV FFMPEG_LIBS \
-lx264 \
-lx265 \
-lvpx \
-lmp3lame \
-logg \
-ltheora \
-lvorbis \
-lvorbisenc \
-lvorbisfile \
-lopus \
-lz \
-lwebpmux \
-lwebp \
-lsharpyuv \
-lfreetype \
-lfribidi \
-lharfbuzz \
-lass \
-lzimg
RUN mkdir -p /src/dist/umd && bash -x /src/build.sh \
${FFMPEG_LIBS} \
-o dist/umd/ffmpeg-core.js
RUN mkdir -p /src/dist/esm && bash -x /src/build.sh \
${FFMPEG_LIBS} \
-sEXPORT_ES6 \
-o dist/esm/ffmpeg-core.js
# Export ffmpeg-core.wasm to dist/, use `docker buildx build -o . .` to get assets
FROM scratch AS exportor
COPY --from=ffmpeg-wasm-builder /src/dist /dist
================================================
FILE: LICENSE
================================================
MIT License
Copyright (c) 2019 Jerome Wu
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
================================================
FILE: Makefile
================================================
all: dev
MT_FLAGS := -sUSE_PTHREADS -pthread
DEV_ARGS := --progress=plain
DEV_CFLAGS := --profiling
DEV_MT_CFLAGS := $(DEV_CFLAGS) $(MT_FLAGS)
PROD_CFLAGS := -O3 -msimd128
PROD_MT_CFLAGS := $(PROD_CFLAGS) $(MT_FLAGS)
clean:
rm -rf ./packages/core$(PKG_SUFFIX)/dist
.PHONY: build
build:
make clean PKG_SUFFIX="$(PKG_SUFFIX)"
EXTRA_CFLAGS="$(EXTRA_CFLAGS)" \
EXTRA_LDFLAGS="$(EXTRA_LDFLAGS)" \
FFMPEG_ST="$(FFMPEG_ST)" \
FFMPEG_MT="$(FFMPEG_MT)" \
docker buildx build \
--build-arg EXTRA_CFLAGS \
--build-arg EXTRA_LDFLAGS \
--build-arg FFMPEG_MT \
--build-arg FFMPEG_ST \
-o ./packages/core$(PKG_SUFFIX) \
$(EXTRA_ARGS) \
.
build-st:
make build \
FFMPEG_ST=yes
build-mt:
make build \
PKG_SUFFIX=-mt \
FFMPEG_MT=yes
dev:
make build-st EXTRA_CFLAGS="$(DEV_CFLAGS)" EXTRA_ARGS="$(DEV_ARGS)"
dev-mt:
make build-mt EXTRA_CFLAGS="$(DEV_MT_CFLAGS)" EXTRA_ARGS="$(DEV_ARGS)"
prd:
make build-st EXTRA_CFLAGS="$(PROD_CFLAGS)"
prd-mt:
make build-mt EXTRA_CFLAGS="$(PROD_MT_CFLAGS)"
================================================
FILE: README.md
================================================
---
<p align="center">
<a href="#">
<img alt="ffmpeg.wasm" width="128px" height="128px" src="https://github.com/ffmpegwasm/ffmpeg.wasm/blob/main/apps/website/static/img/logo192.png"></img>
</a>
</p>
# ffmpeg.wasm
ffmpeg.wasm is a pure Webassembly / Javascript port of FFmpeg. It enables video & audio record, convert and stream right inside browsers.
[](https://github.com/emersion/stability-badges#experimental)
[](https://img.shields.io/node/v/@ffmpeg/ffmpeg.svg)
[](https://github.com/ffmpegwasm/ffmpeg.wasm/actions)

[](https://github.com/ffmpegwasm/ffmpeg.wasm/graphs/commit-activity)
[](https://opensource.org/licenses/MIT)
[](https://www.npmjs.com/package/@ffmpeg/ffmpeg)
[](https://www.npmjs.com/package/@ffmpeg/ffmpeg)
[](https://app.netlify.com/sites/ffmpegwasm/deploys)
Join us on Discord!
[](https://discord.gg/NjGMaqqfm5)
## Documentation
- [Introduction](https://ffmpegwasm.netlify.app/docs/overview)
- [Getting
Started](https://ffmpegwasm.netlify.app/docs/getting-started/installation)
- [API](https://ffmpegwasm.netlify.app/docs/api/ffmpeg/)
- [FAQ](https://ffmpegwasm.netlify.app/docs/faq)
- [Contribution](https://ffmpegwasm.netlify.app/docs/contribution/core)
Please sponsor ffmpeg.wasm to make it sustainable. :heart:
================================================
FILE: apps/angular-app/.editorconfig
================================================
# Editor configuration, see https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
insert_final_newline = true
trim_trailing_whitespace = true
[*.ts]
quote_type = single
[*.md]
max_line_length = off
trim_trailing_whitespace = false
================================================
FILE: apps/angular-app/.gitignore
================================================
# See http://help.github.com/ignore-files/ for more about ignoring files.
# Compiled output
/dist
/tmp
/out-tsc
/bazel-out
# Node
/node_modules
npm-debug.log
yarn-error.log
# IDEs and editors
.idea/
.project
.classpath
.c9/
*.launch
.settings/
*.sublime-workspace
# Visual Studio Code
.vscode/*
!.vscode/settings.json
!.vscode/tasks.json
!.vscode/launch.json
!.vscode/extensions.json
.history/*
# Miscellaneous
/.angular/cache
.sass-cache/
/connect.lock
/coverage
/libpeerconnection.log
testem.log
/typings
# System files
.DS_Store
Thumbs.db
================================================
FILE: apps/angular-app/.vscode/extensions.json
================================================
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846
"recommendations": ["angular.ng-template"]
}
================================================
FILE: apps/angular-app/.vscode/launch.json
================================================
{
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
"version": "0.2.0",
"configurations": [
{
"name": "ng serve",
"type": "chrome",
"request": "launch",
"preLaunchTask": "npm: start",
"url": "http://localhost:4200/"
},
{
"name": "ng test",
"type": "chrome",
"request": "launch",
"preLaunchTask": "npm: test",
"url": "http://localhost:9876/debug.html"
}
]
}
================================================
FILE: apps/angular-app/.vscode/tasks.json
================================================
{
// For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558
"version": "2.0.0",
"tasks": [
{
"type": "npm",
"script": "start",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "(.*?)"
},
"endsPattern": {
"regexp": "bundle generation complete"
}
}
}
},
{
"type": "npm",
"script": "test",
"isBackground": true,
"problemMatcher": {
"owner": "typescript",
"pattern": "$tsc",
"background": {
"activeOnStart": true,
"beginsPattern": {
"regexp": "(.*?)"
},
"endsPattern": {
"regexp": "bundle generation complete"
}
}
}
}
]
}
================================================
FILE: apps/angular-app/README.md
================================================
# AngularApp
This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.0.7.
## Development server
Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The application will automatically reload if you change any of the source files.
## Code scaffolding
Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
## Build
Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory.
## Running unit tests
Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
## Running end-to-end tests
Run `ng e2e` to execute the end-to-end tests via a platform of your choice. To use this command, you need to first add a package that implements end-to-end testing capabilities.
## Further help
To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI Overview and Command Reference](https://angular.io/cli) page.
================================================
FILE: apps/angular-app/angular.json
================================================
{
"$schema": "./node_modules/@angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"angular-app": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "@angular-devkit/build-angular:application",
"options": {
"outputPath": "dist/angular-app",
"index": "src/index.html",
"browser": "src/main.ts",
"polyfills": [
"zone.js"
],
"tsConfig": "tsconfig.app.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
},
"configurations": {
"production": {
"budgets": [
{
"type": "initial",
"maximumWarning": "500kb",
"maximumError": "1mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "2kb",
"maximumError": "4kb"
}
],
"outputHashing": "all"
},
"development": {
"optimization": false,
"extractLicenses": false,
"sourceMap": true
}
},
"defaultConfiguration": "production"
},
"serve": {
"builder": "@angular-devkit/build-angular:dev-server",
"configurations": {
"production": {
"buildTarget": "angular-app:build:production"
},
"development": {
"buildTarget": "angular-app:build:development"
}
},
"defaultConfiguration": "development"
},
"extract-i18n": {
"builder": "@angular-devkit/build-angular:extract-i18n",
"options": {
"buildTarget": "angular-app:build"
}
},
"test": {
"builder": "@angular-devkit/build-angular:karma",
"options": {
"polyfills": [
"zone.js",
"zone.js/testing"
],
"tsConfig": "tsconfig.spec.json",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
}
}
}
}
}
}
================================================
FILE: apps/angular-app/package.json
================================================
{
"name": "angular-app",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"@angular/animations": "^17.0.0",
"@angular/common": "^17.0.0",
"@angular/compiler": "^17.0.0",
"@angular/core": "^17.0.0",
"@angular/forms": "^17.0.0",
"@angular/platform-browser": "^17.0.0",
"@angular/platform-browser-dynamic": "^17.0.0",
"@angular/router": "^17.0.0",
"@ffmpeg/ffmpeg": "*",
"@ffmpeg/util": "*",
"rxjs": "~7.8.0",
"tslib": "^2.3.0",
"zone.js": "~0.14.2"
},
"devDependencies": {
"@angular-devkit/build-angular": "^17.0.7",
"@angular/cli": "^17.0.7",
"@angular/compiler-cli": "^17.0.0",
"@types/jasmine": "~5.1.0",
"jasmine-core": "~5.1.0",
"karma": "~6.4.0",
"karma-chrome-launcher": "~3.2.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.1.0",
"karma-jasmine-html-reporter": "~2.1.0",
"typescript": "~5.2.2"
}
}
================================================
FILE: apps/angular-app/src/app/app.component.css
================================================
================================================
FILE: apps/angular-app/src/app/app.component.html
================================================
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content below * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * Delete the template below * * * * * * * * * -->
<!-- * * * * * * * to get started with your project! * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<style>
:host {
--bright-blue: oklch(51.01% 0.274 263.83);
--electric-violet: oklch(53.18% 0.28 296.97);
--french-violet: oklch(47.66% 0.246 305.88);
--vivid-pink: oklch(69.02% 0.277 332.77);
--hot-red: oklch(61.42% 0.238 15.34);
--orange-red: oklch(63.32% 0.24 31.68);
--gray-900: oklch(19.37% 0.006 300.98);
--gray-700: oklch(36.98% 0.014 302.71);
--gray-400: oklch(70.9% 0.015 304.04);
--red-to-pink-to-purple-vertical-gradient: linear-gradient(
180deg,
var(--orange-red) 0%,
var(--vivid-pink) 50%,
var(--electric-violet) 100%
);
--red-to-pink-to-purple-horizontal-gradient: linear-gradient(
90deg,
var(--orange-red) 0%,
var(--vivid-pink) 50%,
var(--electric-violet) 100%
);
--pill-accent: var(--bright-blue);
font-family: "Inter", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
box-sizing: border-box;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
h1 {
font-size: 3.125rem;
color: var(--gray-900);
font-weight: 500;
line-height: 100%;
letter-spacing: -0.125rem;
margin: 0;
font-family: "Inter Tight", -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto,
Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji",
"Segoe UI Symbol";
}
p {
margin: 0;
color: var(--gray-700);
}
main {
width: 100%;
min-height: 100%;
display: flex;
justify-content: center;
align-items: center;
padding: 1rem;
box-sizing: inherit;
position: relative;
}
@media screen and (max-width: 650px) {
.content {
flex-direction: column;
width: max-content;
}
.divider {
height: 1px;
width: 100%;
background: var(--red-to-pink-to-purple-horizontal-gradient);
margin-block: 1.5rem;
}
}
</style>
<main class="main">
<div *ngIf="loaded">
<video src="{{ videoURL }}" controls></video>
<br />
<button (click)="transcode()">Transcode avi to mp4</button>
<p>{{ message }}</p>
</div>
<div *ngIf="!loaded">
<button (click)="load()">Load ffmpeg-core</button>
</div>
</main>
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * The content above * * * * * * * * * * * * -->
<!-- * * * * * * * * * * is only a placeholder * * * * * * * * * * * -->
<!-- * * * * * * * * * * and can be replaced. * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<!-- * * * * * * * * * * End of Placeholder * * * * * * * * * * * * -->
<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->
<router-outlet></router-outlet>
================================================
FILE: apps/angular-app/src/app/app.component.spec.ts
================================================
import { TestBed } from '@angular/core/testing';
import { AppComponent } from './app.component';
describe('AppComponent', () => {
beforeEach(async () => {
await TestBed.configureTestingModule({
imports: [AppComponent],
}).compileComponents();
});
it('should create the app', () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app).toBeTruthy();
});
it(`should have the 'angular-app' title`, () => {
const fixture = TestBed.createComponent(AppComponent);
const app = fixture.componentInstance;
expect(app.title).toEqual('angular-app');
});
it('should render title', () => {
const fixture = TestBed.createComponent(AppComponent);
fixture.detectChanges();
const compiled = fixture.nativeElement as HTMLElement;
expect(compiled.querySelector('h1')?.textContent).toContain('Hello, angular-app');
});
});
================================================
FILE: apps/angular-app/src/app/app.component.ts
================================================
import { Component } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterOutlet } from '@angular/router';
import { FFmpeg } from '@ffmpeg/ffmpeg';
import { fetchFile, toBlobURL } from '@ffmpeg/util';
const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.10/dist/esm';
@Component({
selector: 'app-root',
standalone: true,
imports: [CommonModule, RouterOutlet],
templateUrl: './app.component.html',
styleUrl: './app.component.css',
})
export class AppComponent {
loaded = false;
ffmpeg = new FFmpeg();
videoURL = '';
message = '';
async load() {
this.ffmpeg.on('log', ({ message }) => {
this.message = message;
});
await this.ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(
`${baseURL}/ffmpeg-core.wasm`,
'application/wasm',
),
workerURL: await toBlobURL(
`${baseURL}/ffmpeg-core.worker.js`,
'text/javascript',
),
});
this.loaded = true;
}
async transcode() {
const videoURL =
'https://raw.githubusercontent.com/ffmpegwasm/testdata/master/video-15s.avi';
await this.ffmpeg.writeFile('input.avi', await fetchFile(videoURL));
await this.ffmpeg.exec(['-i', 'input.avi', 'output.mp4']);
const fileData = await this.ffmpeg.readFile('output.mp4');
const data = new Uint8Array(fileData as ArrayBuffer);
this.videoURL = URL.createObjectURL(
new Blob([data.buffer], { type: 'video/mp4' }),
);
}
}
================================================
FILE: apps/angular-app/src/app/app.config.ts
================================================
import { ApplicationConfig } from '@angular/core';
import { provideRouter } from '@angular/router';
import { routes } from './app.routes';
export const appConfig: ApplicationConfig = {
providers: [provideRouter(routes)]
};
================================================
FILE: apps/angular-app/src/app/app.routes.ts
================================================
import { Routes } from '@angular/router';
export const routes: Routes = [];
================================================
FILE: apps/angular-app/src/assets/.gitkeep
================================================
================================================
FILE: apps/angular-app/src/index.html
================================================
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>AngularApp</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
</body>
</html>
================================================
FILE: apps/angular-app/src/main.ts
================================================
import { bootstrapApplication } from '@angular/platform-browser';
import { appConfig } from './app/app.config';
import { AppComponent } from './app/app.component';
bootstrapApplication(AppComponent, appConfig)
.catch((err) => console.error(err));
================================================
FILE: apps/angular-app/src/styles.css
================================================
/* You can add global styles to this file, and also import other style files */
================================================
FILE: apps/angular-app/tsconfig.app.json
================================================
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/app",
"types": []
},
"files": [
"src/main.ts"
],
"include": [
"src/**/*.d.ts"
]
}
================================================
FILE: apps/angular-app/tsconfig.json
================================================
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"compileOnSave": false,
"compilerOptions": {
"outDir": "./dist/out-tsc",
"forceConsistentCasingInFileNames": true,
"strict": true,
"noImplicitOverride": true,
"noPropertyAccessFromIndexSignature": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"skipLibCheck": true,
"esModuleInterop": true,
"sourceMap": true,
"declaration": false,
"experimentalDecorators": true,
"moduleResolution": "node",
"importHelpers": true,
"target": "ES2022",
"module": "ES2022",
"useDefineForClassFields": false,
"lib": [
"ES2022",
"dom"
]
},
"angularCompilerOptions": {
"enableI18nLegacyMessageIdFormat": false,
"strictInjectionParameters": true,
"strictInputAccessModifiers": true,
"strictTemplates": true
}
}
================================================
FILE: apps/angular-app/tsconfig.spec.json
================================================
/* To learn more about this file see: https://angular.io/config/tsconfig. */
{
"extends": "./tsconfig.json",
"compilerOptions": {
"outDir": "./out-tsc/spec",
"types": [
"jasmine"
]
},
"include": [
"src/**/*.spec.ts",
"src/**/*.d.ts"
]
}
================================================
FILE: apps/nextjs-app/.eslintrc.json
================================================
{
"extends": "next/core-web-vitals"
}
================================================
FILE: apps/nextjs-app/.gitignore
================================================
# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.
# dependencies
/node_modules
/.pnp
.pnp.js
# testing
/coverage
# next.js
/.next/
/out/
# production
/build
# misc
.DS_Store
*.pem
# debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# local env files
.env*.local
# vercel
.vercel
# typescript
*.tsbuildinfo
next-env.d.ts
================================================
FILE: apps/nextjs-app/README.md
================================================
This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js/tree/canary/packages/create-next-app).
## Getting Started
First, run the development server:
```bash
npm run dev
# or
yarn dev
# or
pnpm dev
```
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.
This project uses [`next/font`](https://nextjs.org/docs/basic-features/font-optimization) to automatically optimize and load Inter, a custom Google Font.
## Learn More
To learn more about Next.js, take a look at the following resources:
- [Next.js Documentation](https://nextjs.org/docs) - learn about Next.js features and API.
- [Learn Next.js](https://nextjs.org/learn) - an interactive Next.js tutorial.
You can check out [the Next.js GitHub repository](https://github.com/vercel/next.js/) - your feedback and contributions are welcome!
## Deploy on Vercel
The easiest way to deploy your Next.js app is to use the [Vercel Platform](https://vercel.com/new?utm_medium=default-template&filter=next.js&utm_source=create-next-app&utm_campaign=create-next-app-readme) from the creators of Next.js.
Check out our [Next.js deployment documentation](https://nextjs.org/docs/deployment) for more details.
================================================
FILE: apps/nextjs-app/app/Home.tsx
================================================
"use client";
import { FFmpeg } from "@ffmpeg/ffmpeg";
import { fetchFile, toBlobURL } from "@ffmpeg/util";
import { useRef, useState } from "react";
export default function Home() {
const [loaded, setLoaded] = useState(false);
const [isLoading, setIsLoading] = useState(false);
const ffmpegRef = useRef(new FFmpeg());
const videoRef = useRef<HTMLVideoElement | null>(null);
const messageRef = useRef<HTMLParagraphElement | null>(null);
const load = async () => {
setIsLoading(true);
const baseURL = "https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/umd";
const ffmpeg = ffmpegRef.current;
ffmpeg.on("log", ({ message }) => {
if (messageRef.current) messageRef.current.innerHTML = message;
});
// toBlobURL is used to bypass CORS issue, urls with the same
// domain can be used directly.
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, "text/javascript"),
wasmURL: await toBlobURL(
`${baseURL}/ffmpeg-core.wasm`,
"application/wasm"
),
});
setLoaded(true);
setIsLoading(false);
};
const transcode = async () => {
const ffmpeg = ffmpegRef.current;
// u can use 'https://ffmpegwasm.netlify.app/video/video-15s.avi' to download the video to public folder for testing
await ffmpeg.writeFile(
"input.avi",
await fetchFile(
"https://raw.githubusercontent.com/ffmpegwasm/testdata/master/video-15s.avi"
)
);
await ffmpeg.exec(["-i", "input.avi", "output.mp4"]);
const data = (await ffmpeg.readFile("output.mp4")) as any;
if (videoRef.current)
videoRef.current.src = URL.createObjectURL(
new Blob([data.buffer], { type: "video/mp4" })
);
};
return loaded ? (
<div className="fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%]">
<video ref={videoRef} controls></video>
<br />
<button
onClick={transcode}
className="bg-green-500 hover:bg-green-700 text-white py-3 px-6 rounded"
>
Transcode avi to mp4
</button>
<p ref={messageRef}></p>
</div>
) : (
<button
className="fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] flex items-center bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded"
onClick={load}
>
Load ffmpeg-core
{isLoading && (
<span className="animate-spin ml-3">
<svg
viewBox="0 0 1024 1024"
focusable="false"
data-icon="loading"
width="1em"
height="1em"
fill="currentColor"
aria-hidden="true"
>
<path d="M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z"></path>
</svg>
</span>
)}
</button>
);
}
================================================
FILE: apps/nextjs-app/app/NoSSRWrapper.tsx
================================================
import dynamic from 'next/dynamic'
import React from 'react'
const NoSSRWrapper = props => (
<React.Fragment>{props.children}</React.Fragment>
)
export default dynamic(() => Promise.resolve(NoSSRWrapper), {
ssr: false
})
================================================
FILE: apps/nextjs-app/app/globals.css
================================================
@tailwind base;
@tailwind components;
@tailwind utilities;
================================================
FILE: apps/nextjs-app/app/layout.tsx
================================================
import './globals.css'
import type { Metadata } from 'next'
import { Inter } from 'next/font/google'
const inter = Inter({ subsets: ['latin'] })
export const metadata: Metadata = {
title: 'Create Next App',
description: 'Generated by create next app',
}
export default function RootLayout({
children,
}: {
children: React.ReactNode
}) {
return (
<html lang="en">
<body className={inter.className}>{children}</body>
</html>
)
}
================================================
FILE: apps/nextjs-app/app/page.tsx
================================================
'use client'
import NoSSRWrapper from "./NoSSRWrapper";
import Home from "./Home";
export default function Page() {
return <NoSSRWrapper><Home /></NoSSRWrapper>
}
================================================
FILE: apps/nextjs-app/next.config.js
================================================
/** @type {import('next').NextConfig} */
const nextConfig = {}
module.exports = nextConfig
================================================
FILE: apps/nextjs-app/package.json
================================================
{
"name": "nextjs-ffmpeg-starter",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint"
},
"dependencies": {
"@ffmpeg/ffmpeg": "*",
"@ffmpeg/util": "*",
"@types/node": "20.4.9",
"@types/react": "18.2.20",
"@types/react-dom": "18.2.7",
"autoprefixer": "10.4.14",
"eslint": "8.46.0",
"eslint-config-next": "13.4.13",
"next": "^14.0.4",
"postcss": "8.4.31",
"react": "18.2.0",
"react-dom": "18.2.0",
"tailwindcss": "3.3.3",
"typescript": "5.1.6"
}
}
================================================
FILE: apps/nextjs-app/postcss.config.js
================================================
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
================================================
FILE: apps/nextjs-app/tailwind.config.ts
================================================
import type { Config } from 'tailwindcss'
const config: Config = {
content: [
'./pages/**/*.{js,ts,jsx,tsx,mdx}',
'./components/**/*.{js,ts,jsx,tsx,mdx}',
'./app/**/*.{js,ts,jsx,tsx,mdx}',
],
theme: {
extend: {
backgroundImage: {
'gradient-radial': 'radial-gradient(var(--tw-gradient-stops))',
'gradient-conic':
'conic-gradient(from 180deg at 50% 50%, var(--tw-gradient-stops))',
},
},
},
plugins: [],
}
export default config
================================================
FILE: apps/nextjs-app/tsconfig.json
================================================
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"forceConsistentCasingInFileNames": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}
================================================
FILE: apps/react-vite-app/.eslintrc.cjs
================================================
module.exports = {
root: true,
env: { browser: true, es2020: true },
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:react-hooks/recommended',
],
ignorePatterns: ['dist', '.eslintrc.cjs'],
parser: '@typescript-eslint/parser',
plugins: ['react-refresh'],
rules: {
'react-refresh/only-export-components': [
'warn',
{ allowConstantExport: true },
],
},
}
================================================
FILE: apps/react-vite-app/.gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
dist
dist-ssr
*.local
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
.DS_Store
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
================================================
FILE: apps/react-vite-app/README.md
================================================
# React + TypeScript + Vite
This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules.
Currently, two official plugins are available:
- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react/README.md) uses [Babel](https://babeljs.io/) for Fast Refresh
- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh
## Expanding the ESLint configuration
If you are developing a production application, we recommend updating the configuration to enable type aware lint rules:
- Configure the top-level `parserOptions` property like this:
```js
parserOptions: {
ecmaVersion: 'latest',
sourceType: 'module',
project: ['./tsconfig.json', './tsconfig.node.json'],
tsconfigRootDir: __dirname,
},
```
- Replace `plugin:@typescript-eslint/recommended` to `plugin:@typescript-eslint/recommended-type-checked` or `plugin:@typescript-eslint/strict-type-checked`
- Optionally add `plugin:@typescript-eslint/stylistic-type-checked`
- Install [eslint-plugin-react](https://github.com/jsx-eslint/eslint-plugin-react) and add `plugin:react/recommended` & `plugin:react/jsx-runtime` to the `extends` list
================================================
FILE: apps/react-vite-app/index.html
================================================
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<link rel="icon" type="image/svg+xml" href="/vite.svg" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Vite + React + TS</title>
</head>
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
</body>
</html>
================================================
FILE: apps/react-vite-app/package.json
================================================
{
"name": "react-vite-app",
"private": true,
"version": "0.0.0",
"type": "module",
"scripts": {
"dev": "vite",
"build": "tsc && vite build",
"lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
"preview": "vite preview"
},
"dependencies": {
"@ffmpeg/ffmpeg": "*",
"@ffmpeg/util": "*",
"react": "^18.2.0",
"react-dom": "^18.2.0"
},
"devDependencies": {
"@types/react": "^18.2.15",
"@types/react-dom": "^18.2.7",
"@typescript-eslint/eslint-plugin": "^6.0.0",
"@typescript-eslint/parser": "^6.0.0",
"@vitejs/plugin-react": "^4.0.3",
"eslint": "^8.45.0",
"eslint-plugin-react-hooks": "^4.6.0",
"eslint-plugin-react-refresh": "^0.4.3",
"typescript": "^5.0.2",
"vite": "^4.5.2"
}
}
================================================
FILE: apps/react-vite-app/src/App.tsx
================================================
import { useState, useRef } from "react";
import { FFmpeg } from "@ffmpeg/ffmpeg";
import { toBlobURL, fetchFile } from "@ffmpeg/util";
function App() {
const [loaded, setLoaded] = useState(false);
const ffmpegRef = useRef(new FFmpeg());
const videoRef = useRef<HTMLVideoElement | null>(null);
const messageRef = useRef<HTMLParagraphElement | null>(null);
const load = async () => {
const baseURL = "https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.10/dist/esm";
const ffmpeg = ffmpegRef.current;
ffmpeg.on("log", ({ message }) => {
if (messageRef.current) messageRef.current.innerHTML = message;
});
// toBlobURL is used to bypass CORS issue, urls with the same
// domain can be used directly.
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, "text/javascript"),
wasmURL: await toBlobURL(
`${baseURL}/ffmpeg-core.wasm`,
"application/wasm"
),
workerURL: await toBlobURL(
`${baseURL}/ffmpeg-core.worker.js`,
"text/javascript"
),
});
setLoaded(true);
};
const transcode = async () => {
const videoURL =
"https://raw.githubusercontent.com/ffmpegwasm/testdata/master/video-15s.avi";
const ffmpeg = ffmpegRef.current;
await ffmpeg.writeFile("input.avi", await fetchFile(videoURL));
await ffmpeg.exec(["-i", "input.avi", "output.mp4"]);
const fileData = await ffmpeg.readFile("output.mp4");
const data = new Uint8Array(fileData as ArrayBuffer);
if (videoRef.current) {
videoRef.current.src = URL.createObjectURL(
new Blob([data.buffer], { type: "video/mp4" })
);
}
};
return loaded ? (
<>
<video ref={videoRef} controls></video>
<br />
<button onClick={transcode}>Transcode avi to mp4</button>
<p ref={messageRef}></p>
</>
) : (
<button onClick={load}>Load ffmpeg-core</button>
);
}
export default App;
================================================
FILE: apps/react-vite-app/src/index.css
================================================
:root {
font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;
line-height: 1.5;
font-weight: 400;
color-scheme: light dark;
color: rgba(255, 255, 255, 0.87);
background-color: #242424;
font-synthesis: none;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
-webkit-text-size-adjust: 100%;
}
a {
font-weight: 500;
color: #646cff;
text-decoration: inherit;
}
a:hover {
color: #535bf2;
}
body {
margin: 0;
display: flex;
place-items: center;
min-width: 320px;
min-height: 100vh;
justify-content: center;
}
h1 {
font-size: 3.2em;
line-height: 1.1;
}
button {
border-radius: 8px;
border: 1px solid transparent;
padding: 0.6em 1.2em;
font-size: 1em;
font-weight: 500;
font-family: inherit;
background-color: #1a1a1a;
cursor: pointer;
transition: border-color 0.25s;
}
button:hover {
border-color: #646cff;
}
button:focus,
button:focus-visible {
outline: 4px auto -webkit-focus-ring-color;
}
@media (prefers-color-scheme: light) {
:root {
color: #213547;
background-color: #ffffff;
}
a:hover {
color: #747bff;
}
button {
background-color: #f9f9f9;
}
}
================================================
FILE: apps/react-vite-app/src/main.tsx
================================================
import React from 'react'
import ReactDOM from 'react-dom/client'
import App from './App.tsx'
import './index.css'
ReactDOM.createRoot(document.getElementById('root')!).render(
<React.StrictMode>
<App />
</React.StrictMode>,
)
================================================
FILE: apps/react-vite-app/src/vite-env.d.ts
================================================
/// <reference types="vite/client" />
================================================
FILE: apps/react-vite-app/tsconfig.json
================================================
{
"compilerOptions": {
"target": "ES2020",
"useDefineForClassFields": true,
"lib": ["ES2020", "DOM", "DOM.Iterable"],
"module": "ESNext",
"skipLibCheck": true,
/* Bundler mode */
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"resolveJsonModule": true,
"isolatedModules": true,
"noEmit": true,
"jsx": "react-jsx",
/* Linting */
"strict": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noFallthroughCasesInSwitch": true
},
"include": ["src"],
"references": [{ "path": "./tsconfig.node.json" }]
}
================================================
FILE: apps/react-vite-app/tsconfig.node.json
================================================
{
"compilerOptions": {
"composite": true,
"skipLibCheck": true,
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true
},
"include": ["vite.config.ts"]
}
================================================
FILE: apps/react-vite-app/vite.config.ts
================================================
import { defineConfig } from "vite";
import react from "@vitejs/plugin-react";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [react()],
optimizeDeps: {
exclude: ["@ffmpeg/ffmpeg", "@ffmpeg/util"],
},
server: {
headers: {
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
},
},
});
================================================
FILE: apps/solidstart-app/.gitignore
================================================
dist
.solid
.output
.vercel
.netlify
.vinxi
# Environment
.env
.env*.local
# dependencies
/node_modules
# IDEs and editors
/.idea
.project
.classpath
*.launch
.settings/
# Temp
gitignore
# System Files
.DS_Store
Thumbs.db
================================================
FILE: apps/solidstart-app/README.md
================================================
# SolidStart
Everything you need to build a Solid project, powered by [`solid-start`](https://start.solidjs.com);
## Creating a project
```bash
# create a new project in the current directory
npm init solid@latest
# create a new project in my-app
npm init solid@latest my-app
```
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```bash
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
Solid apps are built with _presets_, which optimise your project for deployment to different environments.
By default, `npm run build` will generate a Node app that you can run with `npm start`. To use a different preset, add it to the `devDependencies` in `package.json` and specify in your `app.config.js`.
## This project was created with the [Solid CLI](https://solid-cli.netlify.app)
================================================
FILE: apps/solidstart-app/app.config.ts
================================================
import { defineConfig } from "@solidjs/start/config";
export default defineConfig({
ssr: false,
server: {
static: true,
},
vite: {
optimizeDeps: {
exclude: ['@ffmpeg/ffmpeg', '@ffmpeg/util']
},
}
});
================================================
FILE: apps/solidstart-app/package.json
================================================
{
"name": "solidstart-ffmpeg",
"type": "module",
"scripts": {
"dev": "vinxi dev",
"build": "vinxi build",
"start": "vinxi start"
},
"dependencies": {
"@ffmpeg/ffmpeg": "^0.12.15",
"@ffmpeg/util": "^0.12.2",
"@solidjs/router": "^0.14.1",
"@solidjs/start": "^1.0.4",
"autoprefixer": "^10.4.19",
"postcss": "^8.4.38",
"solid-js": "^1.8.18",
"tailwindcss": "^3.4.3",
"vinxi": "^0.5.7"
},
"engines": {
"node": ">=18"
}
}
================================================
FILE: apps/solidstart-app/postcss.config.cjs
================================================
module.exports = {
plugins: {
tailwindcss: {},
autoprefixer: {},
},
}
================================================
FILE: apps/solidstart-app/src/app.css
================================================
@tailwind base;
@tailwind components;
@tailwind utilities;
:root {
--background-rgb: 214, 219, 220;
--foreground-rgb: 0, 0, 0;
}
@media (prefers-color-scheme: dark) {
:root {
--background-rgb: 0, 0, 0;
--foreground-rgb: 255, 255, 255;
}
}
body {
background: rgb(var(--background-rgb));
color: rgb(var(--foreground-rgb));
}
================================================
FILE: apps/solidstart-app/src/app.tsx
================================================
import { Router } from '@solidjs/router';
import { FileRoutes } from '@solidjs/start/router';
import { Suspense } from 'solid-js';
import './app.css';
export default function App() {
return (
<Router
root={(props) => (
<>
<Suspense>{props.children}</Suspense>
</>
)}>
<FileRoutes />
</Router>
);
}
================================================
FILE: apps/solidstart-app/src/entry-client.tsx
================================================
// @refresh reload
import { mount, StartClient } from "@solidjs/start/client";
mount(() => <StartClient />, document.getElementById("app")!);
================================================
FILE: apps/solidstart-app/src/entry-server.tsx
================================================
// @refresh reload
import { createHandler, StartServer } from '@solidjs/start/server';
import { HttpHeader, HttpStatusCode } from '@solidjs/start';
export default createHandler(() => (
<StartServer
document={({ assets, children, scripts }) => (
<html lang='en'>
{/*necessary because ffmpeg library uses sharedArrayBuffer */}
<HttpHeader name='Cross-Origin-Opener-Policy' value='same-origin' />
<HttpHeader name='Cross-Origin-Embedder-Policy' value='require-corp' />
<head>
<meta charset='utf-8' />
<meta name='viewport' content='width=device-width, initial-scale=1' />
<link rel='icon' href='/favicon.ico' />
{assets}
</head>
<body>
<div id='app'>{children}</div>
{scripts}
</body>
</html>
)}
/>
));
================================================
FILE: apps/solidstart-app/src/global.d.ts
================================================
/// <reference types="@solidjs/start/env" />
================================================
FILE: apps/solidstart-app/src/routes/index.tsx
================================================
import { FFmpeg } from '@ffmpeg/ffmpeg';
import { fetchFile, toBlobURL } from '@ffmpeg/util';
import { createSignal, Show } from 'solid-js';
const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.10/dist/esm';
const videoURL =
'https://raw.githubusercontent.com/ffmpegwasm/testdata/master/video-15s.avi';
export default function Home() {
const [loaded, setLoaded] = createSignal(false);
const [isLoading, setIsLoading] = createSignal(false);
let ffmpegRef = new FFmpeg();
let videoRef: any = null;
let messageRef: any = null;
const load = async () => {
setIsLoading(true);
const ffmpeg = ffmpegRef;
ffmpeg.on('log', ({ message }) => {
if (messageRef) messageRef.innerHTML = message;
});
// toBlobURL is used to bypass CORS issue, urls with the same
// domain can be used directly.
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(
`${baseURL}/ffmpeg-core.wasm`,
'application/wasm'
),
workerURL: await toBlobURL(
`${baseURL}/ffmpeg-core.worker.js`,
'text/javascript'
),
});
setLoaded(true);
setIsLoading(false);
};
const transcode = async () => {
const ffmpeg = ffmpegRef;
// u can use 'https://ffmpegwasm.netlify.app/video/video-15s.avi' to download the video to public folder for testing
await ffmpeg.writeFile('input.avi', await fetchFile(videoURL));
await ffmpeg.exec(['-i', 'input.avi', 'output.mp4']);
const data = (await ffmpeg.readFile('output.mp4')) as any;
if (videoRef)
videoRef.src = URL.createObjectURL(
new Blob([data.buffer], { type: 'video/mp4' })
);
};
return (
<Show
when={loaded()}
fallback={
<button
class='fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%] flex items-center bg-blue-500 hover:bg-blue-700 text-white py-2 px-4 rounded'
onClick={load}>
Load ffmpeg-core
<Show when={isLoading()}>
<span class='animate-spin ml-3'>
<svg
viewBox='0 0 1024 1024'
data-icon='loading'
width='1em'
height='1em'
fill='currentColor'
aria-hidden='true'>
<path d='M988 548c-19.9 0-36-16.1-36-36 0-59.4-11.6-117-34.6-171.3a440.45 440.45 0 00-94.3-139.9 437.71 437.71 0 00-139.9-94.3C629 83.6 571.4 72 512 72c-19.9 0-36-16.1-36-36s16.1-36 36-36c69.1 0 136.2 13.5 199.3 40.3C772.3 66 827 103 874 150c47 47 83.9 101.8 109.7 162.7 26.7 63.1 40.2 130.2 40.2 199.3.1 19.9-16 36-35.9 36z'></path>
</svg>
</span>
</Show>
</button>
}>
<div class='fixed top-[50%] left-[50%] translate-x-[-50%] translate-y-[-50%]'>
<video ref={videoRef} controls></video>
<br />
<button
onClick={transcode}
class='bg-green-500 hover:bg-green-700 text-white py-3 px-6 rounded'>
Transcode avi to mp4
</button>
<p ref={messageRef}></p>
</div>
</Show>
);
}
================================================
FILE: apps/solidstart-app/tailwind.config.cjs
================================================
/** @type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{html,js,jsx,ts,tsx}"],
theme: {
extend: {}
},
plugins: []
};
================================================
FILE: apps/solidstart-app/tsconfig.json
================================================
{
"compilerOptions": {
"target": "ESNext",
"module": "ESNext",
"moduleResolution": "bundler",
"allowSyntheticDefaultImports": true,
"esModuleInterop": true,
"jsx": "preserve",
"jsxImportSource": "solid-js",
"allowJs": true,
"noEmit": true,
"strict": true,
"types": ["vinxi/types/client"],
"isolatedModules": true,
"paths": {
"~/*": ["./src/*"]
}
}
}
================================================
FILE: apps/sveltekit-app/.eslintignore
================================================
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock
================================================
FILE: apps/sveltekit-app/.eslintrc.cjs
================================================
/** @type { import("eslint").Linter.Config } */
module.exports = {
root: true,
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:svelte/recommended',
'prettier'
],
parser: '@typescript-eslint/parser',
plugins: ['@typescript-eslint'],
parserOptions: {
sourceType: 'module',
ecmaVersion: 2020,
extraFileExtensions: ['.svelte']
},
env: {
browser: true,
es2017: true,
node: true
},
overrides: [
{
files: ['*.svelte'],
parser: 'svelte-eslint-parser',
parserOptions: {
parser: '@typescript-eslint/parser'
}
}
]
};
================================================
FILE: apps/sveltekit-app/.gitignore
================================================
.DS_Store
node_modules
/build
/.svelte-kit
/package
.env
.env.*
!.env.example
vite.config.js.timestamp-*
vite.config.ts.timestamp-*
================================================
FILE: apps/sveltekit-app/.npmrc
================================================
engine-strict=true
================================================
FILE: apps/sveltekit-app/.prettierignore
================================================
# Ignore files for PNPM, NPM and YARN
pnpm-lock.yaml
package-lock.json
yarn.lock
================================================
FILE: apps/sveltekit-app/.prettierrc
================================================
{
"useTabs": true,
"singleQuote": true,
"trailingComma": "none",
"printWidth": 100,
"plugins": ["prettier-plugin-svelte"],
"overrides": [{ "files": "*.svelte", "options": { "parser": "svelte" } }]
}
================================================
FILE: apps/sveltekit-app/README.md
================================================
# create-svelte
Everything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs/kit/tree/main/packages/create-svelte).
## Creating a project
If you're seeing this, you've probably already done this step. Congrats!
```bash
# create a new project in the current directory
npm create svelte@latest
# create a new project in my-app
npm create svelte@latest my-app
```
## Developing
Once you've created a project and installed dependencies with `npm install` (or `pnpm install` or `yarn`), start a development server:
```bash
npm run dev
# or start the server and open the app in a new browser tab
npm run dev -- --open
```
## Building
To create a production version of your app:
```bash
npm run build
```
You can preview the production build with `npm run preview`.
> To deploy your app, you may need to install an [adapter](https://kit.svelte.dev/docs/adapters) for your target environment.
================================================
FILE: apps/sveltekit-app/package.json
================================================
{
"name": "sveltekit-app",
"version": "0.0.1",
"private": true,
"scripts": {
"dev": "vite dev",
"build": "vite build",
"preview": "vite preview",
"test": "npm run test:integration && npm run test:unit",
"check": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json",
"check:watch": "svelte-kit sync && svelte-check --tsconfig ./tsconfig.json --watch",
"lint": "prettier --check . && eslint .",
"format": "prettier --write .",
"test:integration": "playwright test",
"test:unit": "vitest"
},
"devDependencies": {
"@ffmpeg/ffmpeg": "*",
"@ffmpeg/util": "*",
"@playwright/test": "^1.41.2",
"@sveltejs/adapter-auto": "^3.1.1",
"@sveltejs/kit": "^2.5.0",
"@sveltejs/vite-plugin-svelte": "^3.0.2",
"@tsconfig/node18": "^18.2.2",
"@types/eslint": "8.56.2",
"@typescript-eslint/eslint-plugin": "^6.21.0",
"@typescript-eslint/parser": "^6.21.0",
"eslint": "^8.56.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-svelte": "^2.35.1",
"prettier": "^3.2.5",
"prettier-plugin-svelte": "^3.1.2",
"svelte": "^4.2.10",
"svelte-check": "^3.6.4",
"tslib": "^2.6.2",
"typescript": "^5.3.3",
"vite": "^5.1.1",
"vitest": "^1.2.2"
},
"type": "module"
}
================================================
FILE: apps/sveltekit-app/playwright.config.ts
================================================
import type { PlaywrightTestConfig } from '@playwright/test';
const config: PlaywrightTestConfig = {
webServer: {
command: 'npm run build && npm run preview',
port: 4173
},
testDir: 'tests',
testMatch: /(.+\.)?(test|spec)\.[jt]s/
};
export default config;
================================================
FILE: apps/sveltekit-app/src/app.d.ts
================================================
// See https://kit.svelte.dev/docs/types#app
// for information about these interfaces
declare global {
namespace App {
// interface Error {}
// interface Locals {}
// interface PageData {}
// interface PageState {}
// interface Platform {}
}
}
export {};
================================================
FILE: apps/sveltekit-app/src/app.html
================================================
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<link rel="icon" href="%sveltekit.assets%/favicon.png" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
%sveltekit.head%
</head>
<body data-sveltekit-preload-data="hover">
<div style="display: contents">%sveltekit.body%</div>
</body>
</html>
================================================
FILE: apps/sveltekit-app/src/index.test.ts
================================================
import { describe, it, expect } from 'vitest';
describe('sum test', () => {
it('adds 1 + 2 to equal 3', () => {
expect(1 + 2).toBe(3);
});
});
================================================
FILE: apps/sveltekit-app/src/lib/FFmpegDemo.svelte
================================================
<script lang="ts">
import { FFmpeg } from '@ffmpeg/ffmpeg';
// @ts-ignore
import type { LogEvent } from '@ffmpeg/ffmpeg/dist/esm/types';
import { fetchFile, toBlobURL } from '@ffmpeg/util';
let videoEl: HTMLVideoElement;
const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.10/dist/esm';
const videoURL = 'https://raw.githubusercontent.com/ffmpegwasm/testdata/master/video-15s.avi';
let message = 'Click Start to Transcode';
async function transcode() {
const ffmpeg = new FFmpeg();
message = 'Loading ffmpeg-core.js';
ffmpeg.on('log', ({ message: msg }: LogEvent) => {
message = msg;
console.log(message);
});
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript')
});
message = 'Start transcoding';
await ffmpeg.writeFile('test.avi', await fetchFile(videoURL));
await ffmpeg.exec(['-i', 'test.avi', 'test.mp4']);
message = 'Complete transcoding';
const data = await ffmpeg.readFile('test.mp4');
console.log('done');
videoEl.src = URL.createObjectURL(
new Blob([(data as Uint8Array).buffer], { type: 'video/mp4' })
);
}
</script>
<div>
<!-- svelte-ignore a11y-media-has-caption -->
<video bind:this={videoEl} controls />
<br />
<button on:click={transcode}>Start</button>
<p>{message}</p>
</div>
================================================
FILE: apps/sveltekit-app/src/lib/index.ts
================================================
// place files you want to import through the `$lib` alias in this folder.
================================================
FILE: apps/sveltekit-app/src/routes/+page.svelte
================================================
<script lang="ts">
import FFmpegDemo from '../lib/FFmpegDemo.svelte';
</script>
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
<FFmpegDemo></FFmpegDemo>
================================================
FILE: apps/sveltekit-app/svelte.config.js
================================================
import adapter from '@sveltejs/adapter-auto';
import { vitePreprocess } from '@sveltejs/vite-plugin-svelte';
/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://kit.svelte.dev/docs/integrations#preprocessors
// for more information about preprocessors
preprocess: vitePreprocess(),
kit: {
// adapter-auto only supports some environments, see https://kit.svelte.dev/docs/adapter-auto for a list.
// If your environment is not supported or you settled on a specific environment, switch out the adapter.
// See https://kit.svelte.dev/docs/adapters for more information about adapters.
adapter: adapter()
}
};
export default config;
================================================
FILE: apps/sveltekit-app/tests/test.ts
================================================
import { expect, test } from '@playwright/test';
test('index page has expected h1', async ({ page }) => {
await page.goto('/');
await expect(page.getByRole('heading', { name: 'Welcome to SvelteKit' })).toBeVisible();
});
================================================
FILE: apps/sveltekit-app/tsconfig.json
================================================
{
"extends": "./.svelte-kit/tsconfig.json",
"compilerOptions": {
"allowJs": true,
"checkJs": true,
"esModuleInterop": true,
"forceConsistentCasingInFileNames": true,
"resolveJsonModule": true,
"skipLibCheck": true,
"sourceMap": true,
"strict": true,
"moduleResolution": "bundler"
}
// Path aliases are handled by https://kit.svelte.dev/docs/configuration#alias
//
// If you want to overwrite includes/excludes, make sure to copy over the relevant includes/excludes
// from the referenced tsconfig.json - TypeScript does not merge them in
}
================================================
FILE: apps/sveltekit-app/vite.config.ts
================================================
import { sveltekit } from '@sveltejs/kit/vite';
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vitest/config';
/** @type {import('vite').Plugin} */
const viteServerConfig = {
name: 'log-request-middleware',
configureServer(server) {
server.middlewares.use((req, res, next) => {
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Methods", "GET");
res.setHeader("Cross-Origin-Opener-Policy", "same-origin");
res.setHeader("Cross-Origin-Embedder-Policy", "require-corp");
next();
});
}
};
export default defineConfig({
plugins: [sveltekit(), viteServerConfig],
test: {
include: ['src/**/*.{test,spec}.{js,ts}']
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
optimizeDeps: {
exclude: ['@ffmpeg/ffmpeg', '@ffmpeg/util']
},
server: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp'
},
fs: {
allow: ['../..']
}
}
});
================================================
FILE: apps/vanilla-app/.gitignore
================================================
*.tgz
public/assets
================================================
FILE: apps/vanilla-app/README.md
================================================
# Vanilla / Browser Examples
## Setup
You need to download assets from npm before running the examples:
```bash
$ npm run download
```
## Run
To run this example, execute:
```bash
$ npm start
```
Visit http://localhost:8080 to check available examples.
## Examples
| Example | Description |
| ------- | ----------- |
| transcode.html | Transcoding example |
| transcode-mt.html | Transcoding example using multi-thread |
| transcode.esm.html | Transcoding example using module |
| trim.html | Video trimming example |
| concatDemuxer.html | Video concat example |
================================================
FILE: apps/vanilla-app/package.json
================================================
{
"name": "browser",
"version": "0.12.0-alpha.0",
"description": "browser example",
"private": true,
"scripts": {
"download": "node ../../scripts/download-assets.js",
"prestart": "npm run download",
"start": "node server.js"
},
"author": "Jerome Wu <jeromewus@gmail.com>",
"license": "MIT",
"dependencies": {
"express": "^4.19.2",
"serve-index": "^1.9.1",
"tar": "^6.2.1"
}
}
================================================
FILE: apps/vanilla-app/public/concatDemuxer.html
================================================
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="/assets/ffmpeg/package/dist/umd/ffmpeg.js"></script>
<script src="/assets/util/package/dist/umd/index.js"></script>
</head>
<body>
<h3>Select multiple video files to Concatenate</h3>
<video id="output-video" controls></video><br />
<input type="file" id="uploader" multiple />
<p id="message"></p>
<script>
const { fetchFile } = FFmpegUtil;
const { FFmpeg } = FFmpegWASM;
let ffmpeg = null;
const transcode = async ({ target: { files } }) => {
const message = document.getElementById("message");
if (ffmpeg === null) {
ffmpeg = new FFmpeg();
ffmpeg.on("log", ({ message }) => {
console.log(message);
})
ffmpeg.on("progress", ({ progress, time }) => {
message.innerHTML = `${time / 1000000} s`;
});
await ffmpeg.load({
coreURL: "/assets/core/package/dist/umd/ffmpeg-core.js",
});
}
message.innerHTML = "Start Concating";
const inputPaths = [];
for (const file of files) {
const { name } = file;
ffmpeg.writeFile(name, await fetchFile(file));
inputPaths.push(`file ${name}`);
}
await ffmpeg.writeFile('concat_list.txt', inputPaths.join('\n'));
await ffmpeg.exec(['-f', 'concat', '-safe', '0', '-i', 'concat_list.txt', 'output.mp4']);
message.innerHTML = "Complete Concating";
const data = await ffmpeg.readFile('output.mp4');
const video = document.getElementById("output-video");
video.src = URL.createObjectURL(
new Blob([data.buffer], {
type: "video/mp4"
})
);
};
const elm = document.getElementById("uploader");
elm.addEventListener("change", transcode);
</script>
</body>
</html>
================================================
FILE: apps/vanilla-app/public/style.css
================================================
html, body {
margin: 0;
width: 100%;
height: 100%
}
body {
display: flex;
flex-direction: column;
align-items: center;
}
================================================
FILE: apps/vanilla-app/public/transcode-mt.esm.html
================================================
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h3>Upload a video to transcode to mp4 (x264) and play!</h3>
<video id="output-video" controls></video><br/>
<input type="file" id="uploader">
<p id="message"></p>
<script type="module">
import { FFmpeg } from "/assets/ffmpeg/package/dist/esm/index.js";
import { fetchFile } from "/assets/util/package/dist/esm/index.js";
let ffmpeg = null;
const transcode = async ({ target: { files } }) => {
const message = document.getElementById('message');
if (ffmpeg === null) {
ffmpeg = new FFmpeg();
ffmpeg.on("log", ({ message }) => {
console.log(message);
})
ffmpeg.on("progress", ({ progress }) => {
message.innerHTML = `${progress * 100} %`;
});
await ffmpeg.load({
coreURL: "/assets/core-mt/package/dist/esm/ffmpeg-core.js",
});
}
const { name } = files[0];
await ffmpeg.writeFile(name, await fetchFile(files[0]));
message.innerHTML = 'Start transcoding';
await ffmpeg.exec(['-i', name, 'output.mp4']);
message.innerHTML = 'Complete transcoding';
const data = await ffmpeg.readFile('output.mp4');
const video = document.getElementById('output-video');
video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
}
const elm = document.getElementById('uploader');
elm.addEventListener('change', transcode);
</script>
</body>
</html>
================================================
FILE: apps/vanilla-app/public/transcode-mt.html
================================================
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="/assets/ffmpeg/package/dist/umd/ffmpeg.js"></script>
<script src="/assets/util/package/dist/umd/index.js"></script>
</head>
<body>
<h3>Upload a video to transcode to mp4 (x264) and play!</h3>
<video id="output-video" controls></video><br/>
<input type="file" id="uploader">
<p id="message"></p>
<script>
const { fetchFile } = FFmpegUtil;
const { FFmpeg } = FFmpegWASM;
let ffmpeg = null;
const transcode = async ({ target: { files } }) => {
const message = document.getElementById('message');
if (ffmpeg === null) {
ffmpeg = new FFmpeg();
ffmpeg.on("log", ({ message }) => {
console.log(message);
})
ffmpeg.on("progress", ({ progress, time }) => {
message.innerHTML = `${progress * 100} %, time: ${time / 1000000} s`;
});
await ffmpeg.load({
coreURL: "/assets/core-mt/package/dist/umd/ffmpeg-core.js",
});
}
const { name } = files[0];
await ffmpeg.writeFile(name, await fetchFile(files[0]));
message.innerHTML = 'Start transcoding';
console.time('exec');
await ffmpeg.exec(['-i', name, 'output.mp4']);
console.timeEnd('exec');
message.innerHTML = 'Complete transcoding';
const data = await ffmpeg.readFile('output.mp4');
const video = document.getElementById('output-video');
video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
}
const elm = document.getElementById('uploader');
elm.addEventListener('change', transcode);
</script>
</body>
</html>
================================================
FILE: apps/vanilla-app/public/transcode.esm.html
================================================
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<h3>Upload a video to transcode to mp4 (x264) and play!</h3>
<video id="output-video" controls></video><br/>
<input type="file" id="uploader">
<p id="message"></p>
<script type="module">
import { FFmpeg } from "/assets/ffmpeg/package/dist/esm/index.js";
import { fetchFile } from "/assets/util/package/dist/esm/index.js";
let ffmpeg = null;
const transcode = async ({ target: { files } }) => {
const message = document.getElementById('message');
if (ffmpeg === null) {
ffmpeg = new FFmpeg();
ffmpeg.on("log", ({ message }) => {
console.log(message);
})
ffmpeg.on("progress", ({ progress }) => {
message.innerHTML = `${progress * 100} %`;
});
await ffmpeg.load({
coreURL: "/assets/core/package/dist/esm/ffmpeg-core.js",
});
}
const { name } = files[0];
await ffmpeg.writeFile(name, await fetchFile(files[0]));
message.innerHTML = 'Start transcoding';
await ffmpeg.exec(['-i', name, 'output.mp4']);
message.innerHTML = 'Complete transcoding';
const data = await ffmpeg.readFile('output.mp4');
const video = document.getElementById('output-video');
video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
}
const elm = document.getElementById('uploader');
elm.addEventListener('change', transcode);
</script>
</body>
</html>
================================================
FILE: apps/vanilla-app/public/transcode.html
================================================
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="/assets/ffmpeg/package/dist/umd/ffmpeg.js"></script>
<script src="/assets/util/package/dist/umd/index.js"></script>
</head>
<body>
<h3>Upload a video to transcode to mp4 (x264) and play!</h3>
<video id="output-video" controls></video><br/>
<input type="file" id="uploader">
<p id="message"></p>
<script>
const { fetchFile } = FFmpegUtil;
const { FFmpeg } = FFmpegWASM;
let ffmpeg = null;
const transcode = async ({ target: { files } }) => {
const message = document.getElementById('message');
if (ffmpeg === null) {
ffmpeg = new FFmpeg();
ffmpeg.on("log", ({ message }) => {
console.log(message);
})
ffmpeg.on("progress", ({ progress, time }) => {
message.innerHTML = `${progress * 100} %, time: ${time / 1000000} s`;
});
await ffmpeg.load({
coreURL: "/assets/core/package/dist/umd/ffmpeg-core.js",
});
}
const { name } = files[0];
await ffmpeg.writeFile(name, await fetchFile(files[0]));
message.innerHTML = 'Start transcoding';
console.time('exec');
await ffmpeg.exec(['-i', name, 'output.mp4']);
console.timeEnd('exec');
message.innerHTML = 'Complete transcoding';
const data = await ffmpeg.readFile('output.mp4');
const video = document.getElementById('output-video');
video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
}
const elm = document.getElementById('uploader');
elm.addEventListener('change', transcode);
</script>
</body>
</html>
================================================
FILE: apps/vanilla-app/public/trim.html
================================================
<html>
<head>
<link rel="stylesheet" href="style.css">
<script src="/assets/ffmpeg/package/dist/umd/ffmpeg.js"></script>
<script src="/assets/util/package/dist/umd/index.js"></script>
</head>
<body>
<h3>Upload a mp4 (x264) video and trim its first 1 seconds and play!</h3>
<video id="output-video" controls></video><br/>
<input type="file" id="uploader">
<p id="message"></p>
<script>
const { fetchFile } = FFmpegUtil;
const { FFmpeg } = FFmpegWASM;
let ffmpeg = null;
const trim = async ({ target: { files } }) => {
const message = document.getElementById('message');
if (ffmpeg === null) {
ffmpeg = new FFmpeg();
ffmpeg.on("log", ({ message }) => {
console.log(message);
})
ffmpeg.on("progress", ({ progress }) => {
message.innerHTML = `${progress * 100} %`;
});
await ffmpeg.load({
coreURL: "/assets/core/package/dist/umd/ffmpeg-core.js",
});
}
const { name } = files[0];
await ffmpeg.writeFile(name, await fetchFile(files[0]));
message.innerHTML = 'Start trimming';
await ffmpeg.exec(['-i', name, '-ss', '0', '-to', '1', 'output.mp4']);
message.innerHTML = 'Complete trimming';
const data = await ffmpeg.readFile('output.mp4');
const video = document.getElementById('output-video');
video.src = URL.createObjectURL(new Blob([data.buffer], { type: 'video/mp4' }));
}
const elm = document.getElementById('uploader');
elm.addEventListener('change', trim);
</script>
</body>
</html>
================================================
FILE: apps/vanilla-app/server.js
================================================
const path = require("path");
const express = require("express");
const serveIndex = require("serve-index");
const app = express();
const PORT = 8080;
const ROOT = path.join(__dirname, "public");
app.use((_, res, next) => {
res.set({
"Cross-Origin-Opener-Policy": "same-origin",
"Cross-Origin-Embedder-Policy": "require-corp",
"Cross-Origin-Resource-Policy": "cross-origin",
"Origin-Agent-Cluster": "?1",
"Access-Control-Allow-Origin": "*",
"Access-Control-Allow-Methods": "GET, POST, OPTIONS",
"Access-Control-Allow-Headers":
"Origin, X-Requested-With, Content-Type, Accept, Range",
});
next();
});
app.use(express.static(ROOT));
app.use("/", serveIndex(ROOT));
app.listen(PORT, () => {
console.log(`Listening on port ${PORT}`);
});
================================================
FILE: apps/vue-vite-app/.eslintrc.cjs
================================================
/* eslint-env node */
require('@rushstack/eslint-patch/modern-module-resolution')
module.exports = {
root: true,
'extends': [
'plugin:vue/vue3-essential',
'eslint:recommended',
'@vue/eslint-config-typescript',
'@vue/eslint-config-prettier/skip-formatting'
],
parserOptions: {
ecmaVersion: 'latest'
}
}
================================================
FILE: apps/vue-vite-app/.gitignore
================================================
# Logs
logs
*.log
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
lerna-debug.log*
node_modules
.DS_Store
dist
dist-ssr
coverage
*.local
/cypress/videos/
/cypress/screenshots/
# Editor directories and files
.vscode/*
!.vscode/extensions.json
.idea
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw?
================================================
FILE: apps/vue-vite-app/.prettierrc.json
================================================
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": false,
"tabWidth": 2,
"singleQuote": true,
"printWidth": 100,
"trailingComma": "none"
}
================================================
FILE: apps/vue-vite-app/.vscode/extensions.json
================================================
{
"recommendations": ["Vue.volar", "Vue.vscode-typescript-vue-plugin"]
}
================================================
FILE: apps/vue-vite-app/README.md
================================================
# vue-vite-app
This template should help get you started developing with Vue 3 in Vite.
## Recommended IDE Setup
[VSCode](https://code.visualstudio.com/) + [Volar](https://marketplace.visualstudio.com/items?itemName=Vue.volar) (and disable Vetur) + [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin).
## Type Support for `.vue` Imports in TS
TypeScript cannot handle type information for `.vue` imports by default, so we replace the `tsc` CLI with `vue-tsc` for type checking. In editors, we need [TypeScript Vue Plugin (Volar)](https://marketplace.visualstudio.com/items?itemName=Vue.vscode-typescript-vue-plugin) to make the TypeScript language service aware of `.vue` types.
If the standalone TypeScript plugin doesn't feel fast enough to you, Volar has also implemented a [Take Over Mode](https://github.com/johnsoncodehk/volar/discussions/471#discussioncomment-1361669) that is more performant. You can enable it by the following steps:
1. Disable the built-in TypeScript Extension
1) Run `Extensions: Show Built-in Extensions` from VSCode's command palette
2) Find `TypeScript and JavaScript Language Features`, right click and select `Disable (Workspace)`
2. Reload the VSCode window by running `Developer: Reload Window` from the command palette.
## Customize configuration
See [Vite Configuration Reference](https://vitejs.dev/config/).
## Project Setup
```sh
npm install
```
### Compile and Hot-Reload for Development
```sh
npm run dev
```
### Type-Check, Compile and Minify for Production
```sh
npm run build
```
### Lint with [ESLint](https://eslint.org/)
```sh
npm run lint
```
================================================
FILE: apps/vue-vite-app/env.d.ts
================================================
/// <reference types="vite/client" />
================================================
FILE: apps/vue-vite-app/index.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<link rel="icon" href="/favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Vite App</title>
</head>
<body>
<div id="app"></div>
<script type="module" src="/src/main.ts"></script>
</body>
</html>
================================================
FILE: apps/vue-vite-app/package.json
================================================
{
"name": "vue-vite-app",
"version": "0.0.0",
"private": true,
"scripts": {
"dev": "vite",
"build": "run-p type-check build-only",
"preview": "vite preview",
"build-only": "vite build",
"type-check": "vue-tsc --noEmit -p tsconfig.app.json --composite false",
"lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore",
"format": "prettier --write src/"
},
"dependencies": {
"@ffmpeg/ffmpeg": "*",
"@ffmpeg/util": "*",
"vue": "^3.4.18"
},
"devDependencies": {
"@rushstack/eslint-patch": "^1.7.2",
"@tsconfig/node18": "^18.2.2",
"@types/node": "^20.11.17",
"@vitejs/plugin-vue": "^5.0.4",
"@vitejs/plugin-vue-jsx": "^3.1.0",
"@vue/eslint-config-prettier": "^9.0.0",
"@vue/eslint-config-typescript": "^12.0.0",
"@vue/tsconfig": "^0.5.1",
"eslint": "^8.56.0",
"eslint-plugin-vue": "^9.21.1",
"npm-run-all": "^4.1.5",
"prettier": "^3.2.5",
"typescript": "~5.3.3",
"vite": "^4.5.2",
"vue-tsc": "^1.8.27"
}
}
================================================
FILE: apps/vue-vite-app/src/App.vue
================================================
<script setup lang="ts">
import FFmpegDemo from './components/FFmpegDemo.vue'
</script>
<template>
<main>
<FFmpegDemo />
</main>
</template>
================================================
FILE: apps/vue-vite-app/src/assets/base.css
================================================
/* color palette from <https://github.com/vuejs/theme> */
:root {
--vt-c-white: #ffffff;
--vt-c-white-soft: #f8f8f8;
--vt-c-white-mute: #f2f2f2;
--vt-c-black: #181818;
--vt-c-black-soft: #222222;
--vt-c-black-mute: #282828;
--vt-c-indigo: #2c3e50;
--vt-c-divider-light-1: rgba(60, 60, 60, 0.29);
--vt-c-divider-light-2: rgba(60, 60, 60, 0.12);
--vt-c-divider-dark-1: rgba(84, 84, 84, 0.65);
--vt-c-divider-dark-2: rgba(84, 84, 84, 0.48);
--vt-c-text-light-1: var(--vt-c-indigo);
--vt-c-text-light-2: rgba(60, 60, 60, 0.66);
--vt-c-text-dark-1: var(--vt-c-white);
--vt-c-text-dark-2: rgba(235, 235, 235, 0.64);
}
/* semantic color variables for this project */
:root {
--color-background: var(--vt-c-white);
--color-background-soft: var(--vt-c-white-soft);
--color-background-mute: var(--vt-c-white-mute);
--color-border: var(--vt-c-divider-light-2);
--color-border-hover: var(--vt-c-divider-light-1);
--color-heading: var(--vt-c-text-light-1);
--color-text: var(--vt-c-text-light-1);
--section-gap: 160px;
}
@media (prefers-color-scheme: dark) {
:root {
--color-background: var(--vt-c-black);
--color-background-soft: var(--vt-c-black-soft);
--color-background-mute: var(--vt-c-black-mute);
--color-border: var(--vt-c-divider-dark-2);
--color-border-hover: var(--vt-c-divider-dark-1);
--color-heading: var(--vt-c-text-dark-1);
--color-text: var(--vt-c-text-dark-2);
}
}
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
font-weight: normal;
}
body {
min-height: 100vh;
color: var(--color-text);
background: var(--color-background);
transition:
color 0.5s,
background-color 0.5s;
line-height: 1.6;
font-family:
Inter,
-apple-system,
BlinkMacSystemFont,
'Segoe UI',
Roboto,
Oxygen,
Ubuntu,
Cantarell,
'Fira Sans',
'Droid Sans',
'Helvetica Neue',
sans-serif;
font-size: 15px;
text-rendering: optimizeLegibility;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
}
================================================
FILE: apps/vue-vite-app/src/assets/main.css
================================================
@import './base.css';
#app {
max-width: 1280px;
margin: 0 auto;
padding: 2rem;
font-weight: normal;
}
a,
.green {
text-decoration: none;
color: hsla(160, 100%, 37%, 1);
transition: 0.4s;
}
@media (hover: hover) {
a:hover {
background-color: hsla(160, 100%, 37%, 0.2);
}
}
@media (min-width: 1024px) {
body {
display: flex;
place-items: center;
}
#app {
display: grid;
grid-template-columns: 1fr 1fr;
padding: 0 2rem;
}
}
================================================
FILE: apps/vue-vite-app/src/components/FFmpegDemo.vue
================================================
<template>
<video :src="video" controls />
<br />
<button @click="transcode">Start</button>
<p>{{ message }}</p>
</template>
<script lang="ts">
import { FFmpeg } from '@ffmpeg/ffmpeg'
import type { LogEvent } from '@ffmpeg/ffmpeg/dist/esm/types'
import { fetchFile, toBlobURL } from '@ffmpeg/util'
import { defineComponent, ref } from 'vue'
const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.10/dist/esm'
const videoURL = 'https://raw.githubusercontent.com/ffmpegwasm/testdata/master/video-15s.avi'
export default defineComponent({
name: 'App',
setup() {
const ffmpeg = new FFmpeg()
const message = ref('Click Start to Transcode')
let video = ref('')
async function transcode() {
message.value = 'Loading ffmpeg-core.js'
ffmpeg.on('log', ({ message: msg }: LogEvent) => {
message.value = msg
})
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript')
})
message.value = 'Start transcoding'
await ffmpeg.writeFile('test.avi', await fetchFile(videoURL))
await ffmpeg.exec(['-i', 'test.avi', 'test.mp4'])
message.value = 'Complete transcoding'
const data = await ffmpeg.readFile('test.mp4')
video.value = URL.createObjectURL(
new Blob([(data as Uint8Array).buffer], { type: 'video/mp4' })
)
}
return {
video,
message,
transcode
}
}
})
</script>
<style>
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
================================================
FILE: apps/vue-vite-app/src/main.ts
================================================
import './assets/main.css'
import { createApp } from 'vue'
import App from './App.vue'
createApp(App).mount('#app')
================================================
FILE: apps/vue-vite-app/tsconfig.app.json
================================================
{
"extends": "@vue/tsconfig/tsconfig.dom.json",
"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
"exclude": ["src/**/__tests__/*"],
"compilerOptions": {
"composite": true,
"baseUrl": ".",
"paths": {
"@/*": ["./src/*"]
},
"target": "esnext",
"moduleResolution": "node"
}
}
================================================
FILE: apps/vue-vite-app/tsconfig.json
================================================
{
"files": [],
"references": [
{
"path": "./tsconfig.node.json"
},
{
"path": "./tsconfig.app.json"
}
]
}
================================================
FILE: apps/vue-vite-app/tsconfig.node.json
================================================
{
"extends": "@tsconfig/node18/tsconfig.json",
"include": [
"vite.config.*",
"vitest.config.*",
"cypress.config.*",
"nightwatch.conf.*",
"playwright.config.*"
],
"compilerOptions": {
"composite": true,
"module": "ESNext",
"moduleResolution": "Bundler",
"types": ["node"]
}
}
================================================
FILE: apps/vue-vite-app/vite.config.ts
================================================
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
// https://vitejs.dev/config/
export default defineConfig({
plugins: [vue(), vueJsx()],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
},
optimizeDeps: {
exclude: ['@ffmpeg/ffmpeg', '@ffmpeg/util']
},
server: {
headers: {
'Cross-Origin-Opener-Policy': 'same-origin',
'Cross-Origin-Embedder-Policy': 'require-corp'
}
}
})
================================================
FILE: apps/website/.gitignore
================================================
# Dependencies
/node_modules
# Production
/build
/docs/api
# Generated files
.docusaurus
.cache-loader
# Misc
.DS_Store
.env.local
.env.development.local
.env.test.local
.env.production.local
npm-debug.log*
yarn-debug.log*
yarn-error.log*
================================================
FILE: apps/website/README.md
================================================
# Website
This website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.
### Installation
When cloning the repository, make sure you have git-lfs installed. If you install git-lfs after cloning, simple run
`git lfs pull` to download large files.
```
$ npm install
```
### Local Development
```
$ npm start
```
This command starts a local development server and opens up a browser window. Most changes are reflected live without having to restart the server.
### Build
```
$ npm run build
```
This command generates static content into the `build` directory and can be served using any static contents hosting service.
### Deployment
Using SSH:
```
$ USE_SSH=true npm run deploy
```
Not using SSH:
```
$ GIT_USER=<Your GitHub username> npm run deploy
```
If you are using GitHub pages for hosting, this command is a convenient way to build the website and push to the `gh-pages` branch.
================================================
FILE: apps/website/assets/ffmpegwasm-arch.drawio
================================================
<mxfile host="Electron" modified="2023-07-25T14:12:19.793Z" agent="Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/21.6.1 Chrome/112.0.5615.204 Electron/24.6.1 Safari/537.36" etag="yk2PXCvCPGaUw3GiHUln" version="21.6.1" type="device">
<diagram name="Page-1" id="EXaSSQoJnIOsS1fF1PBt">
<mxGraphModel dx="1114" dy="829" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="1169" pageHeight="827" math="0" shadow="0">
<root>
<mxCell id="0" />
<mxCell id="1" parent="0" />
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-27" value="if core is multithread version" style="rounded=0;whiteSpace=wrap;html=1;verticalAlign=top;dashed=1;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="720" y="110" width="220" height="420" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-7" value="Sends Message" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.25;exitDx=0;exitDy=0;entryX=0;entryY=0.25;entryDx=0;entryDy=0;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" edge="1" parent="1" source="veUAN4s3yOlf8Hxa7Fyb-1" target="veUAN4s3yOlf8Hxa7Fyb-3">
<mxGeometry relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-1" value="ffmpeg<br style="font-size: 14px;">(JavaScript)" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#dae8fc;strokeColor=#6c8ebf;verticalAlign=top;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="130" y="110" width="120" height="420" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-2" value="Main Thread" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="145" y="50" width="90" height="30" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-8" value="Sends Message" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0;exitY=0.75;exitDx=0;exitDy=0;entryX=1;entryY=0.75;entryDx=0;entryDy=0;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" edge="1" parent="1" source="veUAN4s3yOlf8Hxa7Fyb-3" target="veUAN4s3yOlf8Hxa7Fyb-1">
<mxGeometry relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-3" value="ffmpeg.worker<br style="font-size: 14px;">(JavaScript)" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;verticalAlign=top;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="450" y="110" width="150" height="420" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-4" value="Web Worker<br style="font-size: 14px;">(Worker Thread)" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="465" y="50" width="120" height="30" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-5" value="load()" style="rounded=0;whiteSpace=wrap;html=1;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="140" y="210" width="100" height="50" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-6" value="exec()" style="rounded=0;whiteSpace=wrap;html=1;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="140" y="280" width="100" height="50" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-22" value="Spawns" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" edge="1" parent="1" source="veUAN4s3yOlf8Hxa7Fyb-9" target="veUAN4s3yOlf8Hxa7Fyb-20">
<mxGeometry x="0.0087" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-23" value="Spawns" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" edge="1" parent="1" source="veUAN4s3yOlf8Hxa7Fyb-9" target="veUAN4s3yOlf8Hxa7Fyb-15">
<mxGeometry x="0.0025" relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-24" value="Spawns" style="rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" edge="1" parent="1" source="veUAN4s3yOlf8Hxa7Fyb-9" target="veUAN4s3yOlf8Hxa7Fyb-21">
<mxGeometry relative="1" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-9" value="ffmpeg-core<br style="font-size: 14px;">(WebAssembly)" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;verticalAlign=top;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="465" y="210" width="120" height="230" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-10" value="File System" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#e1d5e7;strokeColor=#9673a6;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="475" y="378" width="100" height="46" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-25" value="" style="edgeStyle=orthogonalEdgeStyle;rounded=0;orthogonalLoop=1;jettySize=auto;html=1;exitX=0.5;exitY=1;exitDx=0;exitDy=0;startArrow=classic;startFill=1;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" edge="1" parent="1" source="veUAN4s3yOlf8Hxa7Fyb-11" target="veUAN4s3yOlf8Hxa7Fyb-10">
<mxGeometry relative="1" as="geometry">
<mxPoint as="offset" />
</mxGeometry>
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-11" value="exec()" style="rounded=0;whiteSpace=wrap;html=1;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="475" y="260" width="100" height="50" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-15" value="ffmpeg-core.worker<br style="font-size: 14px;">(JavaScript)" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;verticalAlign=middle;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="755" y="160" width="150" height="70" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-20" value="ffmpeg-core.worker<br style="font-size: 14px;">(JavaScript)" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;verticalAlign=middle;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="755" y="290" width="150" height="70" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-21" value="ffmpeg-core.worker<br style="font-size: 14px;">(JavaScript)" style="rounded=0;whiteSpace=wrap;html=1;fillColor=#f8cecc;strokeColor=#b85450;verticalAlign=middle;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="755" y="410" width="150" height="70" as="geometry" />
</mxCell>
<mxCell id="veUAN4s3yOlf8Hxa7Fyb-26" value="File I/O" style="text;html=1;strokeColor=none;fillColor=#e1d5e7;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;fontSize=14;fontFamily=Noto Sans;fontSource=https%3A%2F%2Ffonts.googleapis.com%2Fcss%3Ffamily%3DNoto%2BSans;" vertex="1" parent="1">
<mxGeometry x="495" y="330" width="60" height="30" as="geometry" />
</mxCell>
</root>
</mxGraphModel>
</diagram>
</mxfile>
================================================
FILE: apps/website/babel.config.js
================================================
module.exports = {
presets: [require.resolve('@docusaurus/core/lib/babel/preset')],
};
================================================
FILE: apps/website/blog/2023-07-26-release-ffmpeg.wasm-0.12.0.mdx
================================================
---
slug: release-ffmpeg.wasm-0.12.0
title: Release ffmpeg.wasm 0.12.0
authors: [jeromewu]
tags: [ffmpeg.wasm]
---
Finally, a new start. :tada:
<!--truncate-->
I started to work on ffmpeg.wasm around Oct. 2019, it was the time
WebAssembly is still in very early stage and transpiling FFmpeg to ffmpeg.wasm
was very challenging. (but possible as there was a pioneer project
[ffmpeg.js](https://github.com/Kagami/ffmpeg.js/)) Over these years, I
have been trying to make ffmpeg.wasm to be production-grade, but failed
as FFmpeg is such a powerful framework and WebAssembly is still evolving.
It wasn't easy to support even one requirements (ex. RTSP) from the community
and I found it really hard to continue sometimes. But with almost **11k stars**,
**600 forks**, **4.1k used-by projects** and **2.3M downloads** in total,
I still believe ffmpeg.wasm is a meaningful project to continue.
That's why I decided to pause a little while and rethink what
should be done in the next stage.
As the result, I started to work on ffmpeg.wasm 0.12.0, it is a major version and
not backward compatible with 0.11.0. Massive issues are fixed in this version,
including:
- Upgrade Emscripten to 3.1.40
- Upgrade FFmpeg to n5.1.3
- Docker build with cache (reduce time to build a new version)
- Support timeout(), terminate() and other fundamental operations
- Split libraries to multiple small libraries
- Rewrite the whole library with TypeScript
- Merge multiple repositories into one monorepo
- Offical Web Worker support
- Offical single thread and multi thread version support
- Enhanced documentation
- Official domain name
Lots of features are still in the backlog and it requires lots effort to
even just compelete one of them, such as:
- Speed up ffmpeg.wasm using WebAssembly intrinsic
- Support RTSP protocol
- Support more popular libraries
I believe there is still a long way to go for ffmpeg.wasm to really become
a production-grade library, but it is defintely a gamechanger and a chance
to see the potential of WebAssembly and web technologies in general. That's
why I am working on it and welcome to join us.
Hope you enjoy this release :smile:
\- Jerome
================================================
FILE: apps/website/blog/authors.yml
================================================
jeromewu:
name: Jerome Wu
title: Maintainer of ffmpeg.wasm
url: https://github.com/jeromewu
image_url: /img/jeromewu.png
================================================
FILE: apps/website/deploy.sh
================================================
#!/bin/bash
npm install
npm run build
================================================
FILE: apps/website/docs/contribution/core.md
================================================
# @ffmpeg/core
To build @ffmpeg/core, make sure your docker is version 23.0+ as
[buildx](https://docs.docker.com/build/architecture/) is adopted. Also
You will need to install `make` to run build scripts.
## Build
Dev Build (single thread):
```bash
$ make dev
```
Dev Build (multithread):
```bash
$ make dev-mt
```
Prodution Build (single thread):
```bash
$ make prd
```
Prodution Build (multithread):
```bash
$ make prd-mt
```
> Each build might take around 1 hour depends on the spec of your machine,
> subsequent builds are faster as most layers are cached.
The output file locates at **/packages/core** or **/packages/core-mt**.
## Custom Build / Reduce Build Size
You can customize your build to include only the libraries you need, which can significantly reduce the final build size. This is done by modifying the `Dockerfile`.
---
### Step-by-Step Example: Removing WebP Support
Here's how to remove `libwebp` (WebP image support) from the build. The same principle applies to other libraries.
You need to make changes in **4 places** in the `Dockerfile`:
#### 1. Remove the library builder stage
Find the stage that builds the library you want to remove and delete the entire block:
```dockerfile
# Remove this entire block
FROM emsdk-base AS libwebp-builder
COPY --from=zlib-builder $INSTALL_DIR $INSTALL_DIR
ENV LIBWEBP_BRANCH=v1.3.2
ADD https://github.com/ffmpegwasm/libwebp.git#$LIBWEBP_BRANCH /src
COPY build/libwebp.sh /src/build.sh
RUN bash -x /src/build.sh
```
#### 2. Remove the COPY instruction
In the `ffmpeg-base` stage, remove the line that copies the built library:
```dockerfile
# Remove this line
COPY --from=libwebp-builder $INSTALL_DIR $INSTALL_DIR
```
#### 3. Remove the configure flag
In the `ffmpeg-builder` stage, remove the corresponding `--enable-lib...` flag:
```dockerfile
# Remove this line from the ffmpeg-builder stage
--enable-libwebp \
```
#### 4. Remove the linker flags
In the `ffmpeg-wasm-builder` stage, remove the library from `FFMPEG_LIBS`:
```dockerfile
# Remove these lines from FFMPEG_LIBS
-lwebpmux \
-lwebp \
-lsharpyuv \
```
> **💡 Pro Tip:** Start by removing just the main library flag (e.g., `-lwebp`). If the build fails with "undefined reference" errors, those errors will tell you exactly which additional libraries to remove.
#### 5. Build and test
```bash
# Run the build command
make prd
# Output will be in packages/core/dist/
```
---
**Additional Build Size Optimization:**
You can sometimes play around with `build/ffmpeg-wasm.sh` and `build/ffmpeg.sh` to disable things you are not using to make the size smaller.
### More Advance Customization Example: Creating a Minimal Build
For more advanced customization, you might want to create a minimal build that only includes the features you need. A good example is creating a build that can create a video from a sequence of images (e.g., from an HTML canvas), handle MP4 encoding/decoding, and support audio.
A community member, @Kaizodo, shared an approach that resulted in a build size of only 4.80MB. You can find the full details and a discussion in [GitHub Issue #866](https://github.com/ffmpegwasm/ffmpeg.wasm/issues/866).
The general strategy is to:
1. **Start with a minimal configuration:** Instead of removing libraries one by one, a more effective approach is to start with a minimal ffmpeg configuration. This can be achieved by using flags like `--disable-everything` in the ffmpeg configuration step within the `Dockerfile`.
2. **Enable specific components:** After disabling everything, you can selectively enable only the encoders, decoders, muxers, demuxers, and protocols you need for your specific use case. For example: `--enable-encoder=libx264`, `--enable-decoder=png`, `--enable-muxer=mp4`, etc.
3. **Include only necessary libraries:** Make sure your `Dockerfile` only builds and links the external libraries that correspond to the features you enabled (e.g., `libx264`). You can remove the build stages for any other libraries.
This approach gives you control over the build content and its final size.
We would like to thank @Kaizodo, @harkdawg and other community members for sharing their knowledge!
## Publish
Simply run `npm publish` under **packages/core** or **/packages/core-mt**.
================================================
FILE: apps/website/docs/contribution/ffmpeg.md
================================================
# @ffmpeg/ffmpeg
The source code of @ffmpeg/ffmpeg locates at **/packages/ffmpeg**.
## Development
```bash
$ npm run dev
```
## Build
Transpile Typescript to JavaScript.
```bash
$ npm run build
```
## Lint
```bash
$ npm run lint
```
## Publish
Simply run `npm publish` under **packages/ffmpeg**.
================================================
FILE: apps/website/docs/contribution/util.md
================================================
# @ffmpeg/util
The source code of @ffmpeg/util locates at **/packages/util**.
## Development
```bash
$ npm run dev
```
## Build
Transpile Typescript to JavaScript.
```bash
$ npm run build
```
## Lint
```bash
$ npm run lint
```
## Publish
Simply run `npm publish` under **packages/util**.
================================================
FILE: apps/website/docs/faq.md
================================================
# FAQ
### Why ffmpeg.wasm doesn't support nodejs?
ffmpeg.wasm did support nodejs before 0.12.0, but decided to discontinue nodejs support due to:
- It takes extra effort to maintain nodejs support
- If you are not in browser, there are a lot of better choices than using WebAssembly for a better performance, ex:
- nodejs: https://www.npmjs.com/package/fluent-ffmpeg
- react-native: https://github.com/arthenica/ffmpeg-kit
Of course, it is still highly welcome to contribute a nodejs version of ffmpeg.wasm.
### Why ffmpeg.wasm is so slow comparing to ffmpeg?
As of now, WebAssembly is still a lot slower than native, it is possible to further speed up using
WebAssembly intrinsic, which is basically writing assembly code. It is something we are investigating
and hope to introduce in the future.
If you are OK with more unstable version of ffmpeg.wasm, using ffmpeg.wasm multithread (mt) version
can have around 2x speed comparing to single thread (but consume a lot more memory and cpu)
### Is RTSP supported by ffmpeg.wasm?
We are trying to support, but so far WebAssembly itself lack of features like sockets which makes
it hard to implement RTSP protocol. Possible workarounds are still under investigation.
### What is the license of ffmpeg.wasm?
There are two components inside ffmpeg.wasm:
- @ffmpeg/ffmpeg (https://github.com/ffmpegwasm/ffmpeg.wasm/packages/ffmpeg)
- @ffmpeg/core (https://github.com/ffmpegwasm/ffmpeg.wasm/packages/core)
@ffmpeg/core contains WebAssembly code which is transpiled from original FFmpeg C code with minor modifications, but overall it still following the same licenses as FFmpeg and its external libraries (as each external libraries might have its own license).
@ffmpeg/ffmpeg contains kind of a wrapper to handle the complexity of loading core and calling low-level APIs. It is a small code base and under MIT license.
### What is the maximum size of input file?
2 GB, which is a hard limit in WebAssembly. Might become 4 GB in the future.
### How can I build my own ffmpeg.wasm?
In fact, it is `@ffmpeg/core` most people would like to build.
To build on your own, you can check [Contribution Guide](/docs/contribution/core)
Also you can check this series of posts to learn more fundamental concepts
(OUTDATED, but still good to learn foundations):
- https://jeromewu.github.io/build-ffmpeg-webassembly-version-part-1-preparation/
- https://jeromewu.github.io/build-ffmpeg-webassembly-version-part-2-compile-with-emscripten/
- https://jeromewu.github.io/build-ffmpeg-webassembly-version-part-3-v0.1/
- https://jeromewu.github.io/build-ffmpeg-webassembly-version-part-4-v0.2/
================================================
FILE: apps/website/docs/getting-started/examples.md
================================================
import Grid from '@mui/material/Unstable_Grid2';
import MuiThemeProvider from "@site/src/components/common/MuiThemeProvider";
import ExampleCard from "@site/src/components/common/ExampleCard";
# Examples
You can find how to use ffmpeg.wasm with frameworks here. :smile:
:::caution
Do remember to run `npm run build` in the root of the repository before trying
any of the examples.
:::
<MuiThemeProvider>
<Grid container rowSpacing={1} columnSpacing={1}>
<Grid xs={12} sm={6} md={6} lg={6} xl={4}>
<ExampleCard
img="/img/vanilla.png"
title="Vanilla JavaScript"
desc="Plain JavaScript"
url="https://github.com/ffmpegwasm/ffmpeg.wasm/tree/main/apps/vanilla-app"
/>
</Grid>
<Grid xs={12} sm={6} md={6} lg={6} xl={4}>
<ExampleCard
img="/img/react-vite.png"
title="React + Vite"
desc="React with Vite (multithread version)"
url="https://github.com/ffmpegwasm/ffmpeg.wasm/tree/main/apps/react-vite-app"
/>
</Grid>
<Grid xs={12} sm={6} md={6} lg={6} xl={4}>
<ExampleCard
img="/img/vue-vite.png"
title="Vue + Vite"
desc="Vue with Vite (multithread version)"
url="https://github.com/ffmpegwasm/ffmpeg.wasm/tree/main/apps/vue-vite-app"
/>
</Grid>
<Grid xs={12} sm={6} md={6} lg={6} xl={4}>
<ExampleCard
img="/img/angular.png"
title="Angular"
desc="Angular (multithread version)"
url="https://github.com/ffmpegwasm/ffmpeg.wasm/tree/main/apps/angular-app"
/>
</Grid>
<Grid xs={12} sm={6} md={6} lg={6} xl={4}>
<ExampleCard
img="/img/nextjs.png"
title="Next.js"
desc="Next.js (single thread version)"
url="https://github.com/ffmpegwasm/ffmpeg.wasm/tree/main/apps/nextjs-app"
/>
</Grid>
<Grid xs={12} sm={6} md={6} lg={6} xl={4}>
<ExampleCard
img="/img/sveltekit-vite.png"
title="SvelteKit + Vite"
desc="SvelteKit with Vite (multithread version)"
url="https://github.com/ffmpegwasm/ffmpeg.wasm/tree/main/apps/sveltekit-app"
/>
</Grid>
<Grid xs={12} sm={6} md={6} lg={6} xl={4}>
<ExampleCard
img="/img/solidstart-vite.png"
title="SolidStart + Vite"
desc="SolidStart with Vite (multithread version)"
url="https://github.com/ffmpegwasm/ffmpeg.wasm/tree/main/apps/solidstart-app"
/>
</Grid>
</Grid>
</MuiThemeProvider>
================================================
FILE: apps/website/docs/getting-started/installation.md
================================================
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';
# Installation
:::note
ffmpeg.wasm only supports running in browser, see [FAQ](/docs/faq) for more
details
:::
## Package Managers
Install ffmpeg.wasm using package managers like npm and yarn:
<Tabs>
<TabItem value="npm" label="npm" default>
```bash
npm install @ffmpeg/ffmpeg @ffmpeg/util
```
</TabItem>
<TabItem value="yarn" label="yarn">
```bash
yarn add @ffmpeg/ffmpeg @ffmpeg/util
```
</TabItem>
</Tabs>
:::info
As `@ffmpeg/ffmpeg` spawns a web worker, you cannot import `@ffmpeg/ffmpeg` from CDN like
jsdelivr. It is recommended to download it and host it on your server most of the time.
:::
================================================
FILE: apps/website/docs/getting-started/usage.md
================================================
# Usage
Learn the basics of using ffmpeg.wasm.
:::note
It is recommended to read [Overview](/docs/overview) first.
:::
## Transcode webm to mp4 video
:::caution
If you are a [vite](https://vitejs.dev/) user, use `esm` in **baseURL** instead of `umd`:
~~https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/umd~~ => https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/esm
:::
```jsx live
// import { FFmpeg } from '@ffmpeg/ffmpeg';
// import { fetchFile, toBlobURL } from '@ffmpeg/util';
function() {
const [loaded, setLoaded] = useState(false);
const ffmpegRef = useRef(new FFmpeg());
const videoRef = useRef(null);
const messageRef = useRef(null);
const load = async () => {
const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/umd'
const ffmpeg = ffmpegRef.current;
ffmpeg.on('log', ({ message }) => {
messageRef.current.innerHTML = message;
console.log(message);
});
// toBlobURL is used to bypass CORS issue, urls with the same
// domain can be used directly.
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
});
setLoaded(true);
}
const transcode = async () => {
const ffmpeg = ffmpegRef.current;
await ffmpeg.writeFile('input.webm', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm'));
await ffmpeg.exec(['-i', 'input.webm', 'output.mp4']);
const data = await ffmpeg.readFile('output.mp4');
videoRef.current.src =
URL.createObjectURL(new Blob([data.buffer], {type: 'video/mp4'}));
}
return (loaded
? (
<>
<video ref={videoRef} controls></video><br/>
<button onClick={transcode}>Transcode webm to mp4</button>
<p ref={messageRef}></p>
<p>Open Developer Tools (Ctrl+Shift+I) to View Logs</p>
</>
)
: (
<button onClick={load}>Load ffmpeg-core (~31 MB)</button>
)
);
}
```
## Transcode webm to mp4 video (multi-thread)
:::caution
As SharedArrayBuffer is required for multithread version, make sure
you have have fulfilled [Security Requirements](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/SharedArrayBuffer#security_requirements).
:::
```jsx live
// import { FFmpeg } from '@ffmpeg/ffmpeg';
// import { fetchFile, toBlobURL } from '@ffmpeg/util';
function() {
const [loaded, setLoaded] = useState(false);
const ffmpegRef = useRef(new FFmpeg());
const videoRef = useRef(null);
const messageRef = useRef(null);
const load = async () => {
const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@0.12.10/dist/umd'
const ffmpeg = ffmpegRef.current;
ffmpeg.on('log', ({ message }) => {
messageRef.current.innerHTML = message;
console.log(message);
});
// toBlobURL is used to bypass CORS issue, urls with the same
// domain can be used directly.
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
workerURL: await toBlobURL(`${baseURL}/ffmpeg-core.worker.js`, 'text/javascript'),
});
setLoaded(true);
}
const transcode = async () => {
const ffmpeg = ffmpegRef.current;
await ffmpeg.writeFile('input.webm', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm'));
await ffmpeg.exec(['-i', 'input.webm', 'output.mp4']);
const data = await ffmpeg.readFile('output.mp4');
videoRef.current.src =
URL.createObjectURL(new Blob([data.buffer], {type: 'video/mp4'}));
}
return (loaded
? (
<>
<video ref={videoRef} controls></video><br/>
<button onClick={transcode}>Transcode webm to mp4</button>
<p ref={messageRef}></p>
<p>Open Developer Tools (Ctrl+Shift+I) to View Logs</p>
</>
)
: (
<button onClick={load}>Load ffmpeg-core (~31 MB)</button>
)
);
}
```
## Transcode video with timeout
```jsx live
// import { FFmpeg } from '@ffmpeg/ffmpeg';
// import { fetchFile } from '@ffmpeg/util';
function() {
const [loaded, setLoaded] = useState(false);
const ffmpegRef = useRef(new FFmpeg());
const videoRef = useRef(null);
const messageRef = useRef(null);
const load = async () => {
const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/umd'
const ffmpeg = ffmpegRef.current;
ffmpeg.on('log', ({ message }) => {
messageRef.current.innerHTML = message;
console.log(message);
});
// toBlobURL is used to bypass CORS issue, urls with the same
// domain can be used directly.
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
});
setLoaded(true);
}
const transcode = async () => {
const ffmpeg = ffmpegRef.current;
await ffmpeg.writeFile('input.webm', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm'));
// The exec should stop after 1 second.
await ffmpeg.exec(['-i', 'input.webm', 'output.mp4'], 1000);
const data = await ffmpeg.readFile('output.mp4');
videoRef.current.src =
URL.createObjectURL(new Blob([data.buffer], {type: 'video/mp4'}));
}
return (loaded
? (
<>
<video ref={videoRef} controls></video><br/>
<button onClick={transcode}>Transcode webm to mp4</button>
<p ref={messageRef}></p>
<p>Open Developer Tools (Ctrl+Shift+I) to View Logs</p>
</>
)
: (
<button onClick={load}>Load ffmpeg-core (~31 MB)</button>
)
);
}
```
## Transcode video with progress (experimental)
:::danger
`progress` is an experimental feature and might not work for many cases
(ex. concat video files, convert image files, ...). Please use with caution.
:::
```jsx live
// import { FFmpeg } from '@ffmpeg/ffmpeg';
// import { fetchFile } from '@ffmpeg/util';
function() {
const [loaded, setLoaded] = useState(false);
const ffmpegRef = useRef(new FFmpeg());
const videoRef = useRef(null);
const messageRef = useRef(null);
const load = async () => {
const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/umd'
const ffmpeg = ffmpegRef.current;
// Listen to progress event instead of log.
ffmpeg.on('progress', ({ progress, time }) => {
messageRef.current.innerHTML = `${progress * 100} % (transcoded time: ${time / 1000000} s)`;
});
// toBlobURL is used to bypass CORS issue, urls with the same
// domain can be used directly.
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
});
setLoaded(true);
}
const transcode = async () => {
const ffmpeg = ffmpegRef.current;
await ffmpeg.writeFile('input.webm', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm'));
await ffmpeg.exec(['-i', 'input.webm', 'output.mp4']);
const data = await ffmpeg.readFile('output.mp4');
videoRef.current.src =
URL.createObjectURL(new Blob([data.buffer], {type: 'video/mp4'}));
}
return (loaded
? (
<>
<video ref={videoRef} controls></video><br/>
<button onClick={transcode}>Transcode webm to mp4</button>
<p ref={messageRef}></p>
</>
)
: (
<button onClick={load}>Load ffmpeg-core (~31 MB)</button>
)
);
}
```
## Split video into segments of equal duration
```jsx live
// import { FFmpeg } from '@ffmpeg/ffmpeg';
// import { fetchFile } from '@ffmpeg/util';
function() {
const [loaded, setLoaded] = useState(false);
const ffmpegRef = useRef(new FFmpeg());
const videoRef = useRef(null);
const messageRef = useRef(null);
const load = async () => {
const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/umd'
const ffmpeg = ffmpegRef.current;
ffmpeg.on('log', ({ message }) => {
messageRef.current.innerHTML = message;
console.log(message);
});
// toBlobURL is used to bypass CORS issue, urls with the same
// domain can be used directly.
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
});
setLoaded(true);
}
const transcode = async () => {
const ffmpeg = ffmpegRef.current;
await ffmpeg.writeFile('input.webm', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm'));
await ffmpeg.exec([
'-i',
'input.webm',
'-f',
'segment',
'-segment_time',
'3',
'-g',
'9',
'-sc_threshold',
'0',
'-force_key_frames',
'expr:gte(t,n_forced*9)',
'-reset_timestamps',
'1',
'-map',
'0',
'output_%d.mp4'
]);
const data = await ffmpeg.readFile('output_1.mp4');
videoRef.current.src =
URL.createObjectURL(new Blob([data.buffer], {type: 'video/mp4'}));
}
return (loaded
? (
<>
<video ref={videoRef} controls></video><br/>
<button onClick={transcode}>Split video to segments of 3 sec. and plays 2nd segment</button>
<p ref={messageRef}></p>
<p>Open Developer Tools (Ctrl+Shift+I) to View Logs</p>
</>
)
: (
<button onClick={load}>Load ffmpeg-core (~31 MB)</button>
)
);
}
```
## Display Text on the video
```jsx live
// import { FFmpeg } from '@ffmpeg/ffmpeg';
// import { fetchFile } from '@ffmpeg/util';
function() {
const [loaded, setLoaded] = useState(false);
const ffmpegRef = useRef(new FFmpeg());
const videoRef = useRef(null);
const messageRef = useRef(null);
const load = async () => {
const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/umd'
const ffmpeg = ffmpegRef.current;
ffmpeg.on('log', ({ message }) => {
messageRef.current.innerHTML = message;
console.log(message);
});
// toBlobURL is used to bypass CORS issue, urls with the same
// domain can be used directly.
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
});
setLoaded(true);
}
const transcode = async () => {
const ffmpeg = ffmpegRef.current;
await ffmpeg.writeFile('input.webm', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm'));
await ffmpeg.writeFile('arial.ttf', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/arial.ttf'));
await ffmpeg.exec([
'-i',
'input.webm',
'-vf',
'drawtext=fontfile=/arial.ttf:text=\'ffmpeg.wasm\':x=10:y=10:fontsize=24:fontcolor=white',
'output.mp4',
]);
const data = await ffmpeg.readFile('output.mp4');
videoRef.current.src =
URL.createObjectURL(new Blob([data.buffer], {type: 'video/mp4'}));
}
return (loaded
? (
<>
<video ref={videoRef} controls></video><br/>
<button onClick={transcode}>Transcode webm to mp4 with text</button>
<p ref={messageRef}></p>
<p>Open Developer Tools (Ctrl+Shift+I) to View Logs</p>
</>
)
: (
<button onClick={load}>Load ffmpeg-core (~31 MB)</button>
)
);
}
```
## Interlace 2 Videos
```jsx live
// import { FFmpeg } from '@ffmpeg/ffmpeg';
// import { fetchFile } from '@ffmpeg/util';
function() {
const [loaded, setLoaded] = useState(false);
const ffmpegRef = useRef(new FFmpeg());
const videoRef = useRef(null);
const messageRef = useRef(null);
const load = async () => {
const baseURL = 'https://cdn.jsdelivr.net/npm/@ffmpeg/core@0.12.10/dist/umd'
const ffmpeg = ffmpegRef.current;
ffmpeg.on('log', ({ message }) => {
messageRef.current.innerHTML = message;
console.log(message);
});
// toBlobURL is used to bypass CORS issue, urls with the same
// domain can be used directly.
await ffmpeg.load({
coreURL: await toBlobURL(`${baseURL}/ffmpeg-core.js`, 'text/javascript'),
wasmURL: await toBlobURL(`${baseURL}/ffmpeg-core.wasm`, 'application/wasm'),
});
setLoaded(true);
}
const transcode = async () => {
const ffmpeg = ffmpegRef.current;
await ffmpeg.writeFile('input.webm', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s.webm'));
await ffmpeg.writeFile('reversed.webm', await fetchFile('https://raw.githubusercontent.com/ffmpegwasm/testdata/master/Big_Buck_Bunny_180_10s_reversed.webm'));
await ffmpeg.exec([
'-i',
'input.webm',
'-i',
'reversed.webm',
'-filter_complex',
'[0:v][1:v]blend=all_expr=\'A*(if(eq(0,N/2),1,T))+B*(if(eq(0,N/2),T,1))\'',
'output.mp4',
]);
const data = await ffmpeg.readFile('output.mp4');
videoRef.current.src =
URL.createObjectURL(new Blob([data.buffer], {type: 'video/mp4'}));
}
return (loaded
? (
<>
<video ref={videoRef} controls></video><br/>
<button onClick={transcode}>Interlace two webm video to mp4</button>
<p ref={messageRef}></p>
<p>Open Developer Tools (Ctrl+Shift+I) to View Logs</p>
</>
)
: (
<button onClick={load}>Load ffmpeg-core (~31 MB)</button>
)
);
}
```
## Use WORKERFS
:::note
Required:
- @ffmpeg/ffmpeg@0.12.10+
- @ffmpeg/core@0.12.4+
:::
Please Check this PR: [Add WORKERFS support](https://github.com/ffmpegwasm/ffmpeg.wasm/pull/581)
## Abort exec() with signal
:::note
Required:
- @ffmpeg/ffmpeg@0.12.10+
- @ffmpeg/core@0.12.4+
:::
Please check this PR: [abort signal](https://github.com/ffmpegwasm/ffmpeg.wasm/pull/573)
================================================
FILE: apps/website/docs/migration.md
================================================
import MuiThemeProvider from "@site/src/components/common/MuiThemeProvider";
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';
# Migrating from 0.11.x to 0.12+
As 0.12+ is not backward compatible with 0.11.x, below is a quick mapping
table to transform 0.11.x to 0.12+
<MuiThemeProvider>
<TableContainer>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell align="center">0.11.x</TableCell>
<TableCell align="center">0.12+</TableCell>
<TableCell align="center">Note</TableCell>
</TableRow>
</TableHead>
<TableBody>
{[
{"0.11.x": "import { createFFmpeg } from '@ffmpeg/ffmpeg'", "0.12+": "import { FFmpeg } from '@ffmpeg/ffmpeg'", note: ""},
{"0.11.x": "createFFmpeg()", "0.12+": "new FFmpeg()", note: "argumens of createFFmpeg() is moved to ffmpeg.load()"},
{"0.11.x": "await ffmpeg.load()", "0.12+": "await ffmpeg.load()", note: ""},
{"0.11.x": "await ffmpeg.run(...args)", "0.12+": "await ffmpeg.exec([...args])", note: ""},
{"0.11.x": "ffmpeg.FS.writeFile()", "0.12+": "await ffmpeg.writeFile()", note: ""},
{"0.11.x": "ffmpeg.FS.readFile()", "0.12+": "await ffmpeg.readFile()", note: ""},
{"0.11.x": "ffmpeg.exit()", "0.12+": "ffmpeg.terminate()", note: ""},
{"0.11.x": "ffmpeg.setLogger()", "0.12+": "ffmpeg.on(\"log\", () => {})", note: ""},
{"0.11.x": "ffmpeg.setProgress()", "0.12+": "ffmpeg.on(\"progress\", () => {})", note: ""},
{"0.11.x": "import { fetchFile } from '@ffmpeg/ffmpeg'", "0.12+": "import { fetchFile } from '@ffmpeg/util'", note: ""},
].map((row) => (
<TableRow
key={row['0.11.x']}
>
<TableCell component="th" scope="row">
{row['0.11.x']}
</TableCell>
<TableCell align="left">{row['0.12+']}</TableCell>
<TableCell align="left">{row.note}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</MuiThemeProvider>
================================================
FILE: apps/website/docs/overview.md
================================================
import MuiThemeProvider from "@site/src/components/common/MuiThemeProvider";
import Table from '@mui/material/Table';
import TableBody from '@mui/material/TableBody';
import TableCell from '@mui/material/TableCell';
import TableContainer from '@mui/material/TableContainer';
import TableHead from '@mui/material/TableHead';
import TableRow from '@mui/material/TableRow';
import Paper from '@mui/material/Paper';
# Overview
:::info
For 0.11.x, visit [https://ffmpegwasm-0-11-x.netlify.app](https://ffmpegwasm-0-11-x.netlify.app)
and [0.11.x](https://github.com/ffmpegwasm/ffmpeg.wasm/tree/0.11.x) branch.
:::
## Introduction
ffmpeg.wasm is a pure WebAssembly / JavaScript port of [FFmpeg](https://www.ffmpeg.org/)
enabling video & audio record, convert and stream right inside browsers.
We leverage
[Emscripten](https://emscripten.org/) to transpile FFmpeg source code and many
libraries to WebAssembly and develop a minimal but essential library to free
developers from common requirements like running ffmpeg inside web worker and
more.
## Advantages
- **Security**: your users' data only lives inside their browser, no need to
worry about any data leakage or network latency.
- **Client-side computing**: instead of hosting a cluster of server-end servers,
you can now offload multimedia processing to client-side.
- **Flexible**: ffmpeg.wasm comes with single-thread and multi-thread cores, you
can use whichever fits your use case.
## Architecture

Multimedia transcoding is a resource-intensive task that you don't want to
execute in main thread, thus in ffmpeg.wasm we offload those task to web worker
(`ffmpeg.worker`) by default. This makes almost all function calls in ffmpeg.wasm
are asynchronous and it is recommended to use **async** / **await** syntax.
`ffmpeg.worker` downloads WebAssembly code (`ffmpeg-core`) from CDN
and initialized it in WorkerGlobalScope. For any input video file you would like
to process, you need to first populated them inside ffmpeg-core File System and
also read result from `ffmpeg-core` File System once it is done.
If you are using a multi-thread version of `ffmpeg-core`, more web workers will
be spawned by `ffmpeg-core` inside `ffmpeg.worker`
:::info
The concept of `core` in ffmpeg.wasm is like the engine of a car, it is not only
the most important part of ffmpeg.wasm but also a swappable component. Currently
we maintain single-thread (`@ffmpeg/core`) and multi-thread version
(`@ffmpeg/core-mt`) cores, you can build your own core (ex. a core with x264
lib only to minimize ffmpeg-core.wasm file size) using build scripts in the repository.
:::
## Packages
All ffmpeg.wasm packages are under [@ffmpeg](https://www.npmjs.com/search?q=%40ffmpeg)
name space:
| Name | Usage |
| ---- | ----- |
| @ffmpeg/ffmpeg | ffmpeg.wasm main package |
| @ffmpeg/util | common utility functions |
| @ffmpeg/types | TypeScript types |
| @ffmpeg/core | single-thread ffmpeg.wasm core |
| @ffmpeg/core-mt | multi-thread ffmpeg.wasm core |
## Libraries
ffmpeg.wasm is built with toolchains / libraries:
<MuiThemeProvider>
<TableContainer>
<Table sx={{ minWidth: 650 }} aria-label="simple table">
<TableHead>
<TableRow>
<TableCell align="center">Name</TableCell>
<TableCell align="center">Version</TableCell>
<TableCell align="center">Note</TableCell>
</TableRow>
</TableHead>
<TableBody>
{[
{name: "Emscripten", version: "3.1.40", note: "Emscripten is a toolchain for compiling C and C++ code into WebAssembly and JavaScript, making it possible to run applications written in these languages in web browsers."},
{name: "FFmpeg", version: "n5.1.4", note: "FFmpeg is a powerful multimedia framework that can decode, encode, transcode, and stream audio and video files. It's widely used for media manipulation and streaming."},
{name: "x264", version: "0.164.x", note: "x264 is a popular video encoding library that provides high-quality H.264 video compression. It's commonly used for video encoding and transcoding."},
{name: "x265", version: "3.4", note: "x265 is a video encoding library that specializes in encoding videos using the H.265/HEVC codec, offering high compression efficiency for video content."},
{name: "libvpx", version: "v1.13.1", note: "libvpx is an open-source video codec library used for encoding and decoding VP8 and VP9 video formats, commonly used for web-based video streaming."},
{name: "lame", version: "3.100", note: "LAME is an audio encoder that converts audio files to the MP3 format, making it widely used for creating MP3 audio files."},
{name: "ogg", version: "v1.3.4", note: "Ogg is a multimedia container format, and this library provides support for encoding and decoding audio and video in the Ogg format."},
{name: "theora", version: "v1.1.1", note: "Theora is an open video codec designed for efficient video compression within the Ogg multimedia framework."},
{name: "opus", version: "v1.3.1", note: "Opus is a versatile audio codec capable of handling both voice and music with low latency and high-quality compression."},
{name: "vorbis", version: "v1.3.3", note: "Vorbis is an open-source audio codec known for its high audio quality and efficient compression. It's often used for audio streaming."},
{name: "zlib", version: "v1.2.11", note: "zlib is a compression library that provides data compression and decompression functionality, commonly used in file compression formats like gzip."},
{name: "libwebp", version: "v1.3.2", note: "libwebp is a library for working with the WebP image format, offering efficient image compression for web use"},
{name: "freetype2", version: "v2.10.4", note: "FreeType 2 is a library for rendering fonts. It is commonly used for text rendering in applications and systems."},
{name: "fribidi", version: "v1.0.9", note: "FriBidi is a library for handling bidirectional text (text containing both left-to-right and right-to-left scripts) and is often used in text layout and rendering."},
{name: "harfbuzz", version: "5.2.0", note: "HarfBuzz is a text shaping engine that allows complex script text to be rendered correctly. It's used in conjunction with font rendering libraries."},
{name: "libass", version: "0.15.0", note: "libass is a library for rendering and formatting subtitles in multimedia applications, making it essential for displaying subtitles alongside video content."},
{name: "zimg", version: "3.0.5", note: "zimg implements the commonly required image processing basics of scaling, colorspace conversion, and depth conversion."}
].map((row) => (
<TableRow
key={row.name}
>
<TableCell component="th" scope="row">
{row.name}
</TableCell>
<TableCell align="left">{row.version}</TableCell>
<TableCell align="left">{row.note}</TableCell>
</TableRow>
))}
</TableBody>
</Table>
</TableContainer>
</MuiThemeProvider>
================================================
FILE: apps/website/docs/performance.md
================================================
# Performance
ffmpeg.wasm uses transpiled FFmpeg C source code to WebAssembly code, it is for
certain that ffmpeg.wasm won't perform as good as FFmpeg as it is not fully
optimized at the moment. (Even in ffmpeg.wasm multithread version). In this
section we provide a short comparison, so that you can make decision based on your
needs:
## Environment
- CPU: 8 × 11th Gen Intel® Core™ i5-1135G7 @ 2.40GHz
- Memory: 15.6 GiB of RAM
- OS: Manjaro Linux 6.1.44-1-MANJARO (64-bit)
- Browser: Google Chrome Version 116.0.5845.96 (Official Build) (64-bit)
- FFmpeg: n5.1.2
## Comparison
Setup:
- Each command is executed 5 times.
- Only `ffmpeg.exec()` time is measured.
- Candidates
- FFmpeg: [native FFmpeg](https://hub.docker.com/r/linuxserver/ffmpeg),
considered as baseline.
- core: ffmpeg.wasm single thread version.
- core-mt: ffmpeg.wasm multi thread version.
### $ ffmpeg -i [input.webm](https://test-videos.co.uk/vids/bigbuckbunny/webm/vp8/720/Big_Buck_Bunny_720_10s_1MB.webm) output.mp4
| # | FFmpeg | core v0.12.3 | core-mt v0.12.3 |
| --- | ------ | ------------ | --------------- |
| Avg | 5.2 sec | 128.8 sec (0.04x) | 60.4 sec (0.08x) |
| Max | 5.3 sec | 130.7 sec | 63.9 sec |
| Min | 5.1 sec | 126.6 sec | 59 sec |
================================================
FILE: apps/website/docs/privacy-policy.md
================================================
# Privacy Policy
<p>Last updated: August 05, 2023</p>
<p>This Privacy Policy describes Our policies and procedures on the collection, use and disclosure of Your information when You use the Service and tells You about Your privacy rights and how the law protects You.</p>
<p>We use Your Personal data to provide and improve the Service. By using the Service, You agree to the collection and use of information in accordance with this Privacy Policy. This Privacy Policy has been created with the help of the <a href="https://www.freeprivacypolicy.com/free-privacy-policy-generator/" target="_blank">Free Privacy Policy Generator</a>.</p>
<h1>Interpretation and Definitions</h1>
<h2>Interpretation</h2>
<p>The words of which the initial letter is capitalized have meanings defined under the following conditions. The following definitions shall have the same meaning regardless of whether they appear in singular or in plural.</p>
<h2>Definitions</h2>
<p>For the purposes of this Privacy Policy:</p>
<ul>
<li>
<p><strong>Account</strong> means a unique account created for You to access our Service or parts of our Service.</p>
</li>
<li>
<p><strong>Affiliate</strong> means an entity that controls, is controlled by or is under common control with a party, where "control" means ownership of 50% or more of the shares, equity interest or other securities entitled to vote for election of directors or other managing authority.</p>
</li>
<li>
<p><strong>Company</strong> (referred to as either "the Company", "We", "Us" or "Our" in this Agreement) refers to ffmpeg.wasm.</p>
</li>
<li>
<p><strong>Cookies</strong> are small files that are placed on Your computer, mobile device or any other device by a website, containing the details of Your browsing history on that website among its many uses.</p>
</li>
<li>
<p><strong>Country</strong> refers to: Singapore</p>
</li>
<li>
<p><strong>Device</strong> means any device that can access the Service such as a computer, a cellphone or a digital tablet.</p>
</li>
<li>
<p><strong>Personal Data</strong> is any information that relates to an identified or identifiable individual.</p>
</li>
<li>
<p><strong>Service</strong> refers to the Website.</p>
</li>
<li>
<p><strong>Service Provider</strong> means any natural or legal person who processes the data on behalf of the Company. It refers to third-party companies or individuals employed by the Company to facilitate the Service, to provide the Service on behalf of the Company, to perform services related to the Service or to assist the Company in analyzing how the Service is used.</p>
</li>
<li>
<p><strong>Usage Data</strong> refers to data collected automatically, either generated by the use of the Service or from the Service infrastructure itself (for example, the duration of a page visit).</p>
</li>
<li>
<p><strong>Website</strong> refers to ffmpeg.wasm, accessible from <a href="https://ffmpegwasm.netlify.app/" rel="external nofollow noopener" target="_blank">https://ffmpegwasm.netlify.app/</a></p>
</li>
<li>
<p><strong>You</strong> means the individual accessing or using the Service, or the company, or other legal entity on behalf of which such individual is accessing or using the Service, as applicable.</p>
</li>
</ul>
<h1>Collecting and Using Your Personal Data</h1>
<h2>Types of Data Collected</h2>
<h3>Personal Data</h3>
<p>While using Our Service, We may ask You to provide Us with certain personally identifiable information that can be used to contact or identify You. Personally identifiable information may include, but is not limited to:</p>
<ul>
<li>Usage Data</li>
</ul>
<h3>Usage Data</h3>
<p>Usage Data is collected automatically when using the Service.</p>
<p>Usage Data may include information such as Your Device's Internet Protocol address (e.g. IP address), browser type, browser version, the pages of our Service that You visit, the time and date of Your visit, the time spent on those pages, unique device identifiers and other diagnostic data.</p>
<p>When You access the Service by or through a mobile device, We may collect certain information automatically, including, but not limited to, the type of mobile device You use, Your mobile device unique ID, the IP address of Your mobile device, Your mobile operating system, the type of mobile Internet browser You use, unique device identifiers and other diagnostic data.</p>
<p>We may also collect information that Your browser sends whenever You visit our Service or when You access the Service by or through a mobile device.</p>
<h3>Tracking Technologies and Cookies</h3>
<p>We use Cookies and similar tracking technologies to track the activity on Our Service and store certain information. Tracking technologies used are beacons, tags, and scripts to collect and track information and to improve and analyze Our Service. The technologies We use may include:</p>
<ul>
<li><strong>Cookies or Browser Cookies.</strong> A cookie is a small file placed on Your Device. You can instruct Your browser to refuse all Cookies or to indicate when a Cookie is being sent. However, if You do not accept Cookies, You may not be able to use some parts of our Service. Unless you have adjusted Your browser setting so that it will refuse Cookies, our Service may use Cookies.</li>
<li><strong>Web Beacons.</strong> Certain sections of our Service and our emails may contain small electronic files known as web beacons (also referred to as clear gifs, pixel tags, and single-pixel gifs) that permit the Company, for example, to count users who have visited those pages or opened an email and for other related website statistics (for example, recording the popularity of a certain section and verifying system and server integrity).</li>
</ul>
<p>Cookies can be "Persistent" or "Session" Cookies. Persistent Cookies remain on Your personal computer or mobile device when You go offline, while Session Cookies are deleted as soon as You close Your web browser. Learn more about cookies on the <a href="https://www.freeprivacypolicy.com/blog/sample-privacy-policy-template/#Use_Of_Cookies_And_Tracking" target="_blank">Free Privacy Policy website</a> article.</p>
<p>We use both Session and Persistent Cookies for the purposes set out below:</p>
<ul>
<li>
<p><strong>Necessary / Essential Cookies</strong></p>
<p>Type: Session Cookies</p>
<p>Administered by: Us</p>
<p>Purpose: These Cookies are essential to provide You with services available through the Website and to enable You to use some of its features. They help to authenticate users and prevent fraudulent use of user accounts. Without these Cookies, the services that You have asked for cannot be provided, and We only use these Cookies to provide You with those services.</p>
</li>
<li>
<p><strong>Cookies Policy / Notice Acceptance Cookies</strong></p>
<p>Type: Persistent Cookies</p>
<p>Administered by: Us</p>
<p>Purpose: These Cookies identify if users have accepted the use of cookies on the Website.</p>
</li>
<li>
<p><strong>Functionality Cookies</strong></p>
<p>Type: Persistent Cookies</p>
<p>Administered by: Us</p>
<p>Purpose: These Cookies allow us to remember choices You make when You use the Website, such as remembering your login details or language preference. The purpose of these Cookies is to provide You with a more personal experience and to avoid You having to re-enter your preferences every time You use the Website.</p>
</li>
</ul>
<p>For more information about the cookies we use and your choices regarding cookies, please visit our Cookies Policy or the Cookies section of our Privacy Policy.</p>
<h2>Use of Your Personal Data</h2>
<p>The Company may use Personal Data for the following purposes:</p>
<ul>
<li>
<p><strong>To provide and maintain our Service</strong>, including to monitor the usage of our Service.</p>
</li>
<li>
<p><strong>To manage Your Account:</strong> to manage Your registration as a user of the Service. The Personal Data You provide can give You access to different functionalities of the Service that are available to You as a registered user.</p>
</li>
<li>
<p><strong>For the performance of a contract:</strong> the development, compliance and undertaking of the purchase contract for the products, items or services You have purchased or of any other contract with Us through the Service.</p>
</li>
<li>
<p><strong>To contact You:</strong> To contact You by email, telephone calls, SMS, or other equivalent forms of electronic communication, such as a mobile application's push notifications regarding updates or informative communications related to the functionalities, products or contracted services, including the security updates, when necessary or reasonable for their implementation.</p>
</li>
<li>
<p><strong>To provide You</strong> with news, special offers and general information about other goods, services and events which we offer that are similar to those that you have already purchased or enquired about unless You have opted not to receive such information.</p>
</li>
<li>
<p><strong>To manage Your requests:</strong> To attend and manage Your requests to Us.</p>
</li>
<li>
<p><strong>For business transfers:</strong> We may use Your information to evaluate or conduct a merger, divestiture, restructuring, reorganization, dissolution, or other sale or transfer of some or all of Our assets, whether as a going concern or as part of bankruptcy, liquidation, or similar proceeding, in which Personal Data held by Us about our Service users is among the assets transferred.</p>
</li>
<li>
<p><strong>For other purposes</strong>: We may use Your information for other purposes, such as data analysis, identifying usage trends, determining the effectiveness of our promotional campaigns and to evaluate and improve our Service, products, services, marketing and your experience.</p>
</li>
</ul>
<p>We may share Your personal information in the following situations:</p>
<ul>
<li><strong>With Service Providers:</strong> We may share Your personal information with Service Providers to monitor and analyze the use of our Service, to contact You.</li>
<li><strong>For business transfers:</strong> We may share or transfer Your personal information in connection with, or during negotiations of, any merger, sale of Company assets, financing, or acquisition of all or a portion of Our business to another company.</li>
<li><strong>With Affiliates:</strong> We may share Your information with Our affiliates, in which case we will require those affiliates to honor this Privacy Policy. Affiliates include Our parent company and any other subsidiaries, joint venture partners or other companies that We control or that are under common control with Us.</li>
<li><strong>With business partners:</strong> We may share Your information with Our business partners to offer You certain products, services or promotions.</li>
<li><strong>With other users:</strong> when You share personal information or otherwise interact in the public areas with other users, such information may be viewed by all users and may be publicly distributed outside.</li>
<li><strong>With Your consent</strong>: We may disclose Your personal information for any other purpose with Your consent.</li>
</ul>
<h2>Retention of Your Personal Data</h2>
<p>The Company will retain Your Personal Data only for as long as is necessary for the purposes set out in this Privacy Policy. We will retain and use Your Personal Data to the extent necessary to comply with our legal obligations (for example, if we are required to retain your data to comply with applicable laws), resolve disputes, and enforce our legal agreements and policies.</p>
<p>The Company will also retain Usage Data for internal analysis purposes. Usage Data is generally retained for a shorter period of time, except when this data is used to strengthen the security or to improve the functionality of Our Service, or We are legally obligated to retain this data for longer time periods.</p>
<h2>Transfer of Your Personal Data</h2>
<p>Your information, including Personal Data, is processed at the Company's operating offices and in any other places where the parties involved in the processing are located. It means that this information may be transferred to — and maintained on — computers located outside of Your state, province, country or other governmental jurisdiction where the data protection laws may differ than those from Your jurisdiction.</p>
<p>Your consent to this Privacy Policy followed by Your submission of such information represents Your agreement to that transfer.</p>
<p>The Company will take all steps reasonably necessary to ensure that Your data is treated securely and in accordance with this Privacy Policy and no transfer of Your Personal Data will take place to an organization or a country unless there are adequate controls in place including the security of Your data and other personal information.</p>
<h2>Delete Your Personal Data</h2>
<p>You have the right to delete or request that We assist in deleting the Personal Data that We have collected about You.</p>
<p>Our Service may give You the ability to delete certain information about You from within the Service.</p>
<p>You may update, amend, or delete Your information at any time by signing in to Your Account, if you have one, and visiting the account settings section that allows you to manage Your personal information. You may also contact Us to request access to, correct, or delete any personal information that You have provided to Us.</p>
<p>Please note, however, that We may need to retain certain information when we have a legal obligation or lawful basis to do so.</p>
<h2>Disclosure of Your Personal Data</h2>
<h3>Business Transactions</h3>
<p>If the Company is involved in a merger, acquisition or asset sale, Your Personal Data may be transferred. We will provide notice before Your Personal Data is transferred and becomes subject to a different Privacy Policy.</p>
<h3>Law enforcement</h3>
<p>Under certain circumstances, the Company may be required to disclose Your Personal Data if required to do so by law or in response to valid requests by public authorities (e.g. a court or a government agency).</p>
<h3>Other legal requirements</h3>
<p>The Company may disclose Your Personal Data in the good faith belief that such action is necessary to:</p>
<ul>
<li>Comply with a legal obligation</li>
<li>Protect and defend the rights or property of the Company</li>
<li>Prevent or investigate possible wrongdoing in connection with the Service</li>
<li>Protect the personal safety of Users of the Service or the public</li>
<li>Protect against legal liability</li>
</ul>
<h2>Security of Your Personal Data</h2>
<p>The security of Your Personal Data is important to Us, but remember that no method of transmission over the Internet, or method of electronic storage is 100% secure. While We strive to use commercially acceptable means to protect Your Personal Data, We cannot guarantee its absolute security.</p>
<h1>Children's Privacy</h1>
<p>Our Service does not address anyone under the age of 13. We do not knowingly collect personally identifiable information from anyone under the age of 13. If You are a parent or guardian and You are aware that Your child has provided Us with Personal Data, please contact Us. If We become aware that We have collected Personal Data from anyone under the age of 13 without verification of parental consent, We take steps to remove that information from Our servers.</p>
<p>If We need to rely on consent as a legal basis for processing Your information and Your country requires consent from a parent, We may require Your parent's consent before We collect and use that information.</p>
<h1>Links to Other Websites</h1>
<p>Our Service may contain links to other websites that are not operated by Us. If You click on a third party link, You will be directed to that third party's site. We strongly advise You to review the Privacy Policy of every site You visit.</p>
<p>We have no control over and assume no responsibility for the content, privacy policies or practices of any third party sites or services.</p>
<h1>Changes to this Privacy Policy</h1>
<p>We may update Our Privacy Policy from time to time. We will notify You of any changes by posting the new Privacy Policy on this page.</p>
<p>We will let You know via email and/or a prominent notice on Our Service, prior to the change becoming effective and update the "Last updated" date at the top of this Privacy Policy.</p>
<p>You are advised to review this Privacy Policy periodically for any changes. Changes to this Privacy Policy are effective when they are posted on this page.</p>
<h1>Contact Us</h1>
<p>If you have any questions about this Privacy Policy, You can contact us:</p>
<ul>
<li>By email: jeromewus@gmail.com</li>
</ul>
================================================
FILE: apps/website/docusaurus.config.js
================================================
// @ts-check
// Note: type annotations allow type checking and IDEs autocompletion
const lightCodeTheme = require("prism-react-renderer/themes/github");
const darkCodeTheme = require("prism-react-renderer/themes/dracula");
/** @type {import('@docusaurus/types').Config} */
const config = {
title: "ffmpeg.wasm",
tagline:
"ffmpeg.wasm is a pure WebAssembly / JavaScript port of FFmpeg enabling video & audio record, convert and stream right inside browsers!",
url: "https://ffmpegwasm.netlify.app",
baseUrl: "/",
onBrokenLinks: "throw",
onBrokenMarkdownLinks: "warn",
favicon: "img/favicon.ico",
// GitHub pages deployment config.
// If you aren't using GitHub pages, you don't need these.
organizationName: "ffmpegwasm", // Usually your GitHub org/user name.
projectName: "ffmpeg.wasm", // Usually your repo name.
// Even if you don't use internalization, you can use this field to set useful
// metadata like html lang. For example, if your site is Chinese, you may want
// to replace "en" with "zh-Hans".
i18n: {
defaultLocale: "en",
locales: ["en"],
},
presets: [
[
"classic",
/** @type {import('@docusaurus/preset-classic').Options} */
({
docs: {
sidebarPath: require.resolve("./sidebars.js"),
// Please change this to your repo.
// Remove this to remove the "edit this page" links.
editUrl:
"https://github.com/ffmpegwasm/ffmpeg.wasm/tree/main/apps/website",
},
blog: {
showReadingTime: true,
// Please change this to your repo.
// Remove this to remove the "edit this page" links.
editUrl:
"https://github.com/ffmpegwasm/ffmpeg.wasm/tree/main/apps/website",
},
theme: {
customCss: [
require.resolve("./src/css/custom.css"),
require.resolve("@fontsource/roboto/300.css"),
require.resolve("@fontsource/roboto/400.css"),
require.resolve("@fontsource/roboto/500.css"),
require.resolve("@fontsource/roboto/700.css"),
],
},
gtag: {
trackingID: "G-8NBTQ7N6RB",
anonymizeIP: true,
},
}),
],
],
themeConfig:
/** @type {import('@docusaurus/preset-classic').ThemeConfig} */
({
navbar: {
title: "ffmpeg.wasm",
logo: {
alt: "ffmpeg.wasm Logo",
src: "img/logo192.png",
},
items: [
{
type: "doc",
docId: "overview",
position: "left",
label: "Docs",
},
{ to: "/playground", label: "Playground", position: "left" },
{ to: "/blog", label: "Blog", position: "left" },
{
href: "https://github.com/ffmpegwasm/ffmpeg.wasm",
label: "GitHub",
position: "right",
},
],
},
footer: {
style: "dark",
links: [
{
title: "Docs",
items: [
{
label: "Tutorial",
to: "/docs/overview",
},
],
},
{
title: "Community",
items: [
{
label: "Stack Overflow",
href: "https://stackoverflow.com/questions/tagged/ffmpeg.wasm",
},
{
label: "Discord",
href: "https://discord.gg/NjGMaqqfm5",
},
],
},
{
title: "More",
items: [
{
label: "Blog",
to: "/blog",
},
{
label: "GitHub",
href: "https://github.com/ffmpegwasm/ffmpeg.wasm",
},
],
},
],
copyright: `Copyright © ${new Date().getFullYear()} ffmpeg.wasm, Inc. Built with Docusaurus.`,
},
prism: {
theme: lightCodeTheme,
darkTheme: darkCodeTheme,
additionalLanguages: ['docker'],
},
}),
plugins: [
[require.resolve('@easyops-cn/docusaurus-search-local'), {
indexDocs: true,
indexBlog: true,
hashed: true,
}],
[
"docusaurus-plugin-typedoc",
{
id: "ffmpeg",
entryPoints: ["../../packages/ffmpeg/src/index.ts"],
tsconfig: "../../packages/ffmpeg/tsconfig.json",
readme: "none",
out: "api/ffmpeg",
sidebar: {
indexLabel: "@ffmpeg/ffmpeg",
fullNames: true,
},
},
],
[
"docusaurus-plugin-typedoc",
{
id: "util",
entryPoints: ["../../packages/util/src/index.ts"],
tsconfig: "../../packages/util/tsconfig.json",
readme: "none",
out: "api/util",
sidebar: {
indexLabel: "@ffmpeg/util",
fullNames: true,
},
},
],
],
themes: ["@docusaurus/theme-live-codeblock"],
scripts: [
{
src: "https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js?client=ca-pub-8688083214014126",
async: true,
crossorigin: "anonymous",
},
],
};
module.exports = config;
================================================
FILE: apps/website/netlify.toml
================================================
[[headers]]
for = "/*"
[headers.values]
Cross-Origin-Opener-Policy = "same-origin"
Cross-Origin-Embedder-Policy = "require-corp"
================================================
FILE: apps/website/package.json
================================================
{
"name": "website",
"version": "0.12.0-alpha.0",
"private": true,
"scripts": {
"docusaurus": "docusaurus",
"build:packages": "cd ../.. && npm run build",
"clean": "rm -rf docs/api",
"prestart": "npm run clean && npm run build:packages",
"start": "docusaurus start",
"prebuild": "npm run clean && npm run build:packages",
"build": "docusaurus build",
"swizzle": "docusaurus swizzle",
"deploy": "docusaurus deploy",
"clear": "docusaurus clear",
"serve": "docusaurus serve",
"write-translations": "docusaurus write-translations",
"write-heading-ids": "docusaurus write-heading-ids",
"typecheck": "tsc"
},
"dependencies": {
"@docusaurus/core": "^2.4.1",
"@docusaurus/preset-classic": "^2.4.1",
"@docusaurus/theme-live-codeblock": "^2.4.1",
"@emotion/react": "^11.10.4",
"@emotion/styled": "^11.10.4",
"@ffmpeg/ffmpeg": "*",
"@ffmpeg/util": "*",
"@fontsource/roboto": "^4.5.8",
"@mdx-js/react": "^1.6.22",
"@mui/icons-material": "^5.10.6",
"@mui/material": "^5.10.8",
"clsx": "^1.2.1",
"prism-react-renderer": "^1.3.5",
"react": "^17.0.2",
"react-ace": "^10.1.0",
"react-dom": "^17.0.2"
},
"devDependencies": {
"@docusaurus/module-type-aliases": "^2.2.0",
"@easyops-cn/docusaurus-search-local": "^0.34.0",
"@tsconfig/docusaurus": "^1.0.5",
"@types/ace": "^0.0.48",
"docusaurus-plugin-typedoc": "^0.17.5",
"typedoc": "^0.23.15",
"typedoc-plugin-markdown": "^3.13.6",
"typescript": "^4.7.4"
},
"browserslist": {
"production": [
">0.5%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
},
"engines": {
"node": ">=18.17"
}
}
================================================
FILE: apps/website/sidebars.js
================================================
/**
* Creating a sidebar enables you to:
- create an ordered group of docs
- render a sidebar for each doc of that group
- provide next/previous navigation
The sidebars can be generated from the filesystem, or explicitly defined here.
Create as many sidebars as you want.
*/
// @ts-check
/** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */
const sidebars = {
// By default, Docusaurus generates a sidebar from the docs folder structure
// tutorialSidebar: [{type: 'autogenerated', dirName: '.'}],
// But you can create a sidebar manually
tutorialSidebar: [
"overview",
{
type: "category",
label: "Getting Started",
items: [
"getting-started/installation",
"getting-started/usage",
"getting-started/examples",
],
},
"performance",
"migration",
"faq",
{
type: "category",
label: "API",
items: ["api/ffmpeg/index", "api/util/index"],
},
{
type: "category",
label: "Contribution",
items: ["contribution/core", "contribution/ffmpeg", "contribution/util"],
},
{
type: "doc",
label: "Privacy Policy",
id: "privacy-policy",
},
],
};
module.exports = sidebars;
================================================
FILE: apps/website/src/components/ExternalLibraries/index.tsx
================================================
import React from "react";
import clsx from "clsx";
import styles from "./styles.module.css";
interface LibraryItem {
title: string;
desc: string;
img: string;
isBlackBackground?: boolean;
}
const libs: LibraryItem[] = [
{
title: "x264",
desc: "H.264 Codec",
img: require("@site/static/img/libs/x264.png").default,
isBlackBackground: true,
},
{
title: "x265",
desc: "H.265 codec",
img: require("@site/static/img/libs/x265.webp").default,
},
{
title: "libvpx",
desc: "VP8/VP9 codec",
img: require("@site/static/img/libs/libvpx.png").default,
},
{
title: "theora",
desc: "OGV codec",
img: require("@site/static/img/libs/theora.png").default,
},
{
title: "lame",
desc: "MP3 codec",
img: require("@site/static/img/libs/lame.gif").default,
},
{
title: "vorbis",
desc: "OGG codec",
img: require("@site/static/img/libs/vorbis.png").default,
},
{
title: "opus",
desc: "OPUS codec",
img: require("@site/static/img/libs/opus.png").default,
},
{
title: "freetype2",
desc: "Font file renderer",
img: require("@site/static/img/libs/freetype.png").default,
},
{
title: "libass",
desc: "subtitle renderer",
img: require("@site/static/img/libs/freetype.png").default,
},
{
title: "libwebp",
desc: "WEBP codec",
img: require("@site/static/img/libs/webp.png").default,
},
];
function Library({ title, desc, img, isBlackBackground = false }: LibraryItem) {
return (
<div className={clsx("col col--2")}>
<div className="text--center">
<img
src={img}
className={clsx(
styles.libraryImg,
isBlackBackground && styles.blackBackground
)}
/>
</div>
<div className="text--center padding-horiz--md">
<h3>{title}</h3>
<p>{desc}</p>
</div>
</div>
);
}
export default function ExternalLibraries(): JSX.Element {
return (
<section className={styles.libraries}>
<div className="container">
<h1 className="text--center">External Libraries</h1>
<h4 className="text--center">
{" "}
ffmpeg.wasm is built with common external libraries, and more of
libraries to be added!
</h4>
<div className="row">
{libs.map((props, idx) => (
<Library key={idx} {...props} />
))}
</div>
</div>
</section>
);
}
================================================
FILE: apps/website/src/components/ExternalLibraries/styles.module.css
================================================
.libraries {
display: flex;
align-items: center;
padding: 2rem 0;
width: 100%;
background-color: rgba(229,231,235, 1);
color: #1b1b1d;
}
.libraryImg {
height: 96px;
padding: 16px;
}
.blackBackground {
background-color: #1b1b1d;
}
================================================
FILE: apps/website/src/components/HomepageFeatures/index.tsx
================================================
import React from "react";
import clsx from "clsx";
import styles from "./styles.module.css";
type FeatureItem = {
title: string;
Svg: React.ComponentType<React.ComponentProps<"svg">>;
description: JSX.Element;
};
const FeatureList: FeatureItem[] = [
{
title: "Data Security",
Svg: require("@site/static/img/safety-icon.svg").default,
description: (
<>
ffmpeg.wasm runs only inside your browser, data security is guaranteed as
no data is sent to remote server.
</>
),
},
{
title: "Powered by WebAssembly",
Svg: require("@site/static/img/wasm-logo.svg").default,
description: (
<>
ffmpeg.wasm transpiles <a href="https://ffmpeg.org/">ffmpeg</a> source
code to WebAssembly code using
<a href="https://emscripten.org/"> Emscripten</a> to achieve optimal
performance.
</>
),
},
{
title: "Made with TypeScript",
Svg: require("@site/static/img/ts-logo-round-512.svg").default,
description: (
<>
ffmpeg.wasm is written in TypeScript to provide great developer
experience (DX).
</>
),
},
];
function Feature({ title, Svg, description }: FeatureItem) {
return (
<div className={clsx("col col--4")}>
<div className="text--center">
<Svg className={styles.featureSvg} role="img" />
</div>
<div className="text--center padding-horiz--md">
<h3>{title}</h3>
<p>{description}</p>
</div>
</div>
);
}
export default function HomepageFeatures(): JSX.Element {
return (
<section className={styles.features}>
<div className="container">
<div className="row">
{FeatureList.map((props, idx) => (
<Feature key={idx} {...props} />
))}
</div>
</div>
</section>
);
}
================================================
FILE: apps/website/src/components/HomepageFeatures/styles.module.css
================================================
.features {
display: flex;
align-items: center;
padding: 2rem 0;
width: 100%;
}
.featureSvg {
height: 200px;
width: 200px;
}
================================================
FILE: apps/website/src/components/Playground/CoreDownloader.tsx
================================================
import * as React from "react";
import Typography from "@mui/material/Typography";
import Container from "@mui/material/Container";
import LinearProgressWithLabel from "@site/src/components/common/LinearProgressWithLabel";
import { CORE_SIZE } from "./const";
export default function CoreDownloader({ url, received }) {
const total = CORE_SIZE[url];
return (
<Container>
<Typography>{`Downloading ${url}`}</Typography>
<Typography>{`(${received} / ${total} bytes)`}</Typography>
<LinearProgressWithLabel value={(received / total) * 100} />
</Container>
);
}
================================================
FILE: apps/website/src/components/Playground/CoreSwitcher.tsx
================================================
import React from "react";
import Stack from "@mui/material/Stack";
import FormGroup from "@mui/material/FormGroup";
import FormControlLabel from "@mui/material/FormControlLabel";
import Switch from "@mui/material/Switch";
import IconButton from "@mui/material/IconButton";
import HelpIcon from "@mui/icons-material/HelpOutline";
import Tooltip from "@mui/material/Tooltip";
interface CoreSwitcherProps {
checked: boolean;
onChange: (event: React.ChangeEvent<HTMLInputElement>) => void;
}
export default function CoreSwitcher({ checked, onChange }: CoreSwitcherProps) {
return (
<>
<Stack direction="row" justifyContent="flex-end">
<FormGroup>
<FormControlLabel
control={<Switch checked={checked} onChange={onChange} />}
label="Use Multithreading"
disabled={typeof SharedArrayBuffer !== "function"}
/>
</FormGroup>
<Tooltip title="Multi-threaded core is faster, but unstable and not supported by all browsers.">
<IconButton aria-label="help" size="small">
<HelpIcon fontSize="small" />
</IconButton>
</Tooltip>
</Stack>
</>
);
}
================================================
FILE: apps/website/src/components/Playground/Workspace/Editor.tsx
================================================
/// <reference types="ace" />
import React, { useEffect, useState } from "react";
import AceEditor from "react-ace";
import Paper from "@mui/material/Paper";
import Stack from "@mui/material/Stack";
import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
import LinearProgressWithLabel from "@site/src/components/common/LinearProgressWithLabel";
import { useColorMode } from "@docusaurus/theme-common";
import "ace-builds/src-noconflict/mode-json";
import "ace-builds/src-noconflict/mode-javascript";
import "ace-builds/src-noconflict/mode-text";
import "ace-builds/src-noconflict/theme-dracula";
import "ace-builds/src-noconflict/theme-github";
const genFFmpegText = (args: string) => {
let data: any = [];
try {
data = JSON.parse(args);
} catch (e) {}
return `// equivalent ffmpeg.wasm API call
ffmpeg.exec(${JSON.stringify(data)});
// equivalent ffmpeg command line
ffmpeg ${data.join(" ")}`;
};
interface EditorProps {
args: string;
logs: string[];
progress: number;
time: number;
onArgsUpdate: (args: string) => void;
onExec: () => Promise<void>;
}
export default function Editor({
args = "",
logs = [],
progress = 0,
time = 0,
onArgsUpdate,
onExec,
}: EditorProps) {
const { colorMode } = useColorMode();
const [output, setOutput] = useState<Ace.Editor>();
useEffect(() => {
// scroll logs to the end.
output && output.renderer.scrollToLine(Number.POSITIVE_INFINITY);
}, [logs]);
const theme = colorMode === "dark" ? "github" : "dracula";
return (
<Paper variant="outlined" style={{ padding: 8, height: "100%" }}>
<Stack spacing={1}>
<Stack>
<Typography>Editor:</Typography>
<Typography>Edit arguments below to update command:</Typography>
<AceEditor
mode="json"
theme={theme}
name="input-args"
fontSize={16}
showPrintMargin={true}
showGutter={true}
width="100%"
minLines={8}
maxLines={8}
highlightActiveLine={true}
value={args}
onChange={onArgsUpdate}
setOptions={{ tabSize: 2, useWorker: false }}
/>
</Stack>
<AceEditor
mode="javascript"
theme={theme}
name="ffmpeg.wasm"
fontSize={16}
showGutter={false}
width="100%"
minLines={6}
maxLines={6}
readOnly
highlightActiveLine={false}
value={genFFmpegText(args)}
setOptions={{ tabSize: 2, useWorker: false }}
/>
<Typography>Console Output:</Typography>
<AceEditor
mode="text"
theme={theme}
name="console"
fontSize={16}
width="100%"
minLines={8}
maxLines={8}
readOnly
showPrintMargin={true}
highlightActiveLine={false}
value={logs.join("\n")}
setOptions={{ tabSize: 2, useWorker: false }}
onLoad={(editor) => setOutput(editor)}
/>
<Typography>Transcoding Progress:</Typography>
<LinearProgressWithLabel value={progress} />
<Stack direction="row" spacing={2} justifyContent="space-between">
<Typography>
{time === 0 ? "" : `Time Elapsed: ${(time / 1000).toFixed(2)} s`}
</Typography>
<Button variant="contained" onClick={onExec}>
Run
</Button>
</Stack>
</Stack>
</Paper>
);
}
================================================
FILE: apps/website/src/components/Playground/Workspace/FileSystemManager.tsx
================================================
import React, { useState, ChangeEvent } from "react";
import Box from "@mui/material/Box";
import Button from "@mui/material/Button";
import IconButton from "@mui/material/IconButton";
import List from "@mui/material/List";
import ListItem from "@mui/material/ListItem";
import ListItemButton from "@mui/material/ListItemButton";
import ListItemIcon from "@mui/material/ListItemIcon";
import ListItemText from "@mui/material/ListItemText";
import Modal from "@mui/material/Modal";
import Paper from "@mui/material/Paper";
import Stack from "@mui/material/Stack";
import TextField from "@mui/material/TextField";
import Tooltip from "@mui/material/Tooltip";
import Typography from "@mui/material/Typography";
import FolderIcon from "@mui/icons-material/Folder";
import RefreshIcon from "@mui/icons-material/Refresh";
import UploadFileIcon from "@mui/icons-material/UploadFile";
import UploadIcon from "@mui/icons-material/Upload";
import InsertDriveFileIcon from "@mui/icons-material/InsertDriveFile";
import CreateNewFolderIcon from "@mui/icons-material/CreateNewFolder";
import MoreButton from "./MoreButton";
import { Node } from "./types";
interface FileSystemManagerProps {
path: string;
nodes: Node[];
oldName: string;
newName: string;
renameOpen: boolean;
onNewNameChange: () => (event: ChangeEvent<HTMLInputElement>) => Promise<void>;
onCloseRenameModal: () => () => Promise<v
gitextract_a_xgwnzo/ ├── .gitattributes ├── .github/ │ ├── FUNDING.yml │ ├── ISSUE_TEMPLATE/ │ │ ├── bug_report.md │ │ └── feature_request.md │ ├── SECURITY.md │ └── workflows/ │ └── CI.yml ├── .gitignore ├── .gitmodules ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Dockerfile ├── LICENSE ├── Makefile ├── README.md ├── apps/ │ ├── angular-app/ │ │ ├── .editorconfig │ │ ├── .gitignore │ │ ├── .vscode/ │ │ │ ├── extensions.json │ │ │ ├── launch.json │ │ │ └── tasks.json │ │ ├── README.md │ │ ├── angular.json │ │ ├── package.json │ │ ├── src/ │ │ │ ├── app/ │ │ │ │ ├── app.component.css │ │ │ │ ├── app.component.html │ │ │ │ ├── app.component.spec.ts │ │ │ │ ├── app.component.ts │ │ │ │ ├── app.config.ts │ │ │ │ └── app.routes.ts │ │ │ ├── assets/ │ │ │ │ └── .gitkeep │ │ │ ├── index.html │ │ │ ├── main.ts │ │ │ └── styles.css │ │ ├── tsconfig.app.json │ │ ├── tsconfig.json │ │ └── tsconfig.spec.json │ ├── nextjs-app/ │ │ ├── .eslintrc.json │ │ ├── .gitignore │ │ ├── README.md │ │ ├── app/ │ │ │ ├── Home.tsx │ │ │ ├── NoSSRWrapper.tsx │ │ │ ├── globals.css │ │ │ ├── layout.tsx │ │ │ └── page.tsx │ │ ├── next.config.js │ │ ├── package.json │ │ ├── postcss.config.js │ │ ├── tailwind.config.ts │ │ └── tsconfig.json │ ├── react-vite-app/ │ │ ├── .eslintrc.cjs │ │ ├── .gitignore │ │ ├── README.md │ │ ├── index.html │ │ ├── package.json │ │ ├── src/ │ │ │ ├── App.tsx │ │ │ ├── index.css │ │ │ ├── main.tsx │ │ │ └── vite-env.d.ts │ │ ├── tsconfig.json │ │ ├── tsconfig.node.json │ │ └── vite.config.ts │ ├── solidstart-app/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── app.config.ts │ │ ├── package.json │ │ ├── postcss.config.cjs │ │ ├── src/ │ │ │ ├── app.css │ │ │ ├── app.tsx │ │ │ ├── entry-client.tsx │ │ │ ├── entry-server.tsx │ │ │ ├── global.d.ts │ │ │ └── routes/ │ │ │ └── index.tsx │ │ ├── tailwind.config.cjs │ │ └── tsconfig.json │ ├── sveltekit-app/ │ │ ├── .eslintignore │ │ ├── .eslintrc.cjs │ │ ├── .gitignore │ │ ├── .npmrc │ │ ├── .prettierignore │ │ ├── .prettierrc │ │ ├── README.md │ │ ├── package.json │ │ ├── playwright.config.ts │ │ ├── src/ │ │ │ ├── app.d.ts │ │ │ ├── app.html │ │ │ ├── index.test.ts │ │ │ ├── lib/ │ │ │ │ ├── FFmpegDemo.svelte │ │ │ │ └── index.ts │ │ │ └── routes/ │ │ │ └── +page.svelte │ │ ├── svelte.config.js │ │ ├── tests/ │ │ │ └── test.ts │ │ ├── tsconfig.json │ │ └── vite.config.ts │ ├── vanilla-app/ │ │ ├── .gitignore │ │ ├── README.md │ │ ├── package.json │ │ ├── public/ │ │ │ ├── concatDemuxer.html │ │ │ ├── style.css │ │ │ ├── transcode-mt.esm.html │ │ │ ├── transcode-mt.html │ │ │ ├── transcode.esm.html │ │ │ ├── transcode.html │ │ │ └── trim.html │ │ └── server.js │ ├── vue-vite-app/ │ │ ├── .eslintrc.cjs │ │ ├── .gitignore │ │ ├── .prettierrc.json │ │ ├── .vscode/ │ │ │ └── extensions.json │ │ ├── README.md │ │ ├── env.d.ts │ │ ├── index.html │ │ ├── package.json │ │ ├── src/ │ │ │ ├── App.vue │ │ │ ├── assets/ │ │ │ │ ├── base.css │ │ │ │ └── main.css │ │ │ ├── components/ │ │ │ │ └── FFmpegDemo.vue │ │ │ └── main.ts │ │ ├── tsconfig.app.json │ │ ├── tsconfig.json │ │ ├── tsconfig.node.json │ │ └── vite.config.ts │ └── website/ │ ├── .gitignore │ ├── README.md │ ├── assets/ │ │ ├── angular.xcf │ │ ├── background.xcf │ │ ├── ffmpegwasm-arch.drawio │ │ ├── nextjs.xcf │ │ ├── react-vite.xcf │ │ ├── solidstart-vite.xcf │ │ ├── sveltekit-vite.xcf │ │ ├── vanilla.xcf │ │ └── vue-vite.xcf │ ├── babel.config.js │ ├── blog/ │ │ ├── 2023-07-26-release-ffmpeg.wasm-0.12.0.mdx │ │ └── authors.yml │ ├── deploy.sh │ ├── docs/ │ │ ├── contribution/ │ │ │ ├── core.md │ │ │ ├── ffmpeg.md │ │ │ └── util.md │ │ ├── faq.md │ │ ├── getting-started/ │ │ │ ├── examples.md │ │ │ ├── installation.md │ │ │ └── usage.md │ │ ├── migration.md │ │ ├── overview.md │ │ ├── performance.md │ │ └── privacy-policy.md │ ├── docusaurus.config.js │ ├── netlify.toml │ ├── package.json │ ├── sidebars.js │ ├── src/ │ │ ├── components/ │ │ │ ├── ExternalLibraries/ │ │ │ │ ├── index.tsx │ │ │ │ └── styles.module.css │ │ │ ├── HomepageFeatures/ │ │ │ │ ├── index.tsx │ │ │ │ └── styles.module.css │ │ │ ├── Playground/ │ │ │ │ ├── CoreDownloader.tsx │ │ │ │ ├── CoreSwitcher.tsx │ │ │ │ ├── Workspace/ │ │ │ │ │ ├── Editor.tsx │ │ │ │ │ ├── FileSystemManager.tsx │ │ │ │ │ ├── MoreButton.tsx │ │ │ │ │ ├── index.tsx │ │ │ │ │ └── types.tsx │ │ │ │ ├── const.ts │ │ │ │ └── index.tsx │ │ │ └── common/ │ │ │ ├── ExampleCard.tsx │ │ │ ├── LinearProgressWithLabel.tsx │ │ │ ├── MuiThemeProvider/ │ │ │ │ └── index.tsx │ │ │ ├── ThemedButton/ │ │ │ │ └── index.tsx │ │ │ └── ThemedIconButton/ │ │ │ └── index.tsx │ │ ├── css/ │ │ │ └── custom.css │ │ ├── pages/ │ │ │ ├── index.module.css │ │ │ ├── index.tsx │ │ │ └── playground.md │ │ ├── theme/ │ │ │ └── ReactLiveScope/ │ │ │ └── index.js │ │ └── util.ts │ ├── static/ │ │ ├── .nojekyll │ │ └── ads.txt │ └── tsconfig.json ├── build/ │ ├── aom.sh │ ├── ffmpeg-wasm.sh │ ├── ffmpeg.sh │ ├── freetype2.sh │ ├── fribidi.sh │ ├── harfbuzz.sh │ ├── lame.sh │ ├── libass.sh │ ├── libvpx.sh │ ├── libwebp.sh │ ├── ogg.sh │ ├── opus.sh │ ├── theora.sh │ ├── vorbis.sh │ ├── wavpack.sh │ ├── x264.sh │ ├── x265.sh │ ├── zimg.sh │ └── zlib.sh ├── package.json ├── packages/ │ ├── core/ │ │ ├── .gitignore │ │ └── package.json │ ├── core-mt/ │ │ ├── .gitignore │ │ └── package.json │ ├── ffmpeg/ │ │ ├── .eslintignore │ │ ├── .eslintrc.cjs │ │ ├── .gitignore │ │ ├── package.json │ │ ├── src/ │ │ │ ├── classes.ts │ │ │ ├── const.ts │ │ │ ├── empty.mts │ │ │ ├── errors.ts │ │ │ ├── index.ts │ │ │ ├── types.ts │ │ │ ├── utils.ts │ │ │ └── worker.ts │ │ ├── tsconfig.esm.json │ │ ├── tsconfig.json │ │ └── webpack.config.js │ ├── types/ │ │ ├── package.json │ │ └── types/ │ │ └── index.d.ts │ └── util/ │ ├── .eslintrc.cjs │ ├── .gitignore │ ├── package.json │ ├── src/ │ │ ├── const.ts │ │ ├── errors.ts │ │ ├── index.ts │ │ └── types.ts │ ├── tests/ │ │ ├── .eslintrc │ │ ├── constants.js │ │ ├── ffmpeg.test.html │ │ └── ffmpeg.test.js │ ├── tsconfig.cjs.json │ ├── tsconfig.esm.json │ ├── tsconfig.json │ └── webpack.config.cjs ├── scripts/ │ └── download-assets.js ├── src/ │ ├── bind/ │ │ ├── .eslintrc.cjs │ │ └── ffmpeg/ │ │ ├── bind.js │ │ ├── export-runtime.js │ │ └── export.js │ └── fftools/ │ ├── Makefile │ ├── cmdutils.c │ ├── cmdutils.h │ ├── ffmpeg.c │ ├── ffmpeg.h │ ├── ffmpeg_filter.c │ ├── ffmpeg_hw.c │ ├── ffmpeg_mux.c │ ├── ffmpeg_opt.c │ ├── ffplay.c │ ├── ffprobe.c │ ├── fopen_utf8.h │ ├── opt_common.c │ └── opt_common.h ├── tests/ │ ├── .eslintrc.json │ ├── ffmpeg-core-mt.test.html │ ├── ffmpeg-core-st.test.html │ ├── ffmpeg-core.test.js │ ├── ffmpeg-mt.test.html │ ├── ffmpeg-st.test.html │ ├── ffmpeg.test.js │ ├── index.html │ ├── test-helper-browser.js │ ├── test-helper-mt.js │ ├── test-helper-st.js │ └── util.js └── tsconfig.json
SYMBOL INDEX (708 symbols across 52 files)
FILE: apps/angular-app/src/app/app.component.ts
class AppComponent (line 16) | class AppComponent {
method load (line 21) | async load() {
method transcode (line 38) | async transcode() {
FILE: apps/nextjs-app/app/Home.tsx
function Home (line 7) | function Home() {
FILE: apps/nextjs-app/app/layout.tsx
function RootLayout (line 12) | function RootLayout({
FILE: apps/nextjs-app/app/page.tsx
function Page (line 6) | function Page() {
FILE: apps/react-vite-app/src/App.tsx
function App (line 5) | function App() {
FILE: apps/solidstart-app/src/app.tsx
function App (line 6) | function App() {
FILE: apps/solidstart-app/src/routes/index.tsx
function Home (line 9) | function Home() {
FILE: apps/sveltekit-app/vite.config.ts
method configureServer (line 8) | configureServer(server) {
FILE: apps/vanilla-app/server.js
constant PORT (line 5) | const PORT = 8080;
constant ROOT (line 6) | const ROOT = path.join(__dirname, "public");
FILE: apps/website/src/components/ExternalLibraries/index.tsx
type LibraryItem (line 5) | interface LibraryItem {
function Library (line 66) | function Library({ title, desc, img, isBlackBackground = false }: Librar...
function ExternalLibraries (line 86) | function ExternalLibraries(): JSX.Element {
FILE: apps/website/src/components/HomepageFeatures/index.tsx
type FeatureItem (line 5) | type FeatureItem = {
function Feature (line 46) | function Feature({ title, Svg, description }: FeatureItem) {
function HomepageFeatures (line 60) | function HomepageFeatures(): JSX.Element {
FILE: apps/website/src/components/Playground/CoreDownloader.tsx
function CoreDownloader (line 7) | function CoreDownloader({ url, received }) {
FILE: apps/website/src/components/Playground/CoreSwitcher.tsx
type CoreSwitcherProps (line 10) | interface CoreSwitcherProps {
function CoreSwitcher (line 15) | function CoreSwitcher({ checked, onChange }: CoreSwitcherProps) {
FILE: apps/website/src/components/Playground/Workspace/Editor.tsx
type EditorProps (line 29) | interface EditorProps {
function Editor (line 38) | function Editor({
FILE: apps/website/src/components/Playground/Workspace/FileSystemManager.tsx
type FileSystemManagerProps (line 25) | interface FileSystemManagerProps {
function FileSystemManager (line 61) | function FileSystemManager({
FILE: apps/website/src/components/Playground/Workspace/MoreButton.tsx
constant ITEM_HEIGHT (line 7) | const ITEM_HEIGHT = 48;
type Option (line 9) | interface Option {
type MoreButtonProps (line 14) | interface MoreButtonProps {
function MoreButton (line 19) | function MoreButton({ options, onItemClick }: MoreButtonProps) {
FILE: apps/website/src/components/Playground/Workspace/index.tsx
type WorkspaceProps (line 19) | interface WorkspaceProps {
function Workspace (line 23) | function Workspace({ ffmpeg: _ffmpeg }: WorkspaceProps) {
FILE: apps/website/src/components/Playground/Workspace/types.tsx
type Node (line 1) | interface Node {
FILE: apps/website/src/components/Playground/const.ts
constant CORE_VERSION (line 1) | const CORE_VERSION = "0.12.10";
constant CORE_URL (line 3) | const CORE_URL = `https://cdn.jsdelivr.net/npm/@ffmpeg/core@${CORE_VERSI...
constant CORE_MT_URL (line 4) | const CORE_MT_URL = `https://cdn.jsdelivr.net/npm/@ffmpeg/core-mt@${CORE...
constant CORE_SIZE (line 6) | const CORE_SIZE = {
constant SAMPLE_FILES (line 14) | const SAMPLE_FILES = {
FILE: apps/website/src/components/Playground/index.tsx
type State (line 11) | enum State {
function Playground (line 17) | function Playground() {
FILE: apps/website/src/components/common/ExampleCard.tsx
function ActionAreaCard (line 9) | function ActionAreaCard({ img, title, desc, url }) {
FILE: apps/website/src/components/common/LinearProgressWithLabel.tsx
function LinearProgressWithLabel (line 8) | function LinearProgressWithLabel(
FILE: apps/website/src/components/common/MuiThemeProvider/index.tsx
function MuiThemeProvider (line 12) | function MuiThemeProvider(props: any) {
FILE: apps/website/src/components/common/ThemedButton/index.tsx
function ThemedButton (line 5) | function ThemedButton(props: ButtonProps) {
FILE: apps/website/src/components/common/ThemedIconButton/index.tsx
function ThemedIconButton (line 5) | function ThemedIconButton(props: IconButtonProps) {
FILE: apps/website/src/pages/index.tsx
function HomepageHeader (line 11) | function HomepageHeader() {
function Home (line 31) | function Home(): JSX.Element {
FILE: packages/ffmpeg/src/classes.ts
type FFMessageOptions (line 23) | type FFMessageOptions = {
class FFmpeg (line 35) | class FFmpeg {
method on (line 147) | public on(
method off (line 165) | public off(
FILE: packages/ffmpeg/src/const.ts
constant MIME_TYPE_JAVASCRIPT (line 1) | const MIME_TYPE_JAVASCRIPT = "text/javascript";
constant MIME_TYPE_WASM (line 2) | const MIME_TYPE_WASM = "application/wasm";
constant CORE_VERSION (line 4) | const CORE_VERSION = "0.12.10";
constant CORE_URL (line 5) | const CORE_URL = `https://cdn.jsdelivr.net/npm/@ffmpeg/core@${CORE_VERSI...
type FFMessageType (line 7) | enum FFMessageType {
FILE: packages/ffmpeg/src/errors.ts
constant ERROR_UNKNOWN_MESSAGE_TYPE (line 1) | const ERROR_UNKNOWN_MESSAGE_TYPE = new Error("unknown message type");
constant ERROR_NOT_LOADED (line 2) | const ERROR_NOT_LOADED = new Error(
constant ERROR_TERMINATED (line 5) | const ERROR_TERMINATED = new Error("called FFmpeg.terminate()");
constant ERROR_IMPORT_FAILURE (line 6) | const ERROR_IMPORT_FAILURE = new Error(
FILE: packages/ffmpeg/src/types.ts
type FFFSPath (line 1) | type FFFSPath = string;
type FFMessageLoadConfig (line 6) | interface FFMessageLoadConfig {
type FFMessageExecData (line 35) | interface FFMessageExecData {
type FFMessageWriteFileData (line 40) | interface FFMessageWriteFileData {
type FFMessageReadFileData (line 45) | interface FFMessageReadFileData {
type FFMessageDeleteFileData (line 50) | interface FFMessageDeleteFileData {
type FFMessageRenameData (line 54) | interface FFMessageRenameData {
type FFMessageCreateDirData (line 59) | interface FFMessageCreateDirData {
type FFMessageListDirData (line 63) | interface FFMessageListDirData {
type FFMessageDeleteDirData (line 71) | interface FFMessageDeleteDirData {
type FFFSType (line 75) | enum FFFSType {
type WorkerFSFileEntry (line 84) | type WorkerFSFileEntry =
type WorkerFSBlobEntry (line 87) | interface WorkerFSBlobEntry {
type WorkerFSMountData (line 92) | interface WorkerFSMountData {
type FFFSMountOptions (line 97) | type FFFSMountOptions =
type FFMessageMountData (line 100) | interface FFMessageMountData {
type FFMessageUnmountData (line 106) | interface FFMessageUnmountData {
type FFMessageData (line 110) | type FFMessageData =
type Message (line 123) | interface Message {
type FFMessage (line 128) | interface FFMessage extends Message {
type FFMessageEvent (line 132) | interface FFMessageEvent extends MessageEvent {
type LogEvent (line 136) | interface LogEvent {
type ProgressEvent (line 141) | interface ProgressEvent {
type ExitCode (line 146) | type ExitCode = number;
type ErrorMessage (line 147) | type ErrorMessage = string;
type FileData (line 148) | type FileData = Uint8Array | string;
type IsFirst (line 149) | type IsFirst = boolean;
type OK (line 150) | type OK = boolean;
type FSNode (line 152) | interface FSNode {
type CallbackData (line 157) | type CallbackData =
type Callbacks (line 169) | interface Callbacks {
type LogEventCallback (line 173) | type LogEventCallback = (event: LogEvent) => void;
type ProgressEventCallback (line 174) | type ProgressEventCallback = (event: ProgressEvent) => void;
type FFMessageEventCallback (line 176) | interface FFMessageEventCallback {
FILE: packages/ffmpeg/src/worker.ts
type WorkerGlobalScope (line 34) | interface WorkerGlobalScope {
type ImportedFFmpegCoreModuleFactory (line 39) | interface ImportedFFmpegCoreModuleFactory {
FILE: packages/types/types/index.d.ts
type Pointer (line 3) | type Pointer = number;
type StringPointer (line 5) | type StringPointer = Pointer;
type StringArrayPointer (line 6) | type StringArrayPointer = Pointer;
type DateString (line 7) | type DateString = string;
type ReadFileOptions (line 15) | interface ReadFileOptions {
type Stat (line 26) | interface Stat {
type FSFilesystemWORKERFS (line 42) | interface FSFilesystemWORKERFS {}
type FSFilesystemMEMFS (line 44) | interface FSFilesystemMEMFS {}
type FSFilesystems (line 46) | interface FSFilesystems {
type FSFilesystem (line 51) | type FSFilesystem = FSFilesystemWORKERFS | FSFilesystemMEMFS;
type OptionReadFile (line 53) | interface OptionReadFile {
type WorkerFSMountConfig (line 57) | interface WorkerFSMountConfig {
type FS (line 71) | interface FS {
type Log (line 96) | interface Log {
type Progress (line 105) | interface Progress {
type FFmpegCoreModule (line 115) | interface FFmpegCoreModule {
type FFmpegCoreModuleFactory (line 140) | type FFmpegCoreModuleFactory = (
FILE: packages/util/src/errors.ts
constant ERROR_RESPONSE_BODY_READER (line 1) | const ERROR_RESPONSE_BODY_READER = new Error(
constant ERROR_INCOMPLETED_DOWNLOAD (line 4) | const ERROR_INCOMPLETED_DOWNLOAD = new Error(
FILE: packages/util/src/types.ts
type DownloadProgressEvent (line 1) | interface DownloadProgressEvent {
type ProgressCallback (line 9) | type ProgressCallback = (event: DownloadProgressEvent) => void;
FILE: packages/util/tests/constants.js
constant TIMEOUT (line 1) | const TIMEOUT = 60000;
constant IS_BROWSER (line 2) | const IS_BROWSER = typeof window !== 'undefined' && typeof window.docume...
constant OPTIONS (line 3) | const OPTIONS = {
constant FLAME_MP4_LENGTH (line 6) | const FLAME_MP4_LENGTH = 100374;
constant META_FLAME_MP4_LENGTH (line 7) | const META_FLAME_MP4_LENGTH = 100408;
constant META_FLAME_MP4_LENGTH_NO_SPACE (line 8) | const META_FLAME_MP4_LENGTH_NO_SPACE = 100404;
FILE: scripts/download-assets.js
constant NPM_URL (line 4) | const NPM_URL = "https://registry.npmjs.org";
constant ROOT (line 5) | const ROOT = "public/assets";
constant FFMPEG_VERSION (line 7) | const FFMPEG_VERSION = "0.12.15";
constant UTIL_VERSION (line 8) | const UTIL_VERSION = "0.12.2";
constant CORE_VERSION (line 9) | const CORE_VERSION = "0.12.10";
constant CORE_MT_VERSION (line 10) | const CORE_MT_VERSION = "0.12.10";
constant FFMPEG_TGZ (line 12) | const FFMPEG_TGZ = `ffmpeg-${FFMPEG_VERSION}.tgz`;
constant UTIL_TGZ (line 13) | const UTIL_TGZ = `util-${UTIL_VERSION}.tgz`;
constant CORE_TGZ (line 14) | const CORE_TGZ = `core-${CORE_VERSION}.tgz`;
constant CORE_MT_TGZ (line 15) | const CORE_MT_TGZ = `core-mt-${CORE_MT_VERSION}.tgz`;
constant FFMPEG_TGZ_URL (line 17) | const FFMPEG_TGZ_URL = `${NPM_URL}/@ffmpeg/ffmpeg/-/${FFMPEG_TGZ}`;
constant UTIL_TGZ_URL (line 18) | const UTIL_TGZ_URL = `${NPM_URL}/@ffmpeg/util/-/${UTIL_TGZ}`;
constant CORE_TGZ_URL (line 19) | const CORE_TGZ_URL = `${NPM_URL}/@ffmpeg/core/-/${CORE_TGZ}`;
constant CORE_MT_TGZ_URL (line 20) | const CORE_MT_TGZ_URL = `${NPM_URL}/@ffmpeg/core-mt/-/${CORE_MT_TGZ}`;
FILE: src/bind/ffmpeg/bind.js
constant NULL (line 5) | const NULL = 0;
constant SIZE_I32 (line 6) | const SIZE_I32 = Uint32Array.BYTES_PER_ELEMENT;
constant DEFAULT_ARGS (line 7) | const DEFAULT_ARGS = ["./ffmpeg", "-nostdin", "-y"];
constant DEFAULT_ARGS_FFPROBE (line 8) | const DEFAULT_ARGS_FFPROBE = ["./ffprobe"];
function stringToPtr (line 28) | function stringToPtr(str) {
function stringsToPtr (line 36) | function stringsToPtr(strs) {
function print (line 46) | function print(message) {
function printErr (line 50) | function printErr(message) {
function exec (line 55) | function exec(..._args) {
function ffprobe (line 67) | function ffprobe(..._args) {
function setLogger (line 79) | function setLogger(logger) {
function setTimeout (line 83) | function setTimeout(timeout) {
function setProgress (line 87) | function setProgress(handler) {
function receiveProgress (line 91) | function receiveProgress(progress, time) {
function reset (line 95) | function reset() {
function _locateFile (line 119) | function _locateFile(path, prefix) {
FILE: src/bind/ffmpeg/export-runtime.js
constant EXPORTED_RUNTIME_METHODS (line 1) | const EXPORTED_RUNTIME_METHODS = [
FILE: src/bind/ffmpeg/export.js
constant EXPORTED_FUNCTIONS (line 1) | const EXPORTED_FUNCTIONS = ["_ffmpeg", "_abort", "_malloc", "_ffprobe"];
FILE: src/fftools/cmdutils.c
function uninit_opts (line 65) | void uninit_opts(void)
function log_callback_help (line 73) | void log_callback_help(void *ptr, int level, const char *fmt, va_list vl)
function init_dynload (line 78) | void init_dynload(void)
function register_exit (line 89) | void register_exit(void (*cb)(int ret))
function exit_program (line 94) | void exit_program(int ret)
function parse_number_or_die (line 118) | double parse_number_or_die(const char *context, const char *numstr, int ...
function parse_time_or_die (line 139) | int64_t parse_time_or_die(const char *context, const char *timestr,
function show_help_options (line 151) | void show_help_options(const OptionDef *options, const char *msg, int re...
function show_help_children (line 180) | void show_help_children(const AVClass *class, int flags)
function OptionDef (line 193) | static const OptionDef *find_option(const OptionDef *po, const char *name)
function prepare_app_arguments (line 220) | static void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
function prepare_app_arguments (line 262) | static inline void prepare_app_arguments(int *argc_ptr, char ***argv_ptr)
function write_option (line 268) | static int write_option(void *optctx, const OptionDef *po, const char *opt,
function parse_option (line 323) | int parse_option(void *optctx, const char *opt, const char *arg,
function parse_options (line 362) | void parse_options(void *optctx, int argc, char **argv, const OptionDef ...
function parse_optgroup (line 393) | int parse_optgroup(void *optctx, OptionGroup *g)
function locate_option (line 426) | int locate_option(int argc, char **argv, const OptionDef *options,
function dump_argument (line 452) | static void dump_argument(FILE *report_file, const char *a)
function check_options (line 476) | static void check_options(const OptionDef *po)
function parse_loglevel (line 485) | void parse_loglevel(int argc, char **argv, const OptionDef *options)
function AVOption (line 517) | static const AVOption *opt_find(void *obj, const char *name, const char ...
function opt_default (line 527) | int opt_default(void *optctx, const char *opt, const char *arg)
function match_group_separator (line 599) | static int match_group_separator(const OptionGroupDef *groups, int nb_gr...
function finish_group (line 619) | static void finish_group(OptionParseContext *octx, int group_idx,
function add_opt (line 647) | static void add_opt(OptionParseContext *octx, const OptionDef *opt,
function init_parse_context (line 659) | static void init_parse_context(OptionParseContext *octx,
function uninit_parse_context (line 679) | void uninit_parse_context(OptionParseContext *octx)
function split_commandline (line 704) | int split_commandline(OptionParseContext *octx, int argc, char *argv[],
function print_error (line 810) | void print_error(const char *filename, int err)
function read_yesno (line 820) | int read_yesno(void)
function FILE (line 831) | FILE *get_preset_file(char *filename, size_t filename_size,
function check_stream_specifier (line 903) | int check_stream_specifier(AVFormatContext *s, AVStream *st, const char ...
function AVDictionary (line 911) | AVDictionary *filter_codec_opts(AVDictionary *opts, enum AVCodecID codec...
function AVDictionary (line 969) | AVDictionary **setup_find_stream_info_opts(AVFormatContext *s,
function get_rotation (line 1020) | double get_rotation(int32_t *displaymatrix)
FILE: src/fftools/cmdutils.h
type SpecifierOpt (line 123) | typedef struct SpecifierOpt {
type OptionDef (line 135) | typedef struct OptionDef {
type Option (line 221) | typedef struct Option {
type OptionGroupDef (line 227) | typedef struct OptionGroupDef {
type OptionGroup (line 242) | typedef struct OptionGroup {
type OptionGroupList (line 259) | typedef struct OptionGroupList {
type OptionParseContext (line 266) | typedef struct OptionParseContext {
type AVCodecID (line 346) | enum AVCodecID
FILE: src/fftools/ffmpeg.c
type BenchmarkTimeStamps (line 125) | typedef struct BenchmarkTimeStamps {
type termios (line 164) | struct termios
function sub2video_get_blank_frame (line 177) | static int sub2video_get_blank_frame(InputStream *ist)
function sub2video_copy_rect (line 192) | static void sub2video_copy_rect(uint8_t *dst, int dst_linesize, int w, i...
function sub2video_push_ref (line 223) | static void sub2video_push_ref(InputStream *ist, int64_t pts)
function sub2video_update (line 241) | void sub2video_update(InputStream *ist, int64_t heartbeat_pts, AVSubtitl...
function sub2video_heartbeat (line 281) | static void sub2video_heartbeat(InputStream *ist, int64_t pts)
function sub2video_flush (line 313) | static void sub2video_flush(InputStream *ist)
function term_exit_sigsafe (line 329) | static void term_exit_sigsafe(void)
function term_exit (line 337) | void term_exit(void)
function sigterm_handler (line 350) | static void
function BOOL (line 366) | static BOOL WINAPI CtrlHandler(DWORD fdwCtrlType)
function term_init (line 408) | void term_init(void)
function read_key (line 457) | static int read_key(void)
function decode_interrupt_cb (line 508) | static int decode_interrupt_cb(void *ctx)
function ffmpeg_cleanup (line 515) | static void ffmpeg_cleanup(int ret)
function remove_avoptions (line 659) | void remove_avoptions(AVDictionary **a, AVDictionary *b)
function assert_avoptions (line 668) | void assert_avoptions(AVDictionary *m)
function abort_codec_experimental (line 677) | static void abort_codec_experimental(const AVCodec *c, int encoder)
function update_benchmark (line 682) | static void update_benchmark(const char *fmt, ...)
function close_output_stream (line 703) | static void close_output_stream(OutputStream *ost)
function output_packet (line 726) | static void output_packet(OutputFile *of, AVPacket *pkt,
function check_recording_time (line 752) | static int check_recording_time(OutputStream *ost)
function adjust_frame_pts_to_encoder_tb (line 765) | static double adjust_frame_pts_to_encoder_tb(OutputFile *of, OutputStrea...
function init_output_stream_wrapper (line 812) | static int init_output_stream_wrapper(OutputStream *ost, AVFrame *frame,
function psnr (line 833) | static double psnr(double d)
function update_video_stats (line 838) | static void update_video_stats(OutputStream *ost, const AVPacket *pkt, i...
function encode_frame (line 893) | static int encode_frame(OutputFile *of, OutputStream *ost, AVFrame *frame)
function do_audio_out (line 975) | static void do_audio_out(OutputFile *of, OutputStream *ost,
function do_subtitle_out (line 995) | static void do_subtitle_out(OutputFile *of,
function do_video_out (line 1079) | static void do_video_out(OutputFile *of,
function finish_output_stream (line 1295) | static void finish_output_stream(OutputStream *ost)
function reap_filters (line 1314) | static int reap_filters(int flush)
function print_final_stats (line 1391) | static void print_final_stats(int64_t total_size)
function print_report (line 1512) | static void print_report(int is_last_report, int64_t timer_start, int64_...
function ifilter_parameters_from_codecpar (line 1744) | static int ifilter_parameters_from_codecpar(InputFilter *ifilter, AVCode...
function flush_encoders (line 1762) | static void flush_encoders(void)
function check_output_constraints (line 1821) | static int check_output_constraints(InputStream *ist, OutputStream *ost)
function do_streamcopy (line 1838) | static void do_streamcopy(InputStream *ist, OutputStream *ost, const AVP...
function guess_input_channel_layout (line 1915) | int guess_input_channel_layout(InputStream *ist)
function check_decode_result (line 1934) | static void check_decode_result(InputStream *ist, int *got_output, int ret)
function ifilter_has_all_input_formats (line 1953) | static int ifilter_has_all_input_formats(FilterGraph *fg)
function ifilter_send_frame (line 1964) | static int ifilter_send_frame(InputFilter *ifilter, AVFrame *frame, int ...
function ifilter_send_eof (line 2044) | static int ifilter_send_eof(InputFilter *ifilter, int64_t pts)
function decode (line 2074) | static int decode(AVCodecContext *avctx, AVFrame *frame, int *got_frame,...
function send_frame_to_filters (line 2097) | static int send_frame_to_filters(InputStream *ist, AVFrame *decoded_frame)
function decode_audio (line 2115) | static int decode_audio(InputStream *ist, AVPacket *pkt, int *got_output,
function decode_video (line 2175) | static int decode_video(InputStream *ist, AVPacket *pkt, int *got_output...
function transcode_subtitles (line 2300) | static int transcode_subtitles(InputStream *ist, AVPacket *pkt, int *got...
function send_filter_eof (line 2375) | static int send_filter_eof(InputStream *ist)
function process_input_packet (line 2391) | static int process_input_packet(InputStream *ist, const AVPacket *pkt, i...
function get_format (line 2579) | static enum AVPixelFormat get_format(AVCodecContext *s, const enum AVPix...
function init_input_stream (line 2628) | static int init_input_stream(int ist_index, char *error, int error_len)
function InputStream (line 2693) | static InputStream *get_input_stream(OutputStream *ost)
function compare_int64 (line 2700) | static int compare_int64(const void *a, const void *b)
function init_output_bsfs (line 2705) | static int init_output_bsfs(OutputStream *ost)
function init_output_stream_streamcopy (line 2734) | static int init_output_stream_streamcopy(OutputStream *ost)
function set_encoder_id (line 2853) | static void set_encoder_id(OutputFile *of, OutputStream *ost)
function parse_forced_key_frames (line 2894) | static void parse_forced_key_frames(char *kf, OutputStream *ost,
function init_encoder_time_base (line 2957) | static void init_encoder_time_base(OutputStream *ost, AVRational default...
function init_output_stream_encode (line 2981) | static int init_output_stream_encode(OutputStream *ost, AVFrame *frame)
function init_output_stream (line 3144) | static int init_output_stream(OutputStream *ost, AVFrame *frame,
function report_new_stream (line 3288) | static void report_new_stream(int input_index, AVPacket *pkt)
function transcode_init (line 3303) | static int transcode_init(void)
function need_output (line 3485) | static int need_output(void)
function OutputStream (line 3515) | static OutputStream *choose_output(void)
function set_tty_echo (line 3542) | static void set_tty_echo(int on)
function check_keyboard_interaction (line 3554) | static int check_keyboard_interaction(int64_t cur_time)
function free_input_thread (line 3718) | static void free_input_thread(int i)
function free_input_threads (line 3734) | static void free_input_threads(void)
function init_input_thread (line 3742) | static int init_input_thread(int i)
function init_input_threads (line 3769) | static int init_input_threads(void)
function get_input_packet_mt (line 3781) | static int get_input_packet_mt(InputFile *f, AVPacket **pkt)
function get_input_packet (line 3789) | static int get_input_packet(InputFile *f, AVPacket **pkt)
function got_eagain (line 3818) | static int got_eagain(void)
function reset_eagain (line 3827) | static void reset_eagain(void)
function AVRational (line 3837) | static AVRational duration_max(int64_t tmp, int64_t *duration, AVRationa...
function seek_to_start (line 3856) | static int seek_to_start(InputFile *ifile, AVFormatContext *is)
function process_input (line 3922) | static int process_input(int file_index)
function transcode_from_filter (line 4218) | static int transcode_from_filter(FilterGraph *graph, InputStream **best_...
function transcode_step (line 4264) | static int transcode_step(void)
function transcode (line 4364) | static int transcode(void)
function BenchmarkTimeStamps (line 4511) | static BenchmarkTimeStamps get_benchmark_time_stamps(void)
function getmaxrss (line 4537) | static int64_t getmaxrss(void)
function init_globals (line 4562) | void init_globals() {
function ffmpeg (line 4599) | int ffmpeg(int argc, char **argv)
FILE: src/fftools/ffmpeg.h
type VideoSyncMethod (line 50) | enum VideoSyncMethod {
type HWAccelID (line 61) | enum HWAccelID {
type HWDevice (line 67) | typedef struct HWDevice {
type StreamMap (line 74) | typedef struct StreamMap {
type AudioChannelMap (line 83) | typedef struct {
type OptionsContext (line 88) | typedef struct OptionsContext {
type InputFilter (line 242) | typedef struct InputFilter {
type OutputFilter (line 266) | typedef struct OutputFilter {
type FilterGraph (line 290) | typedef struct FilterGraph {
type InputStream (line 306) | typedef struct InputStream {
type InputFile (line 404) | typedef struct InputFile {
type forced_keyframes_const (line 438) | enum forced_keyframes_const {
type OSTFinished (line 452) | typedef enum {
type OutputStream (line 457) | typedef struct OutputStream {
type OutputFile (line 586) | typedef struct OutputFile {
type VideoSyncMethod (line 625) | enum VideoSyncMethod
FILE: src/fftools/ffmpeg_filter.c
type AVPixelFormat (line 42) | enum AVPixelFormat
type AVPixelFormat (line 42) | enum AVPixelFormat
type AVPixelFormat (line 44) | enum AVPixelFormat
function choose_pixel_fmt (line 55) | static enum AVPixelFormat choose_pixel_fmt(AVStream *st, AVCodecContext ...
type AVPixelFormat (line 107) | enum AVPixelFormat
function init_input_filter (line 228) | static void init_input_filter(FilterGraph *fg, AVFilterInOut *in)
function init_complex_filtergraph (line 315) | int init_complex_filtergraph(FilterGraph *fg)
function insert_trim (line 353) | static int insert_trim(int64_t start_time, int64_t duration,
function insert_filter (line 404) | static int insert_filter(AVFilterContext **last_filter, int *pad_idx,
function configure_output_video_filter (line 426) | static int configure_output_video_filter(FilterGraph *fg, OutputFilter *...
function configure_output_audio_filter (line 521) | static int configure_output_audio_filter(FilterGraph *fg, OutputFilter *...
function configure_output_filter (line 630) | static int configure_output_filter(FilterGraph *fg, OutputFilter *ofilter,
function check_filter_outputs (line 645) | void check_filter_outputs(void)
function sub2video_prepare (line 660) | static int sub2video_prepare(InputStream *ist, InputFilter *ifilter)
function configure_input_video_filter (line 707) | static int configure_input_video_filter(FilterGraph *fg, InputFilter *if...
function configure_input_audio_filter (line 832) | static int configure_input_audio_filter(FilterGraph *fg, InputFilter *if...
function configure_input_filter (line 943) | static int configure_input_filter(FilterGraph *fg, InputFilter *ifilter,
function cleanup_filtergraph (line 959) | static void cleanup_filtergraph(FilterGraph *fg)
function filter_is_buffersrc (line 969) | static int filter_is_buffersrc(const AVFilterContext *f)
function graph_is_meta (line 976) | static int graph_is_meta(AVFilterGraph *graph)
function configure_filtergraph (line 993) | int configure_filtergraph(FilterGraph *fg)
function ifilter_parameters_from_frame (line 1169) | int ifilter_parameters_from_frame(InputFilter *ifilter, const AVFrame *f...
function filtergraph_is_simple (line 1201) | int filtergraph_is_simple(FilterGraph *fg)
FILE: src/fftools/ffmpeg_hw.c
function HWDevice (line 30) | static HWDevice *hw_device_get_by_type(enum AVHWDeviceType type)
function HWDevice (line 44) | HWDevice *hw_device_get_by_name(const char *name)
function HWDevice (line 54) | static HWDevice *hw_device_add(void)
type AVHWDeviceType (line 69) | enum AVHWDeviceType
function hw_device_init_from_string (line 94) | int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
function hw_device_init_from_type (line 245) | static int hw_device_init_from_type(enum AVHWDeviceType type,
function hw_device_free_all (line 288) | void hw_device_free_all(void)
function HWDevice (line 300) | static HWDevice *hw_device_match_by_codec(const AVCodec *codec)
function hw_device_setup_for_decode (line 317) | int hw_device_setup_for_decode(InputStream *ist)
function hw_device_setup_for_encode (line 445) | int hw_device_setup_for_encode(OutputStream *ost)
function hwaccel_retrieve_data (line 500) | static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input)
function hwaccel_decode_init (line 542) | int hwaccel_decode_init(AVCodecContext *avctx)
function hw_device_setup_for_filter (line 551) | int hw_device_setup_for_filter(FilterGraph *fg)
FILE: src/fftools/ffmpeg_mux.c
function close_all_output_streams (line 35) | static void close_all_output_streams(OutputStream *ost, OSTFinished this...
function of_write_packet (line 44) | void of_write_packet(OutputFile *of, AVPacket *pkt, OutputStream *ost,
function print_sdp (line 176) | static int print_sdp(void)
function of_check_init (line 230) | int of_check_init(OutputFile *of)
function of_write_trailer (line 281) | int of_write_trailer(OutputFile *of)
function of_close (line 302) | void of_close(OutputFile **pof)
FILE: src/fftools/ffmpeg_opt.c
type VideoSyncMethod (line 161) | enum VideoSyncMethod
function uninit_options (line 193) | static void uninit_options(OptionsContext *o)
function init_options (line 225) | static void init_options(OptionsContext *o)
function show_hwaccels (line 241) | static int show_hwaccels(void *optctx, const char *opt, const char *arg)
function AVDictionary (line 254) | static AVDictionary *strip_specifiers(AVDictionary *dict)
function parse_and_set_vsync (line 271) | static int parse_and_set_vsync(const char *arg, int *vsync_var, int file...
function apply_sync_offsets (line 291) | static int apply_sync_offsets(void)
function opt_filter_threads (line 343) | static int opt_filter_threads(void *optctx, const char *opt, const char ...
function opt_abort_on (line 350) | static int opt_abort_on(void *optctx, const char *opt, const char *arg)
function opt_stats_period (line 369) | static int opt_stats_period(void *optctx, const char *opt, const char *arg)
function opt_audio_codec (line 384) | static int opt_audio_codec(void *optctx, const char *opt, const char *arg)
function opt_video_codec (line 390) | static int opt_video_codec(void *optctx, const char *opt, const char *arg)
function opt_subtitle_codec (line 396) | static int opt_subtitle_codec(void *optctx, const char *opt, const char ...
function opt_data_codec (line 402) | static int opt_data_codec(void *optctx, const char *opt, const char *arg)
function opt_map (line 408) | static int opt_map(void *optctx, const char *opt, const char *arg)
function opt_attach (line 526) | static int opt_attach(void *optctx, const char *opt, const char *arg)
function opt_map_channel (line 534) | static int opt_map_channel(void *optctx, const char *opt, const char *arg)
function opt_sdp_file (line 611) | static int opt_sdp_file(void *optctx, const char *opt, const char *arg)
function opt_vaapi_device (line 619) | static int opt_vaapi_device(void *optctx, const char *opt, const char *arg)
function opt_qsv_device (line 634) | static int opt_qsv_device(void *optctx, const char *opt, const char *arg)
function opt_init_hw_device (line 650) | static int opt_init_hw_device(void *optctx, const char *opt, const char ...
function opt_filter_hw_device (line 665) | static int opt_filter_hw_device(void *optctx, const char *opt, const cha...
function parse_meta_type (line 686) | static void parse_meta_type(char *arg, char *type, int *index, const cha...
function copy_metadata (line 713) | static int copy_metadata(char *outspec, char *inspec, AVFormatContext *o...
function opt_recording_timestamp (line 803) | static int opt_recording_timestamp(void *optctx, const char *opt, const ...
function AVCodec (line 818) | static const AVCodec *find_codec_or_die(const char *name, enum AVMediaTy...
function AVCodec (line 847) | static const AVCodec *choose_decoder(OptionsContext *o, AVFormatContext ...
function add_input_streams (line 864) | static void add_input_streams(OptionsContext *o, AVFormatContext *ic)
function assert_file_overwrite (line 1073) | static void assert_file_overwrite(const char *filename)
function dump_attachment (line 1116) | static void dump_attachment(AVStream *st, const char *filename)
function open_input_file (line 1148) | static int open_input_file(OptionsContext *o, const char *filename)
function get_preset_file_2 (line 1456) | static int get_preset_file_2(const char *preset_name, const char *codec_...
function choose_encoder (line 1486) | static int choose_encoder(OptionsContext *o, AVFormatContext *s, OutputS...
function OutputStream (line 1521) | static OutputStream *new_output_stream(OptionsContext *o, AVFormatContex...
function parse_matrix_coeffs (line 1716) | static void parse_matrix_coeffs(uint16_t *dest, const char *str)
function check_streamcopy_filters (line 1779) | static void check_streamcopy_filters(OptionsContext *o, AVFormatContext ...
function OutputStream (line 1793) | static OutputStream *new_video_stream(OptionsContext *o, AVFormatContext...
function OutputStream (line 2031) | static OutputStream *new_audio_stream(OptionsContext *o, AVFormatContext...
function OutputStream (line 2131) | static OutputStream *new_data_stream(OptionsContext *o, AVFormatContext ...
function OutputStream (line 2144) | static OutputStream *new_unknown_stream(OptionsContext *o, AVFormatConte...
function OutputStream (line 2157) | static OutputStream *new_attachment_stream(OptionsContext *o, AVFormatCo...
function OutputStream (line 2165) | static OutputStream *new_subtitle_stream(OptionsContext *o, AVFormatCont...
function opt_streamid (line 2191) | static int opt_streamid(void *optctx, const char *opt, const char *arg)
function copy_chapters (line 2213) | static int copy_chapters(InputFile *ifile, OutputFile *ofile, AVFormatCo...
function set_dispositions (line 2256) | static int set_dispositions(OutputFile *of, AVFormatContext *ctx)
function init_output_filter (line 2322) | static void init_output_filter(OutputFilter *ofilter, OptionsContext *o,
function init_complex_filters (line 2363) | static int init_complex_filters(void)
function set_channel_layout (line 2375) | static void set_channel_layout(OutputFilter *f, OutputStream *ost)
function open_output_file (line 2412) | static int open_output_file(OptionsContext *o, const char *filename)
function opt_target (line 3049) | static int opt_target(void *optctx, const char *opt, const char *arg)
function opt_vstats_file (line 3192) | static int opt_vstats_file(void *optctx, const char *opt, const char *arg)
function opt_vstats (line 3199) | static int opt_vstats(void *optctx, const char *opt, const char *arg)
function opt_video_frames (line 3215) | static int opt_video_frames(void *optctx, const char *opt, const char *arg)
function opt_audio_frames (line 3221) | static int opt_audio_frames(void *optctx, const char *opt, const char *arg)
function opt_data_frames (line 3227) | static int opt_data_frames(void *optctx, const char *opt, const char *arg)
function opt_default_new (line 3233) | static int opt_default_new(OptionsContext *o, const char *opt, const cha...
function opt_preset (line 3253) | static int opt_preset(void *optctx, const char *opt, const char *arg)
function opt_old2new (line 3301) | static int opt_old2new(void *optctx, const char *opt, const char *arg)
function opt_bitrate (line 3313) | static int opt_bitrate(void *optctx, const char *opt, const char *arg)
function opt_qscale (line 3329) | static int opt_qscale(void *optctx, const char *opt, const char *arg)
function opt_profile (line 3346) | static int opt_profile(void *optctx, const char *opt, const char *arg)
function opt_video_filters (line 3358) | static int opt_video_filters(void *optctx, const char *opt, const char *...
function opt_audio_filters (line 3364) | static int opt_audio_filters(void *optctx, const char *opt, const char *...
function opt_vsync (line 3370) | static int opt_vsync(void *optctx, const char *opt, const char *arg)
function opt_timecode (line 3377) | static int opt_timecode(void *optctx, const char *opt, const char *arg)
function opt_audio_qscale (line 3391) | static int opt_audio_qscale(void *optctx, const char *opt, const char *arg)
function opt_filter_complex (line 3397) | static int opt_filter_complex(void *optctx, const char *opt, const char ...
function opt_filter_complex_script (line 3411) | static int opt_filter_complex_script(void *optctx, const char *opt, cons...
function show_help_default (line 3427) | void show_help_default(const char *opt, const char *arg)
function show_usage (line 3499) | void show_usage(void)
type OptGroup (line 3506) | enum OptGroup {
function open_files (line 3516) | static int open_files(OptionGroupList *l, const char *inout,
function ffmpeg_parse_options (line 3550) | int ffmpeg_parse_options(int argc, char **argv)
function opt_progress (line 3610) | static int opt_progress(void *optctx, const char *opt, const char *arg)
function opt_timelimit (line 3627) | int opt_timelimit(void *optctx, const char *opt, const char *arg)
FILE: src/fftools/ffplay.c
type MyAVPacketList (line 114) | typedef struct MyAVPacketList {
type PacketQueue (line 119) | typedef struct PacketQueue {
type AudioParams (line 135) | typedef struct AudioParams {
type Clock (line 143) | typedef struct Clock {
type Frame (line 154) | typedef struct Frame {
type FrameQueue (line 169) | typedef struct FrameQueue {
type Decoder (line 188) | typedef struct Decoder {
type VideoState (line 203) | typedef struct VideoState {
type ShowMode (line 343) | enum ShowMode
type TextureFormatEntry (line 370) | struct TextureFormatEntry {
function opt_add_vfilter (line 397) | static int opt_add_vfilter(void *optctx, const char *opt, const char *arg)
function cmp_audio_fmts (line 405) | static inline
function packet_queue_put_private (line 416) | static int packet_queue_put_private(PacketQueue *q, AVPacket *pkt)
function packet_queue_put (line 439) | static int packet_queue_put(PacketQueue *q, AVPacket *pkt)
function packet_queue_put_nullpacket (line 461) | static int packet_queue_put_nullpacket(PacketQueue *q, AVPacket *pkt, in...
function packet_queue_init (line 468) | static int packet_queue_init(PacketQueue *q)
function packet_queue_flush (line 488) | static void packet_queue_flush(PacketQueue *q)
function packet_queue_destroy (line 502) | static void packet_queue_destroy(PacketQueue *q)
function packet_queue_abort (line 510) | static void packet_queue_abort(PacketQueue *q)
function packet_queue_start (line 521) | static void packet_queue_start(PacketQueue *q)
function packet_queue_get (line 530) | static int packet_queue_get(PacketQueue *q, AVPacket *pkt, int block, in...
function decoder_init (line 564) | static int decoder_init(Decoder *d, AVCodecContext *avctx, PacketQueue *...
function decoder_decode_frame (line 577) | static int decoder_decode_frame(Decoder *d, AVFrame *frame, AVSubtitle *...
function decoder_destroy (line 666) | static void decoder_destroy(Decoder *d) {
function frame_queue_unref_item (line 671) | static void frame_queue_unref_item(Frame *vp)
function frame_queue_init (line 677) | static int frame_queue_init(FrameQueue *f, PacketQueue *pktq, int max_si...
function frame_queue_destory (line 698) | static void frame_queue_destory(FrameQueue *f)
function frame_queue_signal (line 710) | static void frame_queue_signal(FrameQueue *f)
function Frame (line 717) | static Frame *frame_queue_peek(FrameQueue *f)
function Frame (line 722) | static Frame *frame_queue_peek_next(FrameQueue *f)
function Frame (line 727) | static Frame *frame_queue_peek_last(FrameQueue *f)
function Frame (line 732) | static Frame *frame_queue_peek_writable(FrameQueue *f)
function Frame (line 748) | static Frame *frame_queue_peek_readable(FrameQueue *f)
function frame_queue_push (line 764) | static void frame_queue_push(FrameQueue *f)
function frame_queue_next (line 774) | static void frame_queue_next(FrameQueue *f)
function frame_queue_nb_remaining (line 790) | static int frame_queue_nb_remaining(FrameQueue *f)
function frame_queue_last_pos (line 796) | static int64_t frame_queue_last_pos(FrameQueue *f)
function decoder_abort (line 805) | static void decoder_abort(Decoder *d, FrameQueue *fq)
function fill_rectangle (line 814) | static inline void fill_rectangle(int x, int y, int w, int h)
function realloc_texture (line 825) | static int realloc_texture(SDL_Texture **texture, Uint32 new_format, int...
function calculate_display_rect (line 849) | static void calculate_display_rect(SDL_Rect *rect,
function get_sdl_pix_fmt_and_blendmode (line 876) | static void get_sdl_pix_fmt_and_blendmode(int format, Uint32 *sdl_pix_fm...
function upload_texture (line 894) | static int upload_texture(SDL_Texture **tex, AVFrame *frame, struct SwsC...
function set_sdl_yuv_conversion_mode (line 945) | static void set_sdl_yuv_conversion_mode(AVFrame *frame)
function video_image_display (line 961) | static void video_image_display(VideoState *is)
function compute_mod (line 1046) | static inline int compute_mod(int a, int b)
function video_audio_display (line 1051) | static void video_audio_display(VideoState *s)
function stream_component_close (line 1193) | static void stream_component_close(VideoState *is, int stream_index)
function stream_close (line 1250) | static void stream_close(VideoState *is)
function do_exit (line 1287) | static void do_exit(VideoState *is)
function sigterm_handler (line 1308) | static void sigterm_handler(int sig)
function set_default_window_size (line 1313) | static void set_default_window_size(int width, int height, AVRational sar)
function video_open (line 1325) | static int video_open(VideoState *is)
function video_display (line 1349) | static void video_display(VideoState *is)
function get_clock (line 1363) | static double get_clock(Clock *c)
function set_clock_at (line 1375) | static void set_clock_at(Clock *c, double pts, int serial, double time)
function set_clock (line 1383) | static void set_clock(Clock *c, double pts, int serial)
function set_clock_speed (line 1389) | static void set_clock_speed(Clock *c, double speed)
function init_clock (line 1395) | static void init_clock(Clock *c, int *queue_serial)
function sync_clock_to_slave (line 1403) | static void sync_clock_to_slave(Clock *c, Clock *slave)
function get_master_sync_type (line 1411) | static int get_master_sync_type(VideoState *is) {
function get_master_clock (line 1428) | static double get_master_clock(VideoState *is)
function check_external_clock_speed (line 1446) | static void check_external_clock_speed(VideoState *is) {
function stream_seek (line 1461) | static void stream_seek(VideoState *is, int64_t pos, int64_t rel, int by...
function stream_toggle_pause (line 1475) | static void stream_toggle_pause(VideoState *is)
function toggle_pause (line 1488) | static void toggle_pause(VideoState *is)
function toggle_mute (line 1494) | static void toggle_mute(VideoState *is)
function update_volume (line 1499) | static void update_volume(VideoState *is, int sign, double step)
function step_to_next_frame (line 1506) | static void step_to_next_frame(VideoState *is)
function compute_target_delay (line 1514) | static double compute_target_delay(double delay, VideoState *is)
function vp_duration (line 1544) | static double vp_duration(VideoState *is, Frame *vp, Frame *nextvp) {
function update_video_pts (line 1556) | static void update_video_pts(VideoState *is, double pts, int64_t pos, in...
function video_refresh (line 1563) | static void video_refresh(void *opaque, double *remaining_time)
function queue_picture (line 1732) | static int queue_picture(VideoState *is, AVFrame *src_frame, double pts,...
function get_video_frame (line 1763) | static int get_video_frame(VideoState *is, AVFrame *frame)
function configure_filtergraph (line 1797) | static int configure_filtergraph(AVFilterGraph *graph, const char *filte...
function configure_video_filters (line 1840) | static int configure_video_filters(AVFilterGraph *graph, VideoState *is,...
function configure_audio_filters (line 1945) | static int configure_audio_filters(VideoState *is, const char *afilters,...
function audio_thread (line 2020) | static int audio_thread(void *arg)
function decoder_start (line 2105) | static int decoder_start(Decoder *d, int (*fn)(void *), const char *thre...
type AVPixelFormat (line 2131) | enum AVPixelFormat
function subtitle_thread (line 2223) | static int subtitle_thread(void *arg)
function update_sample_display (line 2258) | static void update_sample_display(VideoState *is, short *samples, int sa...
function synchronize_audio (line 2278) | static int synchronize_audio(VideoState *is, int nb_samples)
function audio_decode_frame (line 2326) | static int audio_decode_frame(VideoState *is)
function sdl_audio_callback (line 2435) | static void sdl_audio_callback(void *opaque, Uint8 *stream, int len)
function audio_open (line 2478) | static int audio_open(void *opaque, AVChannelLayout *wanted_channel_layo...
function stream_component_open (line 2555) | static int stream_component_open(VideoState *is, int stream_index)
function decode_interrupt_cb (line 2712) | static int decode_interrupt_cb(void *ctx)
function stream_has_enough_packets (line 2718) | static int stream_has_enough_packets(AVStream *st, int stream_id, Packet...
function is_realtime (line 2725) | static int is_realtime(AVFormatContext *s)
function read_thread (line 2742) | static int read_thread(void *arg)
function VideoState (line 3067) | static VideoState *stream_open(const char *filename,
function stream_cycle_channel (line 3126) | static void stream_cycle_channel(VideoState *is, int codec_type)
function toggle_full_screen (line 3205) | static void toggle_full_screen(VideoState *is)
function toggle_audio_display (line 3211) | static void toggle_audio_display(VideoState *is)
function refresh_loop_wait_event (line 3223) | static void refresh_loop_wait_event(VideoState *is, SDL_Event *event) {
function seek_chapter (line 3240) | static void seek_chapter(VideoState *is, int incr)
function event_loop (line 3268) | static void event_loop(VideoState *cur_stream)
function opt_width (line 3467) | static int opt_width(void *optctx, const char *opt, const char *arg)
function opt_height (line 3473) | static int opt_height(void *optctx, const char *opt, const char *arg)
function opt_format (line 3479) | static int opt_format(void *optctx, const char *opt, const char *arg)
function opt_sync (line 3489) | static int opt_sync(void *optctx, const char *opt, const char *arg)
function opt_seek (line 3504) | static int opt_seek(void *optctx, const char *opt, const char *arg)
function opt_duration (line 3510) | static int opt_duration(void *optctx, const char *opt, const char *arg)
function opt_show_mode (line 3516) | static int opt_show_mode(void *optctx, const char *opt, const char *arg)
function opt_input_file (line 3525) | static void opt_input_file(void *optctx, const char *filename)
function opt_codec (line 3538) | static int opt_codec(void *optctx, const char *opt, const char *arg)
function show_usage (line 3615) | static void show_usage(void)
function show_help_default (line 3622) | void show_help_default(const char *opt, const char *arg)
function ffplay (line 3658) | int ffplay(int argc, char **argv)
FILE: src/fftools/ffprobe.c
type InputStream (line 80) | typedef struct InputStream {
type InputFile (line 86) | typedef struct InputFile {
type ReadInterval (line 139) | typedef struct ReadInterval {
type section (line 156) | struct section {
type SectionID (line 172) | typedef enum {
type section (line 224) | struct section
type AVHashContext (line 286) | struct AVHashContext
type LogBuffer (line 315) | typedef struct LogBuffer {
function log_callback (line 327) | static void log_callback(void *ptr, int level, const char *fmt, va_list vl)
function ffprobe_cleanup (line 376) | static void ffprobe_cleanup(int ret)
type unit_value (line 439) | struct unit_value {
type unit_value (line 444) | struct unit_value
type WriterContext (line 499) | typedef struct WriterContext WriterContext;
type StringValidation (line 504) | typedef enum {
type Writer (line 511) | typedef struct Writer {
type WriterContext (line 529) | struct WriterContext {
function writer_close (line 600) | static int writer_close(WriterContext **wctx)
function bprint_bytes (line 624) | static void bprint_bytes(AVBPrint *bp, const uint8_t *ubuf, size_t ubuf_...
function writer_w8_avio (line 632) | static inline void writer_w8_avio(WriterContext *wctx, int b)
function writer_put_str_avio (line 637) | static inline void writer_put_str_avio(WriterContext *wctx, const char *...
function writer_printf_avio (line 642) | static inline void writer_printf_avio(WriterContext *wctx, const char *f...
function writer_w8_printf (line 651) | static inline void writer_w8_printf(WriterContext *wctx, int b)
function writer_put_str_printf (line 656) | static inline void writer_put_str_printf(WriterContext *wctx, const char...
function writer_printf_printf (line 661) | static inline void writer_printf_printf(WriterContext *wctx, const char ...
function writer_open (line 670) | static int writer_open(WriterContext **wctx, const Writer *writer, const...
function writer_print_section_header (line 772) | static inline void writer_print_section_header(WriterContext *wctx,
function writer_print_section_footer (line 796) | static inline void writer_print_section_footer(WriterContext *wctx)
function writer_print_integer (line 813) | static inline void writer_print_integer(WriterContext *wctx,
function validate_string (line 824) | static inline int validate_string(WriterContext *wctx, char **dstp, cons...
function writer_print_string (line 882) | static inline int writer_print_string(WriterContext *wctx,
function writer_print_rational (line 920) | static inline void writer_print_rational(WriterContext *wctx,
function writer_print_time (line 929) | static void writer_print_time(WriterContext *wctx, const char *key,
function writer_print_ts (line 946) | static void writer_print_ts(WriterContext *wctx, const char *key, int64_...
function writer_print_data (line 955) | static void writer_print_data(WriterContext *wctx, const char *name,
function writer_print_data_hash (line 983) | static void writer_print_data_hash(WriterContext *wctx, const char *name,
function writer_print_integers (line 998) | static void writer_print_integers(WriterContext *wctx, const char *name,
function writer_register (line 1032) | static int writer_register(const Writer *writer)
function Writer (line 1043) | static const Writer *writer_get_by_name(const char *name)
type DefaultContext (line 1070) | typedef struct DefaultContext {
function default_print_section_header (line 1100) | static void default_print_section_header(WriterContext *wctx)
function default_print_section_footer (line 1125) | static void default_print_section_footer(WriterContext *wctx)
function default_print_str (line 1138) | static void default_print_str(WriterContext *wctx, const char *key, cons...
function default_print_int (line 1147) | static void default_print_int(WriterContext *wctx, const char *key, long...
type CompactContext (line 1218) | typedef struct CompactContext {
function av_cold (line 1248) | static av_cold int compact_init(WriterContext *wctx)
function compact_print_section_header (line 1270) | static void compact_print_section_header(WriterContext *wctx)
function compact_print_section_footer (line 1302) | static void compact_print_section_footer(WriterContext *wctx)
function compact_print_str (line 1312) | static void compact_print_str(WriterContext *wctx, const char *key, cons...
function compact_print_int (line 1325) | static void compact_print_int(WriterContext *wctx, const char *key, long...
type FlatContext (line 1380) | typedef struct FlatContext {
function av_cold (line 1400) | static av_cold int flat_init(WriterContext *wctx)
function flat_print_section_header (line 1447) | static void flat_print_section_header(WriterContext *wctx)
function flat_print_int (line 1473) | static void flat_print_int(WriterContext *wctx, const char *key, long lo...
function flat_print_str (line 1478) | static void flat_print_str(WriterContext *wctx, const char *key, const c...
type INIContext (line 1504) | typedef struct INIContext {
function ini_print_section_header (line 1547) | static void ini_print_section_header(WriterContext *wctx)
function ini_print_str (line 1580) | static void ini_print_str(WriterContext *wctx, const char *key, const ch...
function ini_print_int (line 1591) | static void ini_print_int(WriterContext *wctx, const char *key, long lon...
type JSONContext (line 1608) | typedef struct JSONContext {
function av_cold (line 1626) | static av_cold int json_init(WriterContext *wctx)
function json_print_section_header (line 1658) | static void json_print_section_header(WriterContext *wctx)
function json_print_section_footer (line 1697) | static void json_print_section_footer(WriterContext *wctx)
function json_print_item_str (line 1719) | static inline void json_print_item_str(WriterContext *wctx,
function json_print_str (line 1731) | static void json_print_str(WriterContext *wctx, const char *key, const c...
function json_print_int (line 1744) | static void json_print_int(WriterContext *wctx, const char *key, long lo...
type XMLContext (line 1775) | typedef struct XMLContext {
function av_cold (line 1796) | static av_cold int xml_init(WriterContext *wctx)
function xml_print_section_header (line 1819) | static void xml_print_section_header(WriterContext *wctx)
function xml_print_section_footer (line 1859) | static void xml_print_section_footer(WriterContext *wctx)
function xml_print_str (line 1878) | static void xml_print_str(WriterContext *wctx, const char *key, const ch...
function xml_print_int (line 1909) | static void xml_print_int(WriterContext *wctx, const char *key, long lon...
function writer_register_all (line 1928) | static void writer_register_all(void)
function show_tags (line 1988) | static inline int show_tags(WriterContext *w, AVDictionary *tags, int se...
function print_dovi_metadata (line 2006) | static void print_dovi_metadata(WriterContext *w, const AVDOVIMetadata *...
function print_dynamic_hdr10_plus (line 2153) | static void print_dynamic_hdr10_plus(WriterContext *w, const AVDynamicHD...
function print_dynamic_hdr_vivid (line 2252) | static void print_dynamic_hdr_vivid(WriterContext *w, const AVDynamicHDR...
function print_pkt_side_data (line 2320) | static void print_pkt_side_data(WriterContext *w,
function print_color_range (line 2424) | static void print_color_range(WriterContext *w, enum AVColorRange color_...
function print_color_space (line 2434) | static void print_color_space(WriterContext *w, enum AVColorSpace color_...
function print_primaries (line 2444) | static void print_primaries(WriterContext *w, enum AVColorPrimaries colo...
function print_color_trc (line 2454) | static void print_color_trc(WriterContext *w, enum AVColorTransferCharac...
function print_chroma_location (line 2464) | static void print_chroma_location(WriterContext *w, enum AVChromaLocatio...
function clear_log (line 2475) | static void clear_log(int need_lock)
function show_log (line 2491) | static int show_log(WriterContext *w, int section_ids, int section_id, i...
function show_packet (line 2526) | static void show_packet(WriterContext *w, InputFile *ifile, AVPacket *pk...
function show_subtitle (line 2579) | static void show_subtitle(WriterContext *w, AVSubtitle *sub, AVStream *s...
function show_frame (line 2602) | static void show_frame(WriterContext *w, AVFrame *frame, AVStream *stream,
function av_always_inline (line 2756) | static av_always_inline int process_frame(WriterContext *w,
function log_read_interval (line 2819) | static void log_read_interval(const ReadInterval *interval, void *log_ct...
function read_interval_packets (line 2843) | static int read_interval_packets(WriterContext *w, InputFile *ifile,
function read_packets (line 2954) | static int read_packets(WriterContext *w, InputFile *ifile)
function show_stream (line 2974) | static int show_stream(WriterContext *w, AVFormatContext *fmt_ctx, int s...
function show_streams (line 3195) | static int show_streams(WriterContext *w, InputFile *ifile)
function show_program (line 3212) | static int show_program(WriterContext *w, InputFile *ifile, AVProgram *p...
function show_programs (line 3243) | static int show_programs(WriterContext *w, InputFile *ifile)
function show_chapters (line 3261) | static int show_chapters(WriterContext *w, InputFile *ifile)
function show_format (line 3286) | static int show_format(WriterContext *w, InputFile *ifile)
function show_error (line 3317) | static void show_error(WriterContext *w, int err)
function open_input_file (line 3331) | static int open_input_file(InputFile *ifile, const char *filename,
function close_input_file (line 3448) | static void close_input_file(InputFile *ifile)
function probe_file (line 3462) | static int probe_file(WriterContext *wctx, const char *filename,
function show_usage (line 3543) | static void show_usage(void)
function ffprobe_show_program_version (line 3550) | static void ffprobe_show_program_version(WriterContext *w)
function ffprobe_show_library_versions (line 3581) | static void ffprobe_show_library_versions(WriterContext *w)
function ffprobe_show_pixel_formats (line 3600) | static void ffprobe_show_pixel_formats(WriterContext *w)
function opt_show_optional_fields (line 3646) | static int opt_show_optional_fields(void *optctx, const char *opt, const...
function opt_format (line 3657) | static int opt_format(void *optctx, const char *opt, const char *arg)
function mark_section_show_entries (line 3667) | static inline void mark_section_show_entries(SectionID section_id,
function match_section (line 3682) | static int match_section(const char *section_name,
function opt_show_entries (line 3701) | static int opt_show_entries(void *optctx, const char *opt, const char *arg)
function opt_input_file (line 3751) | static void opt_input_file(void *optctx, const char *arg)
function opt_input_file_i (line 3764) | static int opt_input_file_i(void *optctx, const char *opt, const char *arg)
function opt_output_file (line 3770) | static void opt_output_file(void *optctx, const char *arg)
function opt_output_file_o (line 3783) | static int opt_output_file_o(void *optctx, const char *opt, const char *...
function opt_print_filename (line 3789) | static int opt_print_filename(void *optctx, const char *opt, const char ...
function show_help_default_ffprobe (line 3795) | void show_help_default_ffprobe(const char *opt, const char *arg)
function parse_read_interval (line 3811) | static int parse_read_interval(const char *interval_spec,
function parse_read_intervals (line 3893) | static int parse_read_intervals(const char *intervals_spec)
function opt_read_intervals (line 3941) | static int opt_read_intervals(void *optctx, const char *opt, const char ...
function opt_pretty (line 3946) | static int opt_pretty(void *optctx, const char *opt, const char *arg)
function print_section (line 3955) | static void print_section(SectionID id, int level)
function opt_sections (line 3972) | static int opt_sections(void *optctx, const char *opt, const char *arg)
function opt_show_versions (line 3984) | static int opt_show_versions(void *optctx, const char *opt, const char *...
function check_section_show_entries (line 4058) | static inline int check_section_show_entries(int section_id)
function ffprobe (line 4075) | int ffprobe(int argc, char **argv)
FILE: src/fftools/fopen_utf8.h
function FILE (line 32) | static inline FILE *fopen_utf8(const char *path_utf8, const char *mode)
function FILE (line 65) | static inline FILE *fopen_utf8(const char *path, const char *mode)
FILE: src/fftools/opt_common.c
type show_muxdemuxers (line 66) | enum show_muxdemuxers {
function show_license (line 75) | int show_license(void *optctx, const char *opt, const char *arg)
function print_all_libs_info (line 185) | static void print_all_libs_info(int flags, int level)
function print_program_info (line 197) | static void print_program_info(int flags, int level)
function print_buildconf (line 211) | static void print_buildconf(int flags, int level)
function show_banner (line 237) | void show_banner(int argc, char **argv, const OptionDef *options)
function show_version (line 248) | int show_version(void *optctx, const char *opt, const char *arg)
function show_buildconf (line 257) | int show_buildconf(void *optctx, const char *opt, const char *arg)
function print_codec (line 278) | static void print_codec(const AVCodec *c)
function AVCodec (line 382) | static const AVCodec *next_codec_for_id(enum AVCodecID id, void **iter,
function show_help_codec (line 394) | static void show_help_codec(const char *name, int encoder)
function show_help_demuxer (line 430) | static void show_help_demuxer(const char *name)
function show_help_protocol (line 448) | static void show_help_protocol(const char *name)
function show_help_muxer (line 466) | static void show_help_muxer(const char *name)
function show_help_filter (line 500) | static void show_help_filter(const char *name)
function show_help_bsf (line 555) | static void show_help_bsf(const char *name)
function show_help (line 574) | int show_help(void *optctx, const char *opt, const char *arg)
function print_codecs_for_id (line 612) | static void print_codecs_for_id(enum AVCodecID id, int encoder)
function compare_codec_desc (line 625) | static int compare_codec_desc(const void *a, const void *b)
function get_codecs_sorted (line 634) | static unsigned get_codecs_sorted(const AVCodecDescriptor ***rcodecs)
function get_media_type_char (line 655) | static char get_media_type_char(enum AVMediaType type)
function show_codecs (line 667) | int show_codecs(void *optctx, const char *opt, const char *arg)
function print_codecs (line 725) | static void print_codecs(int encoder)
function show_decoders (line 764) | int show_decoders(void *optctx, const char *opt, const char *arg)
function show_encoders (line 770) | int show_encoders(void *optctx, const char *opt, const char *arg)
function show_bsfs (line 776) | int show_bsfs(void *optctx, const char *opt, const char *arg)
function show_filters (line 788) | int show_filters(void *optctx, const char *opt, const char *arg)
function is_device (line 837) | static int is_device(const AVClass *avclass)
function show_formats_devices (line 844) | static int show_formats_devices(void *optctx, const char *opt, const cha...
function show_formats (line 907) | int show_formats(void *optctx, const char *opt, const char *arg)
function show_muxers (line 912) | int show_muxers(void *optctx, const char *opt, const char *arg)
function show_demuxers (line 917) | int show_demuxers(void *optctx, const char *opt, const char *arg)
function show_devices (line 922) | int show_devices(void *optctx, const char *opt, const char *arg)
function show_protocols (line 927) | int show_protocols(void *optctx, const char *opt, const char *arg)
function show_colors (line 942) | int show_colors(void *optctx, const char *opt, const char *arg)
function show_pix_fmts (line 956) | int show_pix_fmts(void *optctx, const char *opt, const char *arg)
function show_layouts (line 994) | int show_layouts(void *optctx, const char *opt, const char *arg)
function show_sample_fmts (line 1027) | int show_sample_fmts(void *optctx, const char *opt, const char *arg)
function show_dispositions (line 1036) | int show_dispositions(void *optctx, const char *opt, const char *arg)
function opt_cpuflags (line 1046) | int opt_cpuflags(void *optctx, const char *opt, const char *arg)
function opt_cpucount (line 1058) | int opt_cpucount(void *optctx, const char *opt, const char *arg)
function expand_filename_template (line 1084) | static void expand_filename_template(AVBPrint *bp, const char *template,
function log_callback_report (line 1112) | static void log_callback_report(void *ptr, int level, const char *fmt, v...
function init_report (line 1128) | int init_report(const char *env, FILE **file)
function opt_report (line 1210) | int opt_report(void *optctx, const char *opt, const char *arg)
function opt_max_alloc (line 1215) | int opt_max_alloc(void *optctx, const char *opt, const char *arg)
function opt_loglevel (line 1229) | int opt_loglevel(void *optctx, const char *opt, const char *arg)
function print_device_list (line 1307) | static void print_device_list(const AVDeviceInfoList *device_list)
function print_device_sources (line 1328) | static int print_device_sources(const AVInputFormat *fmt, AVDictionary *...
function print_device_sinks (line 1349) | static int print_device_sinks(const AVOutputFormat *fmt, AVDictionary *o...
function show_sinks_sources_parse_arg (line 1370) | static int show_sinks_sources_parse_arg(const char *arg, char **dev, AVD...
function show_sources (line 1392) | int show_sources(void *optctx, const char *opt, const char *arg)
function show_sinks (line 1430) | int show_sinks(void *optctx, const char *opt, const char *arg)
FILE: tests/test-helper-browser.js
constant VIDEO_1S_MP4 (line 1) | const VIDEO_1S_MP4 =
Condensed preview — 265 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (1,195K chars).
[
{
"path": ".gitattributes",
"chars": 29,
"preview": ". !text !filter !merge !diff\n"
},
{
"path": ".github/FUNDING.yml",
"chars": 534,
"preview": "# These are supported funding model platforms\n\ngithub: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [u"
},
{
"path": ".github/ISSUE_TEMPLATE/bug_report.md",
"chars": 775,
"preview": "---\nname: Bug report\nabout: Create a report to help us improve\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Describe the b"
},
{
"path": ".github/ISSUE_TEMPLATE/feature_request.md",
"chars": 595,
"preview": "---\nname: Feature request\nabout: Suggest an idea for this project\ntitle: ''\nlabels: ''\nassignees: ''\n\n---\n\n**Is your fea"
},
{
"path": ".github/SECURITY.md",
"chars": 193,
"preview": "## Security contact information\n\nTo report a security vulnerability, please use the\n[Tidelift security contact](https://"
},
{
"path": ".github/workflows/CI.yml",
"chars": 6597,
"preview": "name: CI\n\non:\n push:\n branches:\n - main\n pull_request:\n branches:\n - main\n\njobs:\n build-core:\n run"
},
{
"path": ".gitignore",
"chars": 88,
"preview": "node_modules\ndist\n/.nyc_output\n.DS_Store\n\n# ide\n.idea/\n\n# Local Netlify folder\n.netlify\n"
},
{
"path": ".gitmodules",
"chars": 86,
"preview": "[submodule \"testdata\"]\n\tpath = testdata\n\turl = https://github.com/ffmpegwasm/testdata\n"
},
{
"path": "CODE_OF_CONDUCT.md",
"chars": 3351,
"preview": "# Contributor Covenant Code of Conduct\n\n## Our Pledge\n\nIn the interest of fostering an open and welcoming environment, w"
},
{
"path": "CONTRIBUTING.md",
"chars": 60,
"preview": "Check https://ffmpegwasm.netlify.app/docs/contribution/core\n"
},
{
"path": "Dockerfile",
"chars": 6329,
"preview": "# syntax=docker/dockerfile-upstream:master-labs\n\n# Base emsdk image with environment variables.\nFROM emscripten/emsdk:3."
},
{
"path": "LICENSE",
"chars": 1066,
"preview": "MIT License\n\nCopyright (c) 2019 Jerome Wu\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\n"
},
{
"path": "Makefile",
"chars": 1022,
"preview": "all: dev\n\nMT_FLAGS := -sUSE_PTHREADS -pthread\n\nDEV_ARGS := --progress=plain\n\nDEV_CFLAGS := --profiling\nDEV_MT_CFLAGS := "
},
{
"path": "README.md",
"chars": 2002,
"preview": "---\n<p align=\"center\">\n <a href=\"#\">\n <img alt=\"ffmpeg.wasm\" width=\"128px\" height=\"128px\" src=\"https://github.com/ff"
},
{
"path": "apps/angular-app/.editorconfig",
"chars": 274,
"preview": "# Editor configuration, see https://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size ="
},
{
"path": "apps/angular-app/.gitignore",
"chars": 548,
"preview": "# See http://help.github.com/ignore-files/ for more about ignoring files.\n\n# Compiled output\n/dist\n/tmp\n/out-tsc\n/bazel-"
},
{
"path": "apps/angular-app/.vscode/extensions.json",
"chars": 130,
"preview": "{\n // For more information, visit: https://go.microsoft.com/fwlink/?linkid=827846\n \"recommendations\": [\"angular.ng-tem"
},
{
"path": "apps/angular-app/.vscode/launch.json",
"chars": 470,
"preview": "{\n // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387\n \"version\": \"0.2.0\",\n \"configuratio"
},
{
"path": "apps/angular-app/.vscode/tasks.json",
"chars": 938,
"preview": "{\n // For more information, visit: https://go.microsoft.com/fwlink/?LinkId=733558\n \"version\": \"2.0.0\",\n \"tasks\": [\n "
},
{
"path": "apps/angular-app/README.md",
"chars": 1064,
"preview": "# AngularApp\n\nThis project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 17.0.7.\n\n## "
},
{
"path": "apps/angular-app/angular.json",
"chars": 2617,
"preview": "{\n \"$schema\": \"./node_modules/@angular/cli/lib/config/schema.json\",\n \"version\": 1,\n \"newProjectRoot\": \"projects\",\n \""
},
{
"path": "apps/angular-app/package.json",
"chars": 1094,
"preview": "{\n \"name\": \"angular-app\",\n \"version\": \"0.0.0\",\n \"scripts\": {\n \"ng\": \"ng\",\n \"start\": \"ng serve\",\n \"build\": \"n"
},
{
"path": "apps/angular-app/src/app/app.component.css",
"chars": 0,
"preview": ""
},
{
"path": "apps/angular-app/src/app/app.component.html",
"chars": 3411,
"preview": "<!-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * -->\n<!-- * * * * * * * * * * * The content below * * "
},
{
"path": "apps/angular-app/src/app/app.component.spec.ts",
"chars": 931,
"preview": "import { TestBed } from '@angular/core/testing';\nimport { AppComponent } from './app.component';\n\ndescribe('AppComponent"
},
{
"path": "apps/angular-app/src/app/app.component.ts",
"chars": 1554,
"preview": "import { Component } from '@angular/core';\nimport { CommonModule } from '@angular/common';\nimport { RouterOutlet } from "
},
{
"path": "apps/angular-app/src/app/app.config.ts",
"chars": 227,
"preview": "import { ApplicationConfig } from '@angular/core';\nimport { provideRouter } from '@angular/router';\n\nimport { routes } f"
},
{
"path": "apps/angular-app/src/app/app.routes.ts",
"chars": 77,
"preview": "import { Routes } from '@angular/router';\n\nexport const routes: Routes = [];\n"
},
{
"path": "apps/angular-app/src/assets/.gitkeep",
"chars": 0,
"preview": ""
},
{
"path": "apps/angular-app/src/index.html",
"chars": 296,
"preview": "<!doctype html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <title>AngularApp</title>\n <base href=\"/\">\n <meta n"
},
{
"path": "apps/angular-app/src/main.ts",
"chars": 250,
"preview": "import { bootstrapApplication } from '@angular/platform-browser';\nimport { appConfig } from './app/app.config';\nimport {"
},
{
"path": "apps/angular-app/src/styles.css",
"chars": 80,
"preview": "/* You can add global styles to this file, and also import other style files */\n"
},
{
"path": "apps/angular-app/tsconfig.app.json",
"chars": 263,
"preview": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n \"extends\": \"./tsconfig.json\",\n \"compil"
},
{
"path": "apps/angular-app/tsconfig.json",
"chars": 903,
"preview": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n \"compileOnSave\": false,\n \"compilerOpti"
},
{
"path": "apps/angular-app/tsconfig.spec.json",
"chars": 273,
"preview": "/* To learn more about this file see: https://angular.io/config/tsconfig. */\n{\n \"extends\": \"./tsconfig.json\",\n \"compil"
},
{
"path": "apps/nextjs-app/.eslintrc.json",
"chars": 40,
"preview": "{\n \"extends\": \"next/core-web-vitals\"\n}\n"
},
{
"path": "apps/nextjs-app/.gitignore",
"chars": 368,
"preview": "# See https://help.github.com/articles/ignoring-files/ for more about ignoring files.\n\n# dependencies\n/node_modules\n/.pn"
},
{
"path": "apps/nextjs-app/README.md",
"chars": 1370,
"preview": "This is a [Next.js](https://nextjs.org/) project bootstrapped with [`create-next-app`](https://github.com/vercel/next.js"
},
{
"path": "apps/nextjs-app/app/Home.tsx",
"chars": 3071,
"preview": "\"use client\";\n\nimport { FFmpeg } from \"@ffmpeg/ffmpeg\";\nimport { fetchFile, toBlobURL } from \"@ffmpeg/util\";\nimport { us"
},
{
"path": "apps/nextjs-app/app/NoSSRWrapper.tsx",
"chars": 235,
"preview": "import dynamic from 'next/dynamic'\nimport React from 'react' \nconst NoSSRWrapper = props => ( \n <React.Fragment>{prop"
},
{
"path": "apps/nextjs-app/app/globals.css",
"chars": 60,
"preview": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n"
},
{
"path": "apps/nextjs-app/app/layout.tsx",
"chars": 456,
"preview": "import './globals.css'\nimport type { Metadata } from 'next'\nimport { Inter } from 'next/font/google'\n\nconst inter = Inte"
},
{
"path": "apps/nextjs-app/app/page.tsx",
"chars": 167,
"preview": "'use client'\n\nimport NoSSRWrapper from \"./NoSSRWrapper\";\nimport Home from \"./Home\";\n\nexport default function Page() {\n "
},
{
"path": "apps/nextjs-app/next.config.js",
"chars": 92,
"preview": "/** @type {import('next').NextConfig} */\nconst nextConfig = {}\n\nmodule.exports = nextConfig\n"
},
{
"path": "apps/nextjs-app/package.json",
"chars": 615,
"preview": "{\n \"name\": \"nextjs-ffmpeg-starter\",\n \"version\": \"0.1.0\",\n \"private\": true,\n \"scripts\": {\n \"dev\": \"next dev\",\n "
},
{
"path": "apps/nextjs-app/postcss.config.js",
"chars": 82,
"preview": "module.exports = {\n plugins: {\n tailwindcss: {},\n autoprefixer: {},\n },\n}\n"
},
{
"path": "apps/nextjs-app/tailwind.config.ts",
"chars": 495,
"preview": "import type { Config } from 'tailwindcss'\n\nconst config: Config = {\n content: [\n './pages/**/*.{js,ts,jsx,tsx,mdx}',"
},
{
"path": "apps/nextjs-app/tsconfig.json",
"chars": 641,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"es5\",\n \"lib\": [\"dom\", \"dom.iterable\", \"esnext\"],\n \"allowJs\": true,\n \"sk"
},
{
"path": "apps/react-vite-app/.eslintrc.cjs",
"chars": 436,
"preview": "module.exports = {\n root: true,\n env: { browser: true, es2020: true },\n extends: [\n 'eslint:recommended',\n 'plu"
},
{
"path": "apps/react-vite-app/.gitignore",
"chars": 253,
"preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\ndist\ndis"
},
{
"path": "apps/react-vite-app/README.md",
"chars": 1263,
"preview": "# React + TypeScript + Vite\n\nThis template provides a minimal setup to get React working in Vite with HMR and some ESLin"
},
{
"path": "apps/react-vite-app/index.html",
"chars": 366,
"preview": "<!doctype html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\" />\n <link rel=\"icon\" type=\"image/svg+xml\" href=\"/"
},
{
"path": "apps/react-vite-app/package.json",
"chars": 800,
"preview": "{\n \"name\": \"react-vite-app\",\n \"private\": true,\n \"version\": \"0.0.0\",\n \"type\": \"module\",\n \"scripts\": {\n \"dev\": \"vi"
},
{
"path": "apps/react-vite-app/src/App.tsx",
"chars": 1948,
"preview": "import { useState, useRef } from \"react\";\nimport { FFmpeg } from \"@ffmpeg/ffmpeg\";\nimport { toBlobURL, fetchFile } from "
},
{
"path": "apps/react-vite-app/src/index.css",
"chars": 1222,
"preview": ":root {\n font-family: Inter, system-ui, Avenir, Helvetica, Arial, sans-serif;\n line-height: 1.5;\n font-weight: 400;\n\n"
},
{
"path": "apps/react-vite-app/src/main.tsx",
"chars": 236,
"preview": "import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport App from './App.tsx'\nimport './index.css'\n\nReac"
},
{
"path": "apps/react-vite-app/src/vite-env.d.ts",
"chars": 38,
"preview": "/// <reference types=\"vite/client\" />\n"
},
{
"path": "apps/react-vite-app/tsconfig.json",
"chars": 605,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"ES2020\",\n \"useDefineForClassFields\": true,\n \"lib\": [\"ES2020\", \"DOM\", \"DOM."
},
{
"path": "apps/react-vite-app/tsconfig.node.json",
"chars": 213,
"preview": "{\n \"compilerOptions\": {\n \"composite\": true,\n \"skipLibCheck\": true,\n \"module\": \"ESNext\",\n \"moduleResolution\""
},
{
"path": "apps/react-vite-app/vite.config.ts",
"chars": 382,
"preview": "import { defineConfig } from \"vite\";\nimport react from \"@vitejs/plugin-react\";\n\n// https://vitejs.dev/config/\nexport def"
},
{
"path": "apps/solidstart-app/.gitignore",
"chars": 228,
"preview": "\ndist\n.solid\n.output\n.vercel\n.netlify\n.vinxi\n\n# Environment\n.env\n.env*.local\n\n# dependencies\n/node_modules\n\n# IDEs and e"
},
{
"path": "apps/solidstart-app/README.md",
"chars": 948,
"preview": "# SolidStart\n\nEverything you need to build a Solid project, powered by [`solid-start`](https://start.solidjs.com);\n\n## C"
},
{
"path": "apps/solidstart-app/app.config.ts",
"chars": 257,
"preview": "import { defineConfig } from \"@solidjs/start/config\";\n\nexport default defineConfig({\n ssr: false,\n server: {\n "
},
{
"path": "apps/solidstart-app/package.json",
"chars": 450,
"preview": "{\n\t\"name\": \"solidstart-ffmpeg\",\n\t\"type\": \"module\",\n\t\"scripts\": {\n\t\t\"dev\": \"vinxi dev\",\n\t\t\"build\": \"vinxi build\",\n\t\t\"star"
},
{
"path": "apps/solidstart-app/postcss.config.cjs",
"chars": 82,
"preview": "module.exports = {\n plugins: {\n tailwindcss: {},\n autoprefixer: {},\n },\n}\n"
},
{
"path": "apps/solidstart-app/src/app.css",
"chars": 346,
"preview": "@tailwind base;\n@tailwind components;\n@tailwind utilities;\n\n:root {\n --background-rgb: 214, 219, 220;\n --foreground-rg"
},
{
"path": "apps/solidstart-app/src/app.tsx",
"chars": 355,
"preview": "import { Router } from '@solidjs/router';\nimport { FileRoutes } from '@solidjs/start/router';\nimport { Suspense } from '"
},
{
"path": "apps/solidstart-app/src/entry-client.tsx",
"chars": 143,
"preview": "// @refresh reload\nimport { mount, StartClient } from \"@solidjs/start/client\";\n\nmount(() => <StartClient />, document.ge"
},
{
"path": "apps/solidstart-app/src/entry-server.tsx",
"chars": 841,
"preview": "// @refresh reload\nimport { createHandler, StartServer } from '@solidjs/start/server';\nimport { HttpHeader, HttpStatusCo"
},
{
"path": "apps/solidstart-app/src/global.d.ts",
"chars": 45,
"preview": "/// <reference types=\"@solidjs/start/env\" />\n"
},
{
"path": "apps/solidstart-app/src/routes/index.tsx",
"chars": 3147,
"preview": "import { FFmpeg } from '@ffmpeg/ffmpeg';\nimport { fetchFile, toBlobURL } from '@ffmpeg/util';\nimport { createSignal, Sho"
},
{
"path": "apps/solidstart-app/tailwind.config.cjs",
"chars": 159,
"preview": "/** @type {import('tailwindcss').Config} */\nmodule.exports = {\n content: [\"./src/**/*.{html,js,jsx,ts,tsx}\"],\n theme: "
},
{
"path": "apps/solidstart-app/tsconfig.json",
"chars": 416,
"preview": "{\n \"compilerOptions\": {\n \"target\": \"ESNext\",\n \"module\": \"ESNext\",\n \"moduleResolution\": \"bundler\",\n \"allowSy"
},
{
"path": "apps/sveltekit-app/.eslintignore",
"chars": 160,
"preview": ".DS_Store\nnode_modules\n/build\n/.svelte-kit\n/package\n.env\n.env.*\n!.env.example\n\n# Ignore files for PNPM, NPM and YARN\npnp"
},
{
"path": "apps/sveltekit-app/.eslintrc.cjs",
"chars": 591,
"preview": "/** @type { import(\"eslint\").Linter.Config } */\nmodule.exports = {\n\troot: true,\n\textends: [\n\t\t'eslint:recommended',\n\t\t'p"
},
{
"path": "apps/sveltekit-app/.gitignore",
"chars": 132,
"preview": ".DS_Store\nnode_modules\n/build\n/.svelte-kit\n/package\n.env\n.env.*\n!.env.example\nvite.config.js.timestamp-*\nvite.config.ts."
},
{
"path": "apps/sveltekit-app/.npmrc",
"chars": 19,
"preview": "engine-strict=true\n"
},
{
"path": "apps/sveltekit-app/.prettierignore",
"chars": 81,
"preview": "# Ignore files for PNPM, NPM and YARN\npnpm-lock.yaml\npackage-lock.json\nyarn.lock\n"
},
{
"path": "apps/sveltekit-app/.prettierrc",
"chars": 205,
"preview": "{\n\t\"useTabs\": true,\n\t\"singleQuote\": true,\n\t\"trailingComma\": \"none\",\n\t\"printWidth\": 100,\n\t\"plugins\": [\"prettier-plugin-sv"
},
{
"path": "apps/sveltekit-app/README.md",
"chars": 942,
"preview": "# create-svelte\n\nEverything you need to build a Svelte project, powered by [`create-svelte`](https://github.com/sveltejs"
},
{
"path": "apps/sveltekit-app/package.json",
"chars": 1212,
"preview": "{\n\t\"name\": \"sveltekit-app\",\n\t\"version\": \"0.0.1\",\n\t\"private\": true,\n\t\"scripts\": {\n\t\t\"dev\": \"vite dev\",\n\t\t\"build\": \"vite b"
},
{
"path": "apps/sveltekit-app/playwright.config.ts",
"chars": 266,
"preview": "import type { PlaywrightTestConfig } from '@playwright/test';\n\nconst config: PlaywrightTestConfig = {\n\twebServer: {\n\t\tco"
},
{
"path": "apps/sveltekit-app/src/app.d.ts",
"chars": 269,
"preview": "// See https://kit.svelte.dev/docs/types#app\n// for information about these interfaces\ndeclare global {\n\tnamespace App {"
},
{
"path": "apps/sveltekit-app/src/app.html",
"chars": 346,
"preview": "<!doctype html>\n<html lang=\"en\">\n\t<head>\n\t\t<meta charset=\"utf-8\" />\n\t\t<link rel=\"icon\" href=\"%sveltekit.assets%/favicon."
},
{
"path": "apps/sveltekit-app/src/index.test.ts",
"chars": 148,
"preview": "import { describe, it, expect } from 'vitest';\n\ndescribe('sum test', () => {\n\tit('adds 1 + 2 to equal 3', () => {\n\t\texpe"
},
{
"path": "apps/sveltekit-app/src/lib/FFmpegDemo.svelte",
"chars": 1475,
"preview": "<script lang=\"ts\">\n\timport { FFmpeg } from '@ffmpeg/ffmpeg';\n\t// @ts-ignore\n\timport type { LogEvent } from '@ffmpeg/ffmp"
},
{
"path": "apps/sveltekit-app/src/lib/index.ts",
"chars": 75,
"preview": "// place files you want to import through the `$lib` alias in this folder.\n"
},
{
"path": "apps/sveltekit-app/src/routes/+page.svelte",
"chars": 229,
"preview": "<script lang=\"ts\">\n\timport FFmpegDemo from '../lib/FFmpegDemo.svelte';\n</script>\n\n<h1>Welcome to SvelteKit</h1>\n<p>Visit"
},
{
"path": "apps/sveltekit-app/svelte.config.js",
"chars": 675,
"preview": "import adapter from '@sveltejs/adapter-auto';\nimport { vitePreprocess } from '@sveltejs/vite-plugin-svelte';\n\n/** @type "
},
{
"path": "apps/sveltekit-app/tests/test.ts",
"chars": 224,
"preview": "import { expect, test } from '@playwright/test';\n\ntest('index page has expected h1', async ({ page }) => {\n\tawait page.g"
},
{
"path": "apps/sveltekit-app/tsconfig.json",
"chars": 565,
"preview": "{\n\t\"extends\": \"./.svelte-kit/tsconfig.json\",\n\t\"compilerOptions\": {\n\t\t\"allowJs\": true,\n\t\t\"checkJs\": true,\n\t\t\"esModuleInte"
},
{
"path": "apps/sveltekit-app/vite.config.ts",
"chars": 1108,
"preview": "import { sveltekit } from '@sveltejs/kit/vite';\nimport { fileURLToPath, URL } from 'node:url'\nimport { defineConfig } fr"
},
{
"path": "apps/vanilla-app/.gitignore",
"chars": 20,
"preview": "*.tgz\npublic/assets\n"
},
{
"path": "apps/vanilla-app/README.md",
"chars": 573,
"preview": "# Vanilla / Browser Examples\n\n## Setup\n\nYou need to download assets from npm before running the examples:\n\n```bash\n$ npm"
},
{
"path": "apps/vanilla-app/package.json",
"chars": 420,
"preview": "{\n \"name\": \"browser\",\n \"version\": \"0.12.0-alpha.0\",\n \"description\": \"browser example\",\n \"private\": true,\n \"scripts\""
},
{
"path": "apps/vanilla-app/public/concatDemuxer.html",
"chars": 1912,
"preview": "<html>\n <head>\n <link rel=\"stylesheet\" href=\"style.css\">\n <script src=\"/assets/ffmpeg/package/dist/umd/ffmpeg.js\""
},
{
"path": "apps/vanilla-app/public/style.css",
"chars": 133,
"preview": "html, body {\n margin: 0;\n width: 100%;\n height: 100%\n}\nbody {\n display: flex;\n flex-direction: column;\n align-item"
},
{
"path": "apps/vanilla-app/public/transcode-mt.esm.html",
"chars": 1595,
"preview": "<html>\n <head>\n <link rel=\"stylesheet\" href=\"style.css\">\n </head>\n <body>\n <h3>Upload a video to transcode to m"
},
{
"path": "apps/vanilla-app/public/transcode-mt.html",
"chars": 1744,
"preview": "<html>\n <head>\n <link rel=\"stylesheet\" href=\"style.css\">\n <script src=\"/assets/ffmpeg/package/dist/umd/ffmpeg.js\""
},
{
"path": "apps/vanilla-app/public/transcode.esm.html",
"chars": 1592,
"preview": "<html>\n <head>\n <link rel=\"stylesheet\" href=\"style.css\">\n </head>\n <body>\n <h3>Upload a video to transcode to m"
},
{
"path": "apps/vanilla-app/public/transcode.html",
"chars": 1741,
"preview": "<html>\n <head>\n <link rel=\"stylesheet\" href=\"style.css\">\n <script src=\"/assets/ffmpeg/package/dist/umd/ffmpeg.js\""
},
{
"path": "apps/vanilla-app/public/trim.html",
"chars": 1665,
"preview": "<html>\n <head>\n <link rel=\"stylesheet\" href=\"style.css\">\n <script src=\"/assets/ffmpeg/package/dist/umd/ffmpeg.js\""
},
{
"path": "apps/vanilla-app/server.js",
"chars": 779,
"preview": "const path = require(\"path\");\nconst express = require(\"express\");\nconst serveIndex = require(\"serve-index\");\nconst app ="
},
{
"path": "apps/vue-vite-app/.eslintrc.cjs",
"chars": 333,
"preview": "/* eslint-env node */\nrequire('@rushstack/eslint-patch/modern-module-resolution')\n\nmodule.exports = {\n root: true,\n 'e"
},
{
"path": "apps/vue-vite-app/.gitignore",
"chars": 302,
"preview": "# Logs\nlogs\n*.log\nnpm-debug.log*\nyarn-debug.log*\nyarn-error.log*\npnpm-debug.log*\nlerna-debug.log*\n\nnode_modules\n.DS_Stor"
},
{
"path": "apps/vue-vite-app/.prettierrc.json",
"chars": 163,
"preview": "{\n \"$schema\": \"https://json.schemastore.org/prettierrc\",\n \"semi\": false,\n \"tabWidth\": 2,\n \"singleQuote\": true,\n \"pr"
},
{
"path": "apps/vue-vite-app/.vscode/extensions.json",
"chars": 75,
"preview": "{\n \"recommendations\": [\"Vue.volar\", \"Vue.vscode-typescript-vue-plugin\"]\n}\n"
},
{
"path": "apps/vue-vite-app/README.md",
"chars": 1683,
"preview": "# vue-vite-app\n\nThis template should help get you started developing with Vue 3 in Vite.\n\n## Recommended IDE Setup\n\n[VSC"
},
{
"path": "apps/vue-vite-app/env.d.ts",
"chars": 38,
"preview": "/// <reference types=\"vite/client\" />\n"
},
{
"path": "apps/vue-vite-app/index.html",
"chars": 331,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n <head>\n <meta charset=\"UTF-8\">\n <link rel=\"icon\" href=\"/favicon.ico\">\n <meta"
},
{
"path": "apps/vue-vite-app/package.json",
"chars": 1060,
"preview": "{\n \"name\": \"vue-vite-app\",\n \"version\": \"0.0.0\",\n \"private\": true,\n \"scripts\": {\n \"dev\": \"vite\",\n \"build\": \"run"
},
{
"path": "apps/vue-vite-app/src/App.vue",
"chars": 150,
"preview": "<script setup lang=\"ts\">\nimport FFmpegDemo from './components/FFmpegDemo.vue'\n</script>\n\n<template>\n <main>\n <FFmpeg"
},
{
"path": "apps/vue-vite-app/src/assets/base.css",
"chars": 2067,
"preview": "/* color palette from <https://github.com/vuejs/theme> */\n:root {\n --vt-c-white: #ffffff;\n --vt-c-white-soft: #f8f8f8;"
},
{
"path": "apps/vue-vite-app/src/assets/main.css",
"chars": 477,
"preview": "@import './base.css';\n\n#app {\n max-width: 1280px;\n margin: 0 auto;\n padding: 2rem;\n\n font-weight: normal;\n}\n\na,\n.gre"
},
{
"path": "apps/vue-vite-app/src/components/FFmpegDemo.vue",
"chars": 1848,
"preview": "<template>\n <video :src=\"video\" controls />\n <br />\n <button @click=\"transcode\">Start</button>\n <p>{{ message }}</p>"
},
{
"path": "apps/vue-vite-app/src/main.ts",
"chars": 118,
"preview": "import './assets/main.css'\n\nimport { createApp } from 'vue'\nimport App from './App.vue'\n\ncreateApp(App).mount('#app')\n"
},
{
"path": "apps/vue-vite-app/tsconfig.app.json",
"chars": 316,
"preview": "{\n \"extends\": \"@vue/tsconfig/tsconfig.dom.json\",\n \"include\": [\"env.d.ts\", \"src/**/*\", \"src/**/*.vue\"],\n \"exclude\": [\""
},
{
"path": "apps/vue-vite-app/tsconfig.json",
"chars": 139,
"preview": "{\n \"files\": [],\n \"references\": [\n {\n \"path\": \"./tsconfig.node.json\"\n },\n {\n \"path\": \"./tsconfig.app"
},
{
"path": "apps/vue-vite-app/tsconfig.node.json",
"chars": 321,
"preview": "{\n \"extends\": \"@tsconfig/node18/tsconfig.json\",\n \"include\": [\n \"vite.config.*\",\n \"vitest.config.*\",\n \"cypress"
},
{
"path": "apps/vue-vite-app/vite.config.ts",
"chars": 567,
"preview": "import { fileURLToPath, URL } from 'node:url'\n\nimport { defineConfig } from 'vite'\nimport vue from '@vitejs/plugin-vue'\n"
},
{
"path": "apps/website/.gitignore",
"chars": 243,
"preview": "# Dependencies\n/node_modules\n\n# Production\n/build\n/docs/api\n\n# Generated files\n.docusaurus\n.cache-loader\n\n# Misc\n.DS_Sto"
},
{
"path": "apps/website/README.md",
"chars": 942,
"preview": "# Website\n\nThis website is built using [Docusaurus 2](https://docusaurus.io/), a modern static website generator.\n\n### I"
},
{
"path": "apps/website/assets/ffmpegwasm-arch.drawio",
"chars": 9515,
"preview": "<mxfile host=\"Electron\" modified=\"2023-07-25T14:12:19.793Z\" agent=\"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (K"
},
{
"path": "apps/website/babel.config.js",
"chars": 89,
"preview": "module.exports = {\n presets: [require.resolve('@docusaurus/core/lib/babel/preset')],\n};\n"
},
{
"path": "apps/website/blog/2023-07-26-release-ffmpeg.wasm-0.12.0.mdx",
"chars": 2167,
"preview": "---\nslug: release-ffmpeg.wasm-0.12.0\ntitle: Release ffmpeg.wasm 0.12.0\nauthors: [jeromewu]\ntags: [ffmpeg.wasm]\n---\n\nFina"
},
{
"path": "apps/website/blog/authors.yml",
"chars": 129,
"preview": "jeromewu:\n name: Jerome Wu\n title: Maintainer of ffmpeg.wasm\n url: https://github.com/jeromewu\n image_url: /img/jero"
},
{
"path": "apps/website/deploy.sh",
"chars": 39,
"preview": "#!/bin/bash\n\nnpm install\nnpm run build\n"
},
{
"path": "apps/website/docs/contribution/core.md",
"chars": 4270,
"preview": "# @ffmpeg/core\n\nTo build @ffmpeg/core, make sure your docker is version 23.0+ as\n[buildx](https://docs.docker.com/build/"
},
{
"path": "apps/website/docs/contribution/ffmpeg.md",
"chars": 306,
"preview": "# @ffmpeg/ffmpeg\n\nThe source code of @ffmpeg/ffmpeg locates at **/packages/ffmpeg**.\n\n## Development\n\n```bash\n$ npm run "
},
{
"path": "apps/website/docs/contribution/util.md",
"chars": 298,
"preview": "# @ffmpeg/util\n\nThe source code of @ffmpeg/util locates at **/packages/util**.\n\n## Development\n\n```bash\n$ npm run dev\n``"
},
{
"path": "apps/website/docs/faq.md",
"chars": 2644,
"preview": "# FAQ\n\n### Why ffmpeg.wasm doesn't support nodejs?\n\nffmpeg.wasm did support nodejs before 0.12.0, but decided to discont"
},
{
"path": "apps/website/docs/getting-started/examples.md",
"chars": 2472,
"preview": "import Grid from '@mui/material/Unstable_Grid2';\nimport MuiThemeProvider from \"@site/src/components/common/MuiThemeProvi"
},
{
"path": "apps/website/docs/getting-started/installation.md",
"chars": 679,
"preview": "import Tabs from '@theme/Tabs';\nimport TabItem from '@theme/TabItem';\n\n# Installation\n\n:::note\nffmpeg.wasm only supports"
},
{
"path": "apps/website/docs/getting-started/usage.md",
"chars": 15564,
"preview": "# Usage\n\nLearn the basics of using ffmpeg.wasm.\n\n:::note\nIt is recommended to read [Overview](/docs/overview) first.\n:::"
},
{
"path": "apps/website/docs/migration.md",
"chars": 2460,
"preview": "import MuiThemeProvider from \"@site/src/components/common/MuiThemeProvider\";\nimport Table from '@mui/material/Table';\nim"
},
{
"path": "apps/website/docs/overview.md",
"chars": 7278,
"preview": "import MuiThemeProvider from \"@site/src/components/common/MuiThemeProvider\";\nimport Table from '@mui/material/Table';\nim"
},
{
"path": "apps/website/docs/performance.md",
"chars": 1248,
"preview": "# Performance\n\nffmpeg.wasm uses transpiled FFmpeg C source code to WebAssembly code, it is for\ncertain that ffmpeg.wasm "
},
{
"path": "apps/website/docs/privacy-policy.md",
"chars": 16865,
"preview": "# Privacy Policy\n<p>Last updated: August 05, 2023</p>\n<p>This Privacy Policy describes Our policies and procedures on th"
},
{
"path": "apps/website/docusaurus.config.js",
"chars": 5245,
"preview": "// @ts-check\n// Note: type annotations allow type checking and IDEs autocompletion\n\nconst lightCodeTheme = require(\"pris"
},
{
"path": "apps/website/netlify.toml",
"chars": 137,
"preview": "[[headers]]\n for = \"/*\"\n [headers.values]\n Cross-Origin-Opener-Policy = \"same-origin\"\n Cross-Origin-Embedder-Policy "
},
{
"path": "apps/website/package.json",
"chars": 1830,
"preview": "{\n \"name\": \"website\",\n \"version\": \"0.12.0-alpha.0\",\n \"private\": true,\n \"scripts\": {\n \"docusaurus\": \"docusaurus\",\n"
},
{
"path": "apps/website/sidebars.js",
"chars": 1245,
"preview": "/**\n * Creating a sidebar enables you to:\n - create an ordered group of docs\n - render a sidebar for each doc of that gr"
},
{
"path": "apps/website/src/components/ExternalLibraries/index.tsx",
"chars": 2481,
"preview": "import React from \"react\";\nimport clsx from \"clsx\";\nimport styles from \"./styles.module.css\";\n\ninterface LibraryItem {\n "
},
{
"path": "apps/website/src/components/ExternalLibraries/styles.module.css",
"chars": 250,
"preview": ".libraries {\n display: flex;\n align-items: center;\n padding: 2rem 0;\n width: 100%;\n background-color: rgba(229,231,"
},
{
"path": "apps/website/src/components/HomepageFeatures/index.tsx",
"chars": 1842,
"preview": "import React from \"react\";\nimport clsx from \"clsx\";\nimport styles from \"./styles.module.css\";\n\ntype FeatureItem = {\n ti"
},
{
"path": "apps/website/src/components/HomepageFeatures/styles.module.css",
"chars": 138,
"preview": ".features {\n display: flex;\n align-items: center;\n padding: 2rem 0;\n width: 100%;\n}\n\n.featureSvg {\n height: 200px;\n"
},
{
"path": "apps/website/src/components/Playground/CoreDownloader.tsx",
"chars": 591,
"preview": "import * as React from \"react\";\nimport Typography from \"@mui/material/Typography\";\nimport Container from \"@mui/material/"
},
{
"path": "apps/website/src/components/Playground/CoreSwitcher.tsx",
"chars": 1179,
"preview": "import React from \"react\";\nimport Stack from \"@mui/material/Stack\";\nimport FormGroup from \"@mui/material/FormGroup\";\nimp"
},
{
"path": "apps/website/src/components/Playground/Workspace/Editor.tsx",
"chars": 3549,
"preview": "/// <reference types=\"ace\" />\n\nimport React, { useEffect, useState } from \"react\";\nimport AceEditor from \"react-ace\";\nim"
},
{
"path": "apps/website/src/components/Playground/Workspace/FileSystemManager.tsx",
"chars": 8519,
"preview": "import React, { useState, ChangeEvent } from \"react\";\nimport Box from \"@mui/material/Box\";\nimport Button from \"@mui/mate"
},
{
"path": "apps/website/src/components/Playground/Workspace/MoreButton.tsx",
"chars": 1684,
"preview": "import * as React from \"react\";\nimport IconButton from \"@mui/material/IconButton\";\nimport Menu from \"@mui/material/Menu\""
},
{
"path": "apps/website/src/components/Playground/Workspace/index.tsx",
"chars": 5241,
"preview": "import React, {\n ChangeEvent,\n useState,\n useEffect,\n MutableRefObject,\n} from \"react\";\nimport Box from \"@mui/materi"
},
{
"path": "apps/website/src/components/Playground/Workspace/types.tsx",
"chars": 60,
"preview": "export interface Node {\n name: string;\n isDir: boolean;\n}\n"
},
{
"path": "apps/website/src/components/Playground/const.ts",
"chars": 948,
"preview": "export const CORE_VERSION = \"0.12.10\";\n\nexport const CORE_URL = `https://cdn.jsdelivr.net/npm/@ffmpeg/core@${CORE_VERSIO"
},
{
"path": "apps/website/src/components/Playground/index.tsx",
"chars": 2301,
"preview": "import React, { useState, useEffect, useRef } from \"react\";\nimport { FFmpeg } from \"@ffmpeg/ffmpeg\";\nimport { toBlobURL "
},
{
"path": "apps/website/src/components/common/ExampleCard.tsx",
"chars": 1046,
"preview": "import * as React from \"react\";\nimport Card from \"@mui/material/Card\";\nimport CardContent from \"@mui/material/CardConten"
},
{
"path": "apps/website/src/components/common/LinearProgressWithLabel.tsx",
"chars": 682,
"preview": "import * as React from \"react\";\nimport Box from \"@mui/material/Box\";\nimport Typography from \"@mui/material/Typography\";\n"
},
{
"path": "apps/website/src/components/common/MuiThemeProvider/index.tsx",
"chars": 477,
"preview": "import React from \"react\";\nimport { useColorMode } from \"@docusaurus/theme-common\";\nimport { ThemeProvider, createTheme "
},
{
"path": "apps/website/src/components/common/ThemedButton/index.tsx",
"chars": 292,
"preview": "import React from \"react\";\nimport MuiThemeProvider from \"../MuiThemeProvider\";\nimport Button, { ButtonProps } from \"@mui"
},
{
"path": "apps/website/src/components/common/ThemedIconButton/index.tsx",
"chars": 316,
"preview": "import React from \"react\";\nimport MuiThemeProvider from \"../MuiThemeProvider\";\nimport IconButton, { IconButtonProps } fr"
},
{
"path": "apps/website/src/css/custom.css",
"chars": 1046,
"preview": "/**\n * Any CSS included here will be global. The classic template\n * bundles Infima by default. Infima is a CSS framewor"
},
{
"path": "apps/website/src/pages/index.module.css",
"chars": 365,
"preview": "/**\n * CSS files with the .module.css suffix will be treated as CSS modules\n * and scoped locally.\n */\n\n.heroBanner {\n "
},
{
"path": "apps/website/src/pages/index.tsx",
"chars": 1319,
"preview": "import React from \"react\";\nimport clsx from \"clsx\";\nimport Link from \"@docusaurus/Link\";\nimport useDocusaurusContext fro"
},
{
"path": "apps/website/src/pages/playground.md",
"chars": 3752,
"preview": "import BrowserOnly from '@docusaurus/BrowserOnly';\nimport MuiThemeProvider from \"@site/src/components/common/MuiThemePro"
},
{
"path": "apps/website/src/theme/ReactLiveScope/index.js",
"chars": 278,
"preview": "import React from \"react\";\nimport { FFmpeg } from \"@ffmpeg/ffmpeg\";\nimport { fetchFile, toBlobURL } from \"@ffmpeg/util\";"
},
{
"path": "apps/website/src/util.ts",
"chars": 286,
"preview": "export const downloadFile = (name: string, data: ArrayBuffer | string) => {\n const a = document.createElement(\"a\");\n c"
},
{
"path": "apps/website/static/.nojekyll",
"chars": 0,
"preview": ""
},
{
"path": "apps/website/static/ads.txt",
"chars": 59,
"preview": "google.com, pub-8688083214014126, DIRECT, f08c47fec0942fa0\n"
},
{
"path": "apps/website/tsconfig.json",
"chars": 190,
"preview": "{\n // This file is not used in compilation. It is here just for a nice editor experience.\n \"extends\": \"@tsconfig/docus"
},
{
"path": "build/aom.sh",
"chars": 965,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCM_FLAGS=(\n -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR # assign lib and include inst"
},
{
"path": "build/ffmpeg-wasm.sh",
"chars": 1892,
"preview": "#!/bin/bash\n# `-o <OUTPUT_FILE_NAME>` must be provided when using this build script.\n# ex:\n# bash ffmpeg-wasm.sh -o "
},
{
"path": "build/ffmpeg.sh",
"chars": 1019,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCONF_FLAGS=(\n --target-os=none # disable target specific configs\n --arch="
},
{
"path": "build/freetype2.sh",
"chars": 593,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCONF_FLAGS=(\n --prefix=$INSTALL_DIR # install library in "
},
{
"path": "build/fribidi.sh",
"chars": 545,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCONF_FLAGS=(\n --prefix=$INSTALL_DIR # install library in "
},
{
"path": "build/harfbuzz.sh",
"chars": 701,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCFLAGS=\"$CFLAGS -DHB_NO_PRAGMA_GCC_DIAGNOSTIC_ERROR\"\n\n# A hacky way to disable pthread\ni"
},
{
"path": "build/lame.sh",
"chars": 652,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCONF_FLAGS=(\n --prefix=$INSTALL_DIR # install library in "
},
{
"path": "build/libass.sh",
"chars": 498,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCONF_FLAGS=(\n --prefix=$INSTALL_DIR # install library in "
},
{
"path": "build/libvpx.sh",
"chars": 1115,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCONF_FLAGS=(\n --prefix=$INSTALL_DIR # install library in a"
},
{
"path": "build/libwebp.sh",
"chars": 599,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCM_FLAGS=(\n -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR\n -DCMAKE_TOOLCHAIN_FILE=$EM_TOOLCHAIN_"
},
{
"path": "build/ogg.sh",
"chars": 514,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCONF_FLAGS=(\n --prefix=$INSTALL_DIR # install library i"
},
{
"path": "build/opus.sh",
"chars": 845,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCONF_FLAGS=(\n --prefix=$INSTALL_DIR # install library in "
},
{
"path": "build/theora.sh",
"chars": 705,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCONF_FLAGS=(\n --prefix=$INSTALL_DIR # install library in "
},
{
"path": "build/vorbis.sh",
"chars": 689,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\n# Remove this flag as clang doesn't recognize\nsed -i 's#-mno-ieee-fp##g' configure.ac\n\nC"
},
{
"path": "build/wavpack.sh",
"chars": 993,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCONF_FLAGS=(\n --prefix=$INSTALL_DIR # install library in"
},
{
"path": "build/x264.sh",
"chars": 531,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCONF_FLAGS=(\n --prefix=$INSTALL_DIR # lib installation dir\n --host=x86-gnu "
},
{
"path": "build/x265.sh",
"chars": 1141,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nBASE_FLAGS=(\n -DCMAKE_TOOLCHAIN_FILE=$EM_TOOLCHAIN_FILE\n -DENABLE_LIBNUMA=OFF\n -DENAB"
},
{
"path": "build/zimg.sh",
"chars": 501,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCONF_FLAGS=(\n --prefix=$INSTALL_DIR # lib installation directory\n --host=x8"
},
{
"path": "build/zlib.sh",
"chars": 301,
"preview": "#!/bin/bash\n\nset -euo pipefail\n\nCM_FLAGS=(\n -DCMAKE_INSTALL_PREFIX=$INSTALL_DIR\n -DCMAKE_TOOLCHAIN_FILE=$EM_TOOLCHAIN_"
},
{
"path": "package.json",
"chars": 1818,
"preview": "{\n \"name\": \"root\",\n \"private\": true,\n \"scripts\": {\n \"lint\": \"npm-run-all lint:*\",\n \"lint:packages\": \"npm run li"
},
{
"path": "packages/core/.gitignore",
"chars": 13,
"preview": "dist/\ntypes/\n"
},
{
"path": "packages/core/package.json",
"chars": 944,
"preview": "{\n \"name\": \"@ffmpeg/core\",\n \"version\": \"0.12.10\",\n \"description\": \"FFmpeg WebAssembly version (single thread)\",\n \"ma"
},
{
"path": "packages/core-mt/.gitignore",
"chars": 13,
"preview": "dist/\ntypes/\n"
},
{
"path": "packages/core-mt/package.json",
"chars": 1075,
"preview": "{\n \"name\": \"@ffmpeg/core-mt\",\n \"version\": \"0.12.10\",\n \"description\": \"FFmpeg WebAssembly version (multi thread)\",\n \""
},
{
"path": "packages/ffmpeg/.eslintignore",
"chars": 14,
"preview": ".eslintrc.cjs\n"
},
{
"path": "packages/ffmpeg/.eslintrc.cjs",
"chars": 374,
"preview": "module.exports = {\n extends: [\n \"eslint:recommended\",\n \"plugin:@typescript-eslint/recommended\",\n \"plugin:@type"
},
{
"path": "packages/ffmpeg/.gitignore",
"chars": 12,
"preview": "dist/\ndocs/\n"
},
{
"path": "packages/ffmpeg/package.json",
"chars": 1655,
"preview": "{\n \"name\": \"@ffmpeg/ffmpeg\",\n \"version\": \"0.12.15\",\n \"description\": \"FFmpeg WebAssembly version for browser\",\n \"main"
},
{
"path": "packages/ffmpeg/src/classes.ts",
"chars": 11848,
"preview": "import { FFMessageType } from \"./const.js\";\nimport {\n CallbackData,\n Callbacks,\n FSNode,\n FFMessageEventCallback,\n "
},
{
"path": "packages/ffmpeg/src/const.ts",
"chars": 660,
"preview": "export const MIME_TYPE_JAVASCRIPT = \"text/javascript\";\nexport const MIME_TYPE_WASM = \"application/wasm\";\n\nexport const C"
},
{
"path": "packages/ffmpeg/src/empty.mts",
"chars": 150,
"preview": "// File to be imported in node environments\n\nexport class FFmpeg {\n constructor() {\n throw new Error(\"ffmpeg.wasm do"
}
]
// ... and 65 more files (download for full content)
About this extraction
This page contains the full source code of the ffmpegwasm/ffmpeg.wasm GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 265 files (1.1 MB), approximately 301.2k tokens, and a symbol index with 708 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.