Created repo
|
@ -0,0 +1,3 @@
|
|||
videos
|
||||
output
|
||||
node/node_modules
|
|
@ -0,0 +1,222 @@
|
|||
---
|
||||
header-includes:
|
||||
- \hypersetup{colorlinks=true,
|
||||
allbordercolors={0 0 1},
|
||||
pdfborderstyle={/S/U/W 1}}
|
||||
---
|
||||
|
||||
# UNIX FOR ARTISTS
|
||||
### Fun with FFMPEG
|
||||
|
||||
## Requirements
|
||||
|
||||
The following applications and runtime environments are needed to run the scripts used in the workshop.
|
||||
Installation instructions are available below, broken down by operating system.
|
||||
|
||||
* [Bash](https://www.gnu.org/software/bash/) - *You probably have it already!*
|
||||
* [FFMPEG](https://www.ffmpeg.org/)
|
||||
* [ImageMagick](https://imagemagick.org/index.php)
|
||||
* [Youtube-dl](https://ytdl-org.github.io/youtube-dl/index.html)
|
||||
* [Golang](https://golang.org/)
|
||||
* \*[Python3](https://www.python.org/downloads/) (*optional*)
|
||||
* \*[Node.js](https://nodejs.org/en/) (*optional*)
|
||||
|
||||
It's very helpful to have a text editor that you can comfortably read and edit scripts in.
|
||||
This selection of text editors ranges from free and open source to "free to use" and "free to try".
|
||||
You can also use TextEdit or Notepad or any text editing application you prefer as long as it's capable of editing in plaintext.
|
||||
|
||||
* [Atom](https://atom.io/) - Free. *macOS, Windows and Linux.*
|
||||
* [GNU Emacs](https://www.gnu.org/software/emacs/download.html) - Free. *Linux, macOS and Windows.*
|
||||
* [Visual Studio Code](https://code.visualstudio.com/download) - Free. *macOS, Windows and Linux.*
|
||||
* [Sublime Text 3](https://www.sublimetext.com/3) - Free to evaluate. *macOS, Windows and Linux.*
|
||||
* [Notepad++](https://notepad-plus-plus.org/downloads/) - Free to use. *Windows only.*
|
||||
* [BBEdit](http://www.barebones.com/products/bbedit/download.html) - Freemium. *macOS only.*
|
||||
|
||||
-------
|
||||
|
||||
## macOS
|
||||
|
||||
![The macOS Terminal](img/mac_terminal.png "The macOS Terminal")
|
||||
|
||||
Open the Terminal app located in your Applications folder.
|
||||
Bash 3.2 is available by default on macOS.
|
||||
|
||||
|
||||
##### Install Homebrew
|
||||
|
||||
Go to [https://brew.sh](https://brew.sh) and run the command under the "Install Homebrew" heading after pasting it into your Terminal.
|
||||
|
||||
You will be asked to confirm a few things while Homebrew installs.
|
||||
|
||||
Once the installation process is complete you can install the applications we will be using in this workshop by running the following commands:
|
||||
|
||||
```bash
|
||||
brew install ffmpeg imagemagick youtube-dl
|
||||
```
|
||||
|
||||
Optionally, you can install Node.js for a single example that we will be covering in the workshop.
|
||||
|
||||
```bash
|
||||
brew install node
|
||||
```
|
||||
|
||||
Make sure that you have a compatible version of Python installed by running the following command:
|
||||
|
||||
```bash
|
||||
python3 --version
|
||||
```
|
||||
|
||||
It should print out a value similar to `Python 3.8.2`.
|
||||
Anything higher than 3.7.0 will work.
|
||||
|
||||
##### Install Golang on macOS
|
||||
|
||||
Go to the [Golang download site](https://golang.org/doc/install).
|
||||
|
||||
Select the "Mac" tab under "2. Go install." if not already selected and download the .pkg installer using the "Download Go for Mac" button.
|
||||
|
||||
Open the installer and follow the instructions.
|
||||
|
||||
Confirm that Go is installed by running the following command in Terminal:
|
||||
|
||||
```bash
|
||||
go version
|
||||
```
|
||||
|
||||
If Golang has been installed correctly you can now install `primitive`.
|
||||
|
||||
```bash
|
||||
go get -u github.com/fogleman/primitive
|
||||
```
|
||||
|
||||
-------
|
||||
|
||||
## Windows 10
|
||||
|
||||
Windows has its own command-line interpreter, but in order to keep code and examples consistent across different operating systems you will need to install the Windows Subsystem for Linux (WSL).
|
||||
|
||||
##### Enable WSL
|
||||
|
||||
Open the "Turn Windows Features on or off" dialog by searching in your command bar.
|
||||
|
||||
![Turn Windows features on or off](img/windows_10_turn_windows_features.png "Turn Windows features on or off")
|
||||
|
||||
Enable "Virtual Machine Platform" and "Windows Subsystem for Linux" by selecting the checkboxes next to the items and hit "OK".
|
||||
|
||||
![Enable WSL and Virtual Machine Platform](img/windows_10_enable.png "Enable WSL and Virtual Machine Platform")
|
||||
|
||||
Restart your computer for changes to apply.
|
||||
|
||||
|
||||
##### Install Ubuntu 20.04 LTS
|
||||
|
||||
Open the Microsoft Store and search for "Ubuntu".
|
||||
For the latest LTS version, install `Ubuntu 20.04`.
|
||||
|
||||
![Install Ubuntu 20.04](img/windows_10_install.png "Install Ubuntu 20.04 through the Microsoft Store")
|
||||
|
||||
Other versions of Ubuntu or openSUSE may work, but will be subject to differences in behavior.
|
||||
|
||||
![Select the Ubuntu shell](img/windows_10_ubuntu.png "Select the Ubuntu shell")
|
||||
|
||||
Once you've installed Ubuntu, you can open the shell and begin running commands using Bash.
|
||||
|
||||
|
||||
##### Install Requirements on Windows 10
|
||||
|
||||
![The Ubuntu shell on Windows 10](img/windows_10_terminal.png "The Ubuntu shell on Windows 10")
|
||||
|
||||
You can now run the following commands to install the applications for this workshop:
|
||||
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install -y ffmpeg imagemagick youtube-dl
|
||||
```
|
||||
|
||||
Optionally install Node.js.
|
||||
|
||||
```bash
|
||||
sudo apt install -y nodejs npm
|
||||
```
|
||||
|
||||
|
||||
##### Install Golang on Windows 10
|
||||
|
||||
Go to the [Golang download site](https://golang.org/doc/install).
|
||||
|
||||
Select the "Windows" tab under "2. Go install." if not already selected and download the .msi installer by using the "Download Go for Windows" button.
|
||||
|
||||
Confirm that Go is installed by running the following command in your shell:
|
||||
|
||||
```bash
|
||||
go version
|
||||
```
|
||||
|
||||
If Golang has been installed correctly you can now install `primitive`.
|
||||
|
||||
```bash
|
||||
go get -u github.com/fogleman/primitive
|
||||
```
|
||||
|
||||
-------
|
||||
|
||||
Additional tutorials for installing Bash on Windows 10.
|
||||
|
||||
* [How to Install Linux Bash Shell on Windows 10](https://itsfoss.com/install-bash-on-windows/)
|
||||
* [Install Bash on Windows 10](https://bayton.org/docs/linux/ubuntu/install-bash-on-windows-10-build-14316/)
|
||||
|
||||
-------
|
||||
|
||||
## Linux
|
||||
|
||||
Open up your preferred terminal application and install the required applications on a Debian-based system.
|
||||
|
||||
```bash
|
||||
sudo apt install -y ffmpeg imagemagick youtube-dl
|
||||
```
|
||||
|
||||
Or, if your distribution uses the `yum` package manager.
|
||||
|
||||
```bash
|
||||
yum install ffmpeg imagemagick youtube-dl
|
||||
```
|
||||
|
||||
Optionally install Node.js.
|
||||
|
||||
```bash
|
||||
sudo apt install -y nodejs npm
|
||||
```
|
||||
Or using yum.
|
||||
|
||||
```
|
||||
yum install nodejs
|
||||
```
|
||||
|
||||
##### Install Golang on Linux
|
||||
|
||||
Go to the [Golang download site](https://golang.org/doc/install).
|
||||
|
||||
Select the "Linux" tab under "2. Go install." if not already selected and download the .tar.gz archive using the "Download Go for Linux" button.
|
||||
|
||||
Navigate to the folder you downloaded the archive into.
|
||||
For the following commands, `go1.16.3.linux-amd64.tar.gz` can be replaced by the filename of the version that you just downloaded.
|
||||
|
||||
```bash
|
||||
sudo rm -rf /usr/local/go
|
||||
sudo tar -C /usr/local -xzf go1.16.3.linux-amd64.tar.gz
|
||||
export PATH=$PATH:/usr/local/go/bin
|
||||
```
|
||||
|
||||
Either restart your terminal or run the command `source $HOME/.profile` to apply the changes just made to your system.
|
||||
|
||||
Confirm that Go is installed by running the following command:
|
||||
|
||||
```bash
|
||||
go version
|
||||
```
|
||||
|
||||
If Golang has been correctly installed you can now install `primitive`.
|
||||
|
||||
```bash
|
||||
go get -u github.com/fogleman/primitive
|
||||
```
|
|
@ -0,0 +1,22 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# Arguments are provided to commands and scripts usually
|
||||
# separated by a space. They can be read and used within
|
||||
# bash scripts by referencing them with the "$#" notation.
|
||||
#
|
||||
# Usage: bash bash/arguments.sh <first> <second> <third> <etc>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
echo "You entered \"$1\" as the first argument"
|
||||
|
||||
# Using a slightly different notation
|
||||
if [ "${2}" != "" ]; then
|
||||
echo "You entered \"${2}\" as the second argument"
|
||||
fi
|
||||
|
||||
if [ "${3}" != "" ]; then
|
||||
echo "All of the arguments you entered \"${@}\""
|
||||
fi
|
|
@ -0,0 +1,28 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# "cat" is an application that prints text files
|
||||
# into your terminal and allows you to concatinate
|
||||
# multiple files together.
|
||||
#
|
||||
# Usage: bash bash/cat.sh
|
||||
#
|
||||
#####################################################
|
||||
|
||||
cat "text/cat1.txt"
|
||||
|
||||
sleep 2
|
||||
|
||||
# Concatinate multiple files and print the result
|
||||
cat "text/cat2.txt" "text/cat3.txt"
|
||||
|
||||
sleep 2
|
||||
|
||||
# Concatinate all files into a new file using the ">" redirect operator
|
||||
cat "text/cat1.txt" "text/cat2.txt" "text/cat3.txt" > "text/all.txt"
|
||||
|
||||
sleep 2
|
||||
|
||||
# Print the contents of this file
|
||||
cat bash/cat.sh
|
|
@ -0,0 +1,26 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# Functions can be defined using the "name () {}"
|
||||
# notation where the code is contained within the
|
||||
# brackets. Functions receive arguments the same way
|
||||
# a script does, using the "$#" notation.
|
||||
#
|
||||
#####################################################
|
||||
|
||||
myFunction () {
|
||||
if [ "${1}" != "" ]; then
|
||||
echo "Your first argument is \"${1}\""
|
||||
else
|
||||
echo "Called myFunction with no arguments"
|
||||
fi
|
||||
}
|
||||
|
||||
# Invoke your function as if it were any other command
|
||||
# or application located in your $PATH.
|
||||
myFunction
|
||||
|
||||
sleep 2
|
||||
|
||||
myFunction "First argument"
|
|
@ -0,0 +1,72 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# If/else statements allow you to run select commands
|
||||
# if conditions are met or if they are not.
|
||||
#
|
||||
# Usage: bash bash/ifelse.sh
|
||||
#
|
||||
#####################################################
|
||||
|
||||
NUMBER=3
|
||||
COMPARE="Compare this string"
|
||||
SUBSTRING="not"
|
||||
SUBSTRING2="this"
|
||||
|
||||
# Evaluate whether two numbers are equal with the "-eq" operator
|
||||
if [ ${NUMBER} -eq 3 ]; then
|
||||
echo "Variable \$NUMBER is equal to 3"
|
||||
else
|
||||
echo "Variable \$NUMBER is NOT equal to 3"
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
|
||||
# Evaluate whether a string contains substrings. Uses the
|
||||
# "elif" operator to check if a second condition is met if
|
||||
# the first one fails.
|
||||
if [[ "${COMPARE}" == *"${SUBSTRING}"* ]]; then
|
||||
echo "String \$COMPARE contains substring \"${SUBSTRING}\""
|
||||
elif [[ "${COMPARE}" == *"${SUBSTRING2}"* ]]; then
|
||||
echo "String \$COMPARE contains substring \"${SUBSTRING2}\""
|
||||
else
|
||||
echo "String \$COMPARE contains none of the substrings"
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
|
||||
# Evaluate whether a file exists with the "-f" operator
|
||||
if [ -f "text/cat1.txt" ]; then
|
||||
echo "File text/cat1.txt exists. Here are the contents:"
|
||||
cat text/cat1.txt
|
||||
else
|
||||
echo "File text/cat1.txt does NOT exist"
|
||||
fi
|
||||
|
||||
sleep 2
|
||||
|
||||
# Evaluate whether a directory exists with the "-d" operator
|
||||
if [ -d "not_here" ]; then
|
||||
echo "Directory not_here exists. Here are the contents:"
|
||||
ls not_here
|
||||
else
|
||||
echo "Directory not_here does NOT exist"
|
||||
fi
|
||||
|
||||
# Evaluate whether or not one condition OR another
|
||||
# is met using the "||" operators.
|
||||
# The "-gt" operator determines if a number is
|
||||
# greater than a compared number and "-lt" for
|
||||
# less than.
|
||||
if [ $NUMBER -gt 1 ] || [ $NUMBER -lt 5]; then
|
||||
echo "Variable \$NUMBER is greater than 1 or less than 5"
|
||||
fi
|
||||
|
||||
# Evaluate whether both conditions are met using
|
||||
# the AND operator "&&"
|
||||
if [[ "${COMPARE}" == *"${SUBSTRING}"* ]] && [[ "${COMPARE}" == *"${SUBSTRING2}"* ]]; then
|
||||
echo "String \$COMPARE contains both substrings"
|
||||
else
|
||||
echo "String \$COMPARE does not contain both substrings"
|
||||
fi
|
|
@ -0,0 +1,50 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# The commands "cd",
|
||||
#
|
||||
# Usage: bash bash/paths.sh
|
||||
#
|
||||
#####################################################
|
||||
|
||||
THIS_DIRECTORY=`pwd`
|
||||
echo "${THIS_DIRECTORY}"
|
||||
|
||||
sleep 2
|
||||
|
||||
# Go to your "home" directory for your user
|
||||
cd ~/
|
||||
echo "You are now in:"
|
||||
pwd
|
||||
|
||||
sleep 2
|
||||
|
||||
# Go to the root of your filesystem
|
||||
cd /
|
||||
echo "You are now in:"
|
||||
pwd
|
||||
|
||||
sleep 2
|
||||
# List all files and directories in "long" and "readable" format
|
||||
ls -lh
|
||||
|
||||
sleep 10
|
||||
|
||||
# Return to the directory you started in
|
||||
cd "${THIS_DIRECTORY}"
|
||||
echo "You are now back in:"
|
||||
pwd
|
||||
|
||||
sleep 2
|
||||
|
||||
# Go into the "bash" sub-directory
|
||||
cd bash
|
||||
echo "You are now in:"
|
||||
pwd
|
||||
|
||||
# Return to the parent directory, the one you started in,
|
||||
# by using the double period ".." notation
|
||||
cd ../
|
||||
echo "You are now back in:"
|
||||
pwd
|
|
@ -0,0 +1,33 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# Variables are stored values that can be set locally
|
||||
# in the script or inherited from your environment.
|
||||
#
|
||||
# Usage: bash bash/variables.sh
|
||||
#
|
||||
#####################################################
|
||||
|
||||
# Set this variable to run the script
|
||||
VARIABLE=""
|
||||
NUMBER=3
|
||||
|
||||
# Save output of the command "pwd" to a variable
|
||||
# by running it in a subshell
|
||||
CURRENT_DIR=`pwd`
|
||||
|
||||
# A different notation for subshells, this time
|
||||
# saving the contents of a text file to a variable
|
||||
FILE=$(cat text/cat1.txt)
|
||||
|
||||
if [ "${VARIABLE}" != "" ]; then
|
||||
echo "Your variable: ${VARIABLE}"
|
||||
echo "Your number: ${NUMBER}"
|
||||
echo "Your current dir: ${CURRENT_DIR}"
|
||||
# $PATH is an environment variable set by your system
|
||||
echo "Your username: ${USER}"
|
||||
echo "Your system \$PATH: ${PATH}"
|
||||
else
|
||||
echo "Please create within the quotes on line 13"
|
||||
fi
|
|
@ -0,0 +1,23 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
VIDEOS=(
|
||||
bear.mkv
|
||||
bird.mkv
|
||||
flower.mkv
|
||||
ice.mkv
|
||||
metamorphosis.mkv
|
||||
negative.mkv
|
||||
net.mkv
|
||||
pig.mkv
|
||||
stream.mkv
|
||||
surface.mkv
|
||||
water.mkv
|
||||
)
|
||||
|
||||
mkdir -p videos
|
||||
mkdir -p output
|
||||
|
||||
for video in ${VIDEOS[@]}; do
|
||||
curl "https://sixteenmillimeter.com/unix4artists/${video}" -o "videos/${video}"
|
||||
sleep 2
|
||||
done
|
|
@ -0,0 +1,28 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This script will combine the audio from one file and the
|
||||
# video from another file.
|
||||
#
|
||||
# Usage: bash ffmpeg/audio/audiovideo.sh <input audio> <input video> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
AUDIO="${1}"
|
||||
VIDEO="${2}"
|
||||
OUTPUT="${3}"
|
||||
|
||||
# Check if output file extension is .mkv
|
||||
if [[ "${OUTPUT}" != *".mkv" ]]; then
|
||||
echo "Please use an .mkv extension on your output file argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ffmpeg -i "${VIDEO}" \
|
||||
-i "${AUDIO}" \
|
||||
-c copy \
|
||||
-map 0:v:0 \
|
||||
-map 1:a:0 \
|
||||
-shortest \
|
||||
"${OUTPUT}"
|
|
@ -0,0 +1,21 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This script will extract the audio from a video
|
||||
# losslessly into a .wav file.
|
||||
#
|
||||
# Usage: bash ffmpeg/audio/extract.sh <input video> <output audio>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
INPUT="${1}"
|
||||
OUTPUT="${2}"
|
||||
|
||||
# Check if output file extension is .wav
|
||||
if [[ "${OUTPUT}" != *".wav" ]]; then
|
||||
echo "Please use an .wav extension on your output file argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ffmpeg -i "${INPUT}" -vn "${OUTPUT}"
|
|
@ -0,0 +1,35 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This script will take an audio file and an image and
|
||||
# combine them to create a video.
|
||||
#
|
||||
# Usage: bash ffmpeg/audio/stillaudio.sh <input audio> <input image> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
AUDIO="${1}"
|
||||
IMAGE="${2}"
|
||||
OUTPUT="${3}"
|
||||
|
||||
# Check if file extension is .mkv or .MKV
|
||||
if [[ "${OUTPUT}" != *".mkv" ]]; then
|
||||
echo "Please use an .mkv extension on your output file argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ffmpeg -loop 1 \
|
||||
-framerate 2 \
|
||||
-i "${IMAGE}" \
|
||||
-i "${AUDIO}" \
|
||||
-c:v libx264 \
|
||||
-preset slow \
|
||||
-tune stillimage \
|
||||
-pix_fmt yuv420p \
|
||||
-crf 12 \
|
||||
-vf "scale=1280:720:force_original_aspect_ratio=decrease,pad=1280:720:-1:-1:color=black" \
|
||||
-c:a aac \
|
||||
-b:a 192k \
|
||||
-shortest \
|
||||
"${OUTPUT}"
|
|
@ -0,0 +1,23 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# "ffprobe" is an application that comes bundled with
|
||||
# the ffmpeg installation. It will print file
|
||||
# information about the streams within video and audio
|
||||
# files.
|
||||
#
|
||||
# Usage: bash ffmpeg/basic/info.sh <file>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
if [ "${1}" == "" ]; then
|
||||
echo "Please include a path to a file as the first argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${2}" != "json" ]; then
|
||||
ffprobe -v quiet -show_format -show_streams "${1}"
|
||||
else
|
||||
ffprobe -v quiet -print_format json -show_format -show_streams "${1}"
|
||||
fi
|
|
@ -0,0 +1,55 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This command will re-encode a video into an MOV
|
||||
# container with a ProRes HQ (422) video stream and
|
||||
# audio preserved in its original format.
|
||||
#
|
||||
# -i "${INPUT}"
|
||||
# Sets the first argument, saved as variable "$INPUT"
|
||||
# as the input file that ffmpeg will re-encode. Must
|
||||
# go at the beginning of your command.
|
||||
#
|
||||
# -c:v prores_ks
|
||||
# Sets the video codec of the output video to be ProRes
|
||||
# using the "prores_kostya" library.
|
||||
#
|
||||
# -profile:v 3
|
||||
# Sets the ProRes profile to 3 or "HQ" use on the output
|
||||
# video stream. The profiles available: 0 = proxy (PR),
|
||||
# 1 = light (LT), 2 = standard (ST), 3 = high quality (HQ),
|
||||
# 4 = 4444, 5 = 4444 (XQ)
|
||||
#
|
||||
# -c:a copy
|
||||
# Copies the audio stream and preserves the format
|
||||
# and codec from the original file.
|
||||
#
|
||||
# "${OUTPUT}"
|
||||
# The output video file, which should be the last
|
||||
# argument you provide.
|
||||
#
|
||||
# More info: https://avpres.net/FFmpeg/im_ProRes.html
|
||||
# https://codecs.multimedia.cx/2012/03/a-few-words-about-my-prores-encoder/
|
||||
#
|
||||
# Usage: bash ffmpeg/basic/prores.sh <input video> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
INPUT="${1}"
|
||||
OUTPUT="${2}"
|
||||
|
||||
# Check if input and output arguments are supplied
|
||||
if [ "${INPUT}" == "" ] || [ "${OUTPUT}" == "" ]; then
|
||||
echo "Please provide input and output files as your first and second arguments"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if output file extension is .mov
|
||||
if [[ "${OUTPUT}" != *".mov" ]]; then
|
||||
echo "Please use an .mov extension on your output file argument"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Command to re-encode the input video into ProRes
|
||||
ffmpeg -i "${INPUT}" -c:v prores_ks -profile:v 3 -c:a copy "${OUTPUT}"
|
|
@ -0,0 +1,61 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This command will re-encode a video into an MP4
|
||||
# container with H264 video and AAC audio encoded to
|
||||
# 96K. Each of the arguments are explained as follows:
|
||||
#
|
||||
# -i "${INPUT}"
|
||||
# Sets the first argument, saved as variable "$INPUT"
|
||||
# as the input file that ffmpeg will re-encode. Must
|
||||
# go at the beginning of your command.
|
||||
#
|
||||
# -codec:video libx264
|
||||
# Sets the video codec to libx264, which is the library
|
||||
# ffmpeg uses to encode H264 video streams.
|
||||
#
|
||||
# -preset slow
|
||||
# Sets the preset of the H264 encoding process to run
|
||||
# slow, which can yield higher quality imagery at the
|
||||
# expense of speed. Available options:
|
||||
# ultrafast, superfast, veryfast, faster, medium (default),
|
||||
# slow, slower, veryslow, placebo
|
||||
#
|
||||
# -crf 22
|
||||
# Sets the Constant Rate Factor of the video stream,
|
||||
# which determines the data rate. The range of -crf
|
||||
# values range from 0 to 51, with 0 being visually
|
||||
# lossless and 51 being extremely compressed.
|
||||
#
|
||||
# -codec:audio aac
|
||||
# Sets the codec of the output audio stream to AAC.
|
||||
#
|
||||
# -b:a
|
||||
# Sets the data rate of the audio to 192kbit/s.
|
||||
#
|
||||
# "${OUTPUT}"
|
||||
# The output video file, which should be the last
|
||||
# argument you provide.
|
||||
#
|
||||
# Usage: bash ffmpeg/basic/reencode.sh <input video> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
INPUT="${1}"
|
||||
OUTPUT="${2}"
|
||||
|
||||
# Check if input and output arguments are supplied
|
||||
if [ "${INPUT}" == "" ] || [ "${OUTPUT}" == "" ]; then
|
||||
echo "Please provide input and output files as your first and second arguments"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if file extension is .mp4
|
||||
if [[ "${OUTPUT}" != *".mp4" ]]; then
|
||||
echo "Please use an .mp4 extension on your output file argument"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Command to re-encode the input video into H264/AAC
|
||||
ffmpeg -i "${INPUT}" -codec:video libx264 -preset slow -crf 22 -codec:audio aac -bitrate:audio 192k "${OUTPUT}"
|
|
@ -0,0 +1,74 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# Youtube: https://trac.ffmpeg.org/wiki/Encode/YouTube
|
||||
# Vimeo: https://vimeo.zendesk.com/hc/en-us/articles/360056550451-Video-and-audio-compression-guidelines
|
||||
#
|
||||
# Usage: bash ffmpeg/basic/social.sh <input video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
INPUT=`realpath "${1}"`
|
||||
FILENAME=`basename "${INPUT}"`
|
||||
FILE="${FILENAME%.*}"
|
||||
INPUTDIR=`dirname "${INPUT}"`
|
||||
|
||||
if [ "${INPUT}" == "" ]; then
|
||||
echo "Please provide an input video as your first argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
YOUTUBE="${INPUTDIR}/${FILE}-youtube.mkv"
|
||||
VIMEO="${INPUTDIR}/${FILE}-vimeo.mkv"
|
||||
TWITTER="${INPUTDIR}/${FILE}-twitter.mp4"
|
||||
INSTAGRAM="${INPUTDIR}/${FILE}-instagram.mp4"
|
||||
|
||||
# Encode a video for YouTube
|
||||
ffmpeg -i "${INPUT}" \
|
||||
-vcodec libx264 \
|
||||
-preset slow \
|
||||
-vf "pad=ceil(iw/2)*2:ceil(ih/2)*2" \
|
||||
-pix_fmt yuv420p \
|
||||
-crf 12 \
|
||||
-c:a aac \
|
||||
-b:a 192k \
|
||||
"${YOUTUBE}"
|
||||
|
||||
# Encode a video for Vimeo using the
|
||||
# recommended settings for 720p video
|
||||
ffmpeg -i "${INPUT}" \
|
||||
-vcodec libx264 \
|
||||
-preset slow \
|
||||
-pix_fmt yuv420p \
|
||||
-profile:v main \
|
||||
-b:v 7500k \
|
||||
-minrate 5000k \
|
||||
-maxrate 10000k \
|
||||
-c:a aac \
|
||||
-ar 48000 \
|
||||
"${VIMEO}"
|
||||
|
||||
# Encode video for Twitter
|
||||
ffmpeg -i "${INPUT}" \
|
||||
-pix_fmt yuv420p \
|
||||
-vcodec libx264 \
|
||||
-acodec aac \
|
||||
-vb 2048k\
|
||||
-minrate 1024k \
|
||||
-maxrate 4096k \
|
||||
-bufsize 1024k \
|
||||
-ar 44100 \
|
||||
-ac 2 \
|
||||
-strict experimental \
|
||||
"${TWITTER}"
|
||||
|
||||
# Crop and encode for Instagram
|
||||
ffmpeg -i "${INPUT}" \
|
||||
-vf "crop=w='min(iw\,ih)':h='min(iw\,ih)',setsar=1" \
|
||||
-framerate 30 \
|
||||
-vcodec mpeg4 \
|
||||
-vb 8000k \
|
||||
-strict experimental \
|
||||
-q:v 0 \
|
||||
"${INSTAGRAM}"
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# These commands print out the formats and codecs that
|
||||
# your installation of ffmpeg supports. You can customize
|
||||
# ffmpeg to support additional formats, codecs and features
|
||||
# by using installation options or flags when compiling
|
||||
# from source.
|
||||
#
|
||||
# Mac (Homebrew): https://gist.github.com/Piasy/b5dfd5c048eb69d1b91719988c0325d8
|
||||
# Linux & Windows: https://trac.ffmpeg.org/wiki/CompilationGuide/Ubuntu
|
||||
#
|
||||
# Usage: bash ffmpeg/format/support.sh
|
||||
#
|
||||
#####################################################
|
||||
|
||||
echo "Formats your FFMPEG install supports:"
|
||||
ffmpeg -formats
|
||||
|
||||
sleep 10
|
||||
|
||||
echo "Codecs your FFMPEG install supports:"
|
||||
ffmpeg -codecs
|
|
@ -0,0 +1,24 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This script will trim your video to a 5 second length
|
||||
# starting 2 seconds into it and write the output as a
|
||||
# ProRes video file.
|
||||
#
|
||||
# Usage: bash ffmpeg/basic/trim.sh <input video> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
INPUT="${1}"
|
||||
OUTPUT="${2}"
|
||||
|
||||
# Check if output file extension is .mov
|
||||
if [[ "${OUTPUT}" != *".mov" ]]; then
|
||||
echo "Please use an .mov extension on your output file argument"
|
||||
exit 2
|
||||
fi
|
||||
|
||||
# Trim the video using the "-t" argument with the value 5 (seconds)
|
||||
# and starting at 00:00:02 (h:m:s) using the "-ss" seeking argument
|
||||
ffmpeg -ss 00:00:02 -i "${INPUT}" -t 5 -c:v prores_ks -profile:v 3 -c:a copy "${OUTPUT}"
|
|
@ -0,0 +1,41 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# Bipack.sh will simulate the optical printing effect
|
||||
# of superimposing video A over video B with a third
|
||||
# video (the matte) as the alpha layer.
|
||||
#
|
||||
# Usage: bash ffmpeg/filter/bipack.sh <input video A> <input video B> <input video matte> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
A=${1}
|
||||
B=${2}
|
||||
MATTE=${3}
|
||||
OUTPUT_FILE=${4}
|
||||
|
||||
CONTRAST=100
|
||||
W=1280
|
||||
H=720
|
||||
RATE=24
|
||||
|
||||
echo "Running bipack on image sources ${A} and ${B} with ${MATTE} as the matte layer..."
|
||||
|
||||
time ffmpeg -y -i $A -i $B -i $MATTE \
|
||||
-filter_complex "
|
||||
color=0x000000:size=${W}x${H}, format=rgb24[bla];
|
||||
[0] fps=${RATE},scale=${W}:${H}:force_original_aspect_ratio=decrease,format=rgb24 [a];
|
||||
[1] fps=${RATE},scale=${W}:${H}:force_original_aspect_ratio=decrease,format=rgb24 [b];
|
||||
[2] fps=${RATE},scale=${W}:${H}:force_original_aspect_ratio=decrease,format=gray,
|
||||
smartblur=1, eq=contrast=$CONTRAST, format=rgb24 [maska];
|
||||
[2] fps=${RATE},scale=${W}:${H}:force_original_aspect_ratio=decrease,format=gray,
|
||||
smartblur=1, eq=contrast=$CONTRAST, negate, format=rgb24 [maskb];
|
||||
[bla][a][maska] maskedmerge, format=rgb24 [pass1];
|
||||
[pass1][b][maskb] maskedmerge, format=rgb24
|
||||
" \
|
||||
-r $RATE \
|
||||
-c:v prores_ks \
|
||||
-profile:v 3 \
|
||||
-shortest \
|
||||
$OUTPUT_FILE
|
|
@ -0,0 +1,58 @@
|
|||
#!/bin/bash
|
||||
|
||||
set -e
|
||||
|
||||
W=1280
|
||||
H=720
|
||||
|
||||
A=${1}
|
||||
B=${2}
|
||||
MATTE=${3}
|
||||
OUTPUT=${4}
|
||||
|
||||
MATTE1=matte1.mov
|
||||
MATTE2=matte2.mov
|
||||
PASS1=pass1.mov
|
||||
PASS2=pass2.mov
|
||||
|
||||
echo "Generating mattes from $MATTE..."
|
||||
|
||||
ffmpeg -y -i "$MATTE" -vf eq=saturation=0:contrast=100,smartblur=1 -c:v prores_ks -profile:v 4 "$MATTE1"
|
||||
ffmpeg -y -i "$MATTE1" -vf negate -c:v prores_ks -profile:v 4 "$MATTE2"
|
||||
|
||||
echo "Applying matte to $A..."
|
||||
|
||||
ffmpeg -y -i "$A" -i "$MATTE1" \
|
||||
-filter_complex 'color=0x000000:size=1280x720,format=rgb24[bla];[bla][0][1]maskedmerge' \
|
||||
-c:v prores_ks \
|
||||
-profile:v 4 \
|
||||
-shortest \
|
||||
"$PASS1"
|
||||
|
||||
echo "Applying matte to $B..."
|
||||
|
||||
ffmpeg -y -i "$B" -i "$MATTE2" \
|
||||
-filter_complex 'color=0x000000:size=1280x720,format=rgb24[bla];[bla][0][1]maskedmerge' \
|
||||
-c:v prores_ks \
|
||||
-profile:v 4 \
|
||||
-shortest \
|
||||
"$PASS2"
|
||||
|
||||
echo "Cleaning up tmp matte files..."
|
||||
|
||||
rm "$MATTE1"
|
||||
rm "$MATTE2"
|
||||
|
||||
echo "Combining matted layers together into $OUTPUT_FILE..."
|
||||
|
||||
ffmpeg -y -i "$PASS1" -i "$PASS2" \
|
||||
-filter_complex "[0][1]blend=all_mode='lighten'" \
|
||||
-c:v prores_ks \
|
||||
-profile:v 3 \
|
||||
-shortest \
|
||||
"$OUTPUT"
|
||||
|
||||
echo "Cleaning up temp files..."
|
||||
|
||||
rm "$PASS1"
|
||||
rm "$PASS2"
|
|
@ -0,0 +1,27 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This script will increase the contrast of an input
|
||||
# video by 2 (acceptable values -1000 to 1000) and
|
||||
# increases the brightness by 0.4 (-1 to 1)
|
||||
#
|
||||
# Usage: bash ffmpeg/filter/brightness.sh <input video> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
INPUT="${1}"
|
||||
OUTPUT="${2}"
|
||||
|
||||
# Check if output file extension is .mov
|
||||
if [[ "${OUTPUT}" != *".mov" ]]; then
|
||||
echo "Please use an .mov extension on your output file argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ffmpeg -i "${INPUT}" \
|
||||
-vf eq=contrast=2:brightness=0.4 \
|
||||
-c:v prores_ks \
|
||||
-profile:v 3 \
|
||||
"${OUTPUT}"
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This script will convert a color video to black &
|
||||
# white by reducing color saturation to 0.
|
||||
#
|
||||
# Usage: bash ffmpeg/filter/desaturate.sh <input video> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
INPUT="${1}"
|
||||
OUTPUT="${2}"
|
||||
|
||||
# Check if output file extension is .mov
|
||||
if [[ "${OUTPUT}" != *".mov" ]]; then
|
||||
echo "Please use an .mov extension on your output file argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ffmpeg -i "${INPUT}" \
|
||||
-vf hue=s=0 \
|
||||
-c:v prores_ks \
|
||||
-profile:v 3 \
|
||||
"${OUTPUT}"
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This script will convert a color video to black &
|
||||
# white by converting to grayscale format.
|
||||
#
|
||||
# Usage: bash ffmpeg/filter/grayscale.sh <input video> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
INPUT="${1}"
|
||||
OUTPUT="${2}"
|
||||
|
||||
# Check if output file extension is .mov
|
||||
if [[ "${OUTPUT}" != *".mov" ]]; then
|
||||
echo "Please use an .mov extension on your output file argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ffmpeg -i "${INPUT}" \
|
||||
-vf format=gray \
|
||||
-c:v prores_ks \
|
||||
-profile:v 3 \
|
||||
"${OUTPUT}"
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This script will invert all colors of a video and
|
||||
# save the output in a ProRes video.
|
||||
#
|
||||
# Usage: bash ffmpeg/filter/negative.sh <input video> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
INPUT="${1}"
|
||||
OUTPUT="${2}"
|
||||
|
||||
# Check if output file extension is .mov
|
||||
if [[ "${OUTPUT}" != *".mov" ]]; then
|
||||
echo "Please use an .mov extension on your output file argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
ffmpeg -i "${INPUT}" \
|
||||
-vf negate \
|
||||
-c:v prores_ks \
|
||||
-profile:v 3 \
|
||||
"${OUTPUT}"
|
|
@ -0,0 +1,98 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This script will create a 10 second title and
|
||||
# overlay it on a video with a blend mode:
|
||||
#
|
||||
# addition
|
||||
# grainmerge
|
||||
# and
|
||||
# average
|
||||
# darken
|
||||
# difference
|
||||
# grainextract
|
||||
# divide
|
||||
# dodge
|
||||
# freeze
|
||||
# exlusion
|
||||
# extremity
|
||||
# glow
|
||||
# hardlight
|
||||
# hardmix
|
||||
# heat
|
||||
# lighten
|
||||
# linearlight
|
||||
# multiply
|
||||
# multiply128
|
||||
# negation
|
||||
# normal
|
||||
# or
|
||||
# overlay
|
||||
# pheonix
|
||||
# pinlight
|
||||
# reflect
|
||||
# screen
|
||||
# softlight
|
||||
# subtract
|
||||
# vividlight
|
||||
# xor
|
||||
#
|
||||
# Usage: bash ffmpeg/filter/title.sh <title text> <input video> <output video> <blendmode> "invert" (optional)
|
||||
#
|
||||
#####################################################
|
||||
|
||||
|
||||
W=720
|
||||
H=480
|
||||
|
||||
TEXT="${1}"
|
||||
INPUT="${2}"
|
||||
OUTPUT="${3}"
|
||||
BLENDMODE="${4}"
|
||||
|
||||
# Check if output file extension is .mov
|
||||
if [[ "${OUTPUT}" != *".mov" ]]; then
|
||||
echo "Please use an .mov extension on your output file argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ "${BLENDMODE}" == "" ]; then
|
||||
BLENDMODE="multiply"
|
||||
fi
|
||||
|
||||
if [ "${5}" == "invert" ]; then
|
||||
convert -size ${W}x${H} \
|
||||
-background white \
|
||||
-fill black \
|
||||
-gravity Center \
|
||||
-weight 700 \
|
||||
-pointsize 100 \
|
||||
label:"${TEXT}" \
|
||||
title.png
|
||||
else
|
||||
convert -size ${W}x${H} \
|
||||
-background black \
|
||||
-fill white \
|
||||
-gravity Center \
|
||||
-weight 700 \
|
||||
-pointsize 100 \
|
||||
label:"${TEXT}" \
|
||||
title.png
|
||||
fi
|
||||
|
||||
ffmpeg -y -loop 1 \
|
||||
-framerate 24 \
|
||||
-f image2 \
|
||||
-i title.png \
|
||||
-s ${W}x${H} \
|
||||
-c:v prores_ks \
|
||||
-profile:v 3 \
|
||||
-t 10 \
|
||||
"title.mov"
|
||||
|
||||
ffmpeg -i "${INPUT}" -i "title.mov" -filter_complex "[0][1]blend=${BLENDMODE}" "${OUTPUT}"
|
||||
|
||||
# Clean up by removing the image and title video
|
||||
rm title.png
|
||||
rm title.mov
|
|
@ -0,0 +1,30 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This script splits a video into an image sequence
|
||||
# and then stitches the image sequence back into a
|
||||
# ProRes video.
|
||||
#
|
||||
# Usage: bash ffmpeg/frames/basic.sh <input video> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
INPUT="${1}"
|
||||
OUTPUT="${2}"
|
||||
|
||||
# Check if output file extension is .mov
|
||||
if [[ "${OUTPUT}" != *".mov" ]]; then
|
||||
echo "Please use an .mov extension on your output file argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p frames
|
||||
|
||||
ffmpeg -i "${INPUT}" frames/frame-%06d.png
|
||||
|
||||
sleep 20
|
||||
|
||||
ffmpeg -f image2 -i frames/frame-%06d.png -c:v prores_ks -profile:v 3 "${OUTPUT}"
|
||||
|
||||
rm -rf frames
|
|
@ -0,0 +1,41 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# Frameloom is a script that exports all frames from
|
||||
# two videos and alternates them in
|
||||
#
|
||||
# Usage: bash ffmpeg/frames/frameloom.sh <input video1> <input video2> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
TMPDIR=`mktemp -d`
|
||||
i=0
|
||||
|
||||
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] ;
|
||||
then
|
||||
echo "Not enough arguments supplied"
|
||||
fi
|
||||
|
||||
# Check if output file extension is .mov
|
||||
if [[ "${3}" != *".mov" ]]; then
|
||||
echo "Please use an .mov extension on your output file argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p $TMPDIR
|
||||
|
||||
ffmpeg -i "$1" -compression_algo raw -pix_fmt rgb24 "${TMPDIR}export-%08d_a.tif"
|
||||
ffmpeg -i "$2" -compression_algo raw -pix_fmt rgb24 "${TMPDIR}export-%08d_b.tif"
|
||||
|
||||
#rm -r $TMP
|
||||
|
||||
for filename in ${TMPDIR}*.tif; do
|
||||
value=`printf %08d $i`
|
||||
mv "$filename" "${TMPDIR}render_${value}.tif"
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
|
||||
ffmpeg -r 24 -f image2 -s 1280x720 -i "${TMPDIR}render_%08d.tif" -c:v prores_ks -profile:v 3 -y "$3"
|
||||
|
||||
rm -r "$TMPDIR"
|
|
@ -0,0 +1,39 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This script exports all frames of your video into
|
||||
# a directory named "frames" and then runs a convert
|
||||
# command which does edge detection on each frame.
|
||||
# Then all frames are stitched back into a ProRes
|
||||
# video.
|
||||
#
|
||||
# Usage: bash ffmpeg/frames/loop.sh <input video> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
INPUT="${1}"
|
||||
OUTPUT="${2}"
|
||||
|
||||
# Check if output file extension is .mov
|
||||
if [[ "${OUTPUT}" != *".mov" ]]; then
|
||||
echo "Please use an .mov extension on your output file argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p frames
|
||||
|
||||
ffmpeg -i "${INPUT}" frames/frame-%06d.png
|
||||
|
||||
FRAMES=frames/*.png
|
||||
|
||||
for frame in ${FRAMES}; do
|
||||
echo "Running edge detection on $frame..."
|
||||
convert "${frame}" -edge 1 "${frame}"
|
||||
done
|
||||
|
||||
sleep 10
|
||||
|
||||
ffmpeg -f image2 -i frames/frame-%06d.png -c:v prores_ks -profile:v 3 "${OUTPUT}"
|
||||
|
||||
rm -rf frames
|
|
@ -0,0 +1,53 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This script will export your video to frames and
|
||||
# use the application "primitive" to reproduce the
|
||||
# image with polygonal primitive shapes. Then the
|
||||
# converted frames are p
|
||||
#
|
||||
# The modes available for the -m argument are:
|
||||
# 0=combo
|
||||
# 1=triangle
|
||||
# 2=rect
|
||||
# 3=ellipse
|
||||
# 4=circle
|
||||
# 5=rotatedrect
|
||||
# 6=beziers
|
||||
# 7=rotatedellipse
|
||||
# 8=polygon
|
||||
#
|
||||
# primitive repo : https://github.com/fogleman/primitive
|
||||
#
|
||||
# Usage: bash ffmpeg/frames/primitive.sh <input video> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
INPUT="${1}"
|
||||
OUTPUT="${2}"
|
||||
|
||||
MODE=1
|
||||
NUMBER=100
|
||||
|
||||
# Check if output file extension is .mov
|
||||
if [[ "${OUTPUT}" != *".mov" ]]; then
|
||||
echo "Please use an .mov extension on your output file argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p frames
|
||||
|
||||
ffmpeg -i "${INPUT}" frames/frame-%06d.png
|
||||
|
||||
FRAMES=frames/*.png
|
||||
|
||||
for frame in ${FRAMES}; do
|
||||
echo "Processing $frame with primitive..."
|
||||
# Run the "primitive" application on every frame
|
||||
primitive -i "${frame}" -o "${frame}" -n 200 -m 4
|
||||
done
|
||||
|
||||
ffmpeg -f image2 -i frames/frame-%06d.png -c:v prores_ks -profile:v 3 "${OUTPUT}"
|
||||
|
||||
rm -rf frames
|
|
@ -0,0 +1,42 @@
|
|||
#!/bin/bash -e
|
||||
|
||||
#####################################################
|
||||
#
|
||||
# This script will create a 15 second title with a
|
||||
# 5 second fade in and a 5 second fade out
|
||||
#
|
||||
# Usage: bash im/title.sh <title text> <output video>
|
||||
#
|
||||
#####################################################
|
||||
|
||||
TEXT="${1}"
|
||||
OUTPUT="${2}"
|
||||
|
||||
# Check if output file extension is .mov
|
||||
if [[ "${OUTPUT}" != *".mov" ]]; then
|
||||
echo "Please use an .mov extension on your output file argument"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
convert -size 1280x720 \
|
||||
-background black \
|
||||
-fill white \
|
||||
-gravity Center \
|
||||
-weight 700 \
|
||||
-pointsize 200 \
|
||||
label:"${TEXT}" \
|
||||
title.png
|
||||
|
||||
ffmpeg -loop 1 \
|
||||
-framerate 24 \
|
||||
-f image2 \
|
||||
-i title.png \
|
||||
-s 1280x720 \
|
||||
-vf "fade=t=in:st=0:d=5,fade=t=out:st=10:d=5" \
|
||||
-c:v prores_ks \
|
||||
-profile:v 3 \
|
||||
-t 15 \
|
||||
"${OUTPUT}"
|
||||
|
||||
# Clean up by removing the image
|
||||
rm title.png
|
After Width: | Height: | Size: 792 KiB |
After Width: | Height: | Size: 26 KiB |
After Width: | Height: | Size: 309 KiB |
After Width: | Height: | Size: 160 KiB |
After Width: | Height: | Size: 308 KiB |
After Width: | Height: | Size: 280 KiB |
After Width: | Height: | Size: 538 KiB |
After Width: | Height: | Size: 227 KiB |
After Width: | Height: | Size: 139 KiB |
|
@ -0,0 +1,84 @@
|
|||
'use strict';
|
||||
|
||||
const PORT = typeof process.env.PORT !== 'undefined' ? parseInt(process.env.PORT) : 3000;
|
||||
|
||||
const express = require('express');
|
||||
const bodyParser = require('body-parser');
|
||||
const { execSync } = require('child_process');
|
||||
|
||||
const app = express();
|
||||
|
||||
const HOME = `<html>
|
||||
<head><title>FFMPEG demo</title></head>
|
||||
<body>
|
||||
<form method="POST">
|
||||
<input name="title" />
|
||||
<input type="submit" />
|
||||
</form>
|
||||
</body>
|
||||
</html>`;
|
||||
|
||||
const VIDEO = `<html>
|
||||
<head><title>FFMPEG demo</title></head>
|
||||
<body>
|
||||
<video controls autoplay>
|
||||
<source src="/title.mp4" type="video/mp4" />
|
||||
</video>
|
||||
</body>
|
||||
</html>`
|
||||
|
||||
function generateTitle (text) {
|
||||
const title = `convert \
|
||||
-size 720x480 \
|
||||
-background black \
|
||||
-fill white \
|
||||
-gravity Center \
|
||||
-weight 700 \
|
||||
-pointsize 100 \
|
||||
label:"${text}" \
|
||||
title.png`;
|
||||
|
||||
const ffmpeg = `ffmpeg -y \
|
||||
-loop 1 \
|
||||
-framerate 24 \
|
||||
-f image2 \
|
||||
-i title.png \
|
||||
-s 720x480 \
|
||||
-vf "fade=t=in:st=0:d=5,fade=t=out:st=10:d=5" \
|
||||
-c:v libx264 \
|
||||
-preset slow \
|
||||
-crf 22 \
|
||||
-f mp4 \
|
||||
-strict -2 \
|
||||
-pix_fmt yuv420p \
|
||||
-t 15 \
|
||||
-an \
|
||||
title.mp4`;
|
||||
|
||||
const cleanup = `rm title.png`;
|
||||
|
||||
execSync(title);
|
||||
execSync(ffmpeg);
|
||||
execSync(cleanup);
|
||||
}
|
||||
|
||||
app.use(express.static('./'));
|
||||
app.use(bodyParser.urlencoded({ extended : true }));
|
||||
|
||||
app.get('/', (req, res, next) => {
|
||||
res.end(HOME);
|
||||
return next();
|
||||
});
|
||||
|
||||
app.post('/', (req, res, next) => {
|
||||
|
||||
generateTitle(req.body.title);
|
||||
|
||||
res.end(VIDEO);
|
||||
return next();
|
||||
});
|
||||
|
||||
app.listen(PORT, () => {
|
||||
console.log(`Server running on port ${PORT}`);
|
||||
execSync('rm -f title.mp4');
|
||||
});
|
|
@ -0,0 +1,860 @@
|
|||
{
|
||||
"name": "ffmpeg-demo",
|
||||
"version": "0.0.1",
|
||||
"lockfileVersion": 2,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "ffmpeg-demo",
|
||||
"version": "0.0.1",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
"express": "^4.17.1"
|
||||
}
|
||||
},
|
||||
"node_modules/accepts": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
|
||||
"dependencies": {
|
||||
"mime-types": "~2.1.24",
|
||||
"negotiator": "0.6.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
|
||||
},
|
||||
"node_modules/body-parser": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
|
||||
"integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
|
||||
"dependencies": {
|
||||
"bytes": "3.1.0",
|
||||
"content-type": "~1.0.4",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"http-errors": "1.7.2",
|
||||
"iconv-lite": "0.4.24",
|
||||
"on-finished": "~2.3.0",
|
||||
"qs": "6.7.0",
|
||||
"raw-body": "2.4.0",
|
||||
"type-is": "~1.6.17"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/bytes": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/content-disposition": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
|
||||
"integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
|
||||
"dependencies": {
|
||||
"safe-buffer": "5.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/content-type": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
|
||||
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/cookie-signature": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
|
||||
},
|
||||
"node_modules/debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"dependencies": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/destroy": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||
},
|
||||
"node_modules/ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||
},
|
||||
"node_modules/encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
|
||||
},
|
||||
"node_modules/etag": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/express": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
|
||||
"integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
|
||||
"dependencies": {
|
||||
"accepts": "~1.3.7",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.19.0",
|
||||
"content-disposition": "0.5.3",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.4.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"finalhandler": "~1.1.2",
|
||||
"fresh": "0.5.2",
|
||||
"merge-descriptors": "1.0.1",
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "~2.3.0",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"proxy-addr": "~2.0.5",
|
||||
"qs": "6.7.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"safe-buffer": "5.1.2",
|
||||
"send": "0.17.1",
|
||||
"serve-static": "1.14.1",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": "~1.5.0",
|
||||
"type-is": "~1.6.18",
|
||||
"utils-merge": "1.0.1",
|
||||
"vary": "~1.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/finalhandler": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
|
||||
"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
|
||||
"dependencies": {
|
||||
"debug": "2.6.9",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"on-finished": "~2.3.0",
|
||||
"parseurl": "~1.3.3",
|
||||
"statuses": "~1.5.0",
|
||||
"unpipe": "~1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/forwarded": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
|
||||
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/http-errors": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
|
||||
"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
|
||||
"dependencies": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.3",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"dependencies": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=0.10.0"
|
||||
}
|
||||
},
|
||||
"node_modules/inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"node_modules/ipaddr.js": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/merge-descriptors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
|
||||
},
|
||||
"node_modules/methods": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
|
||||
"bin": {
|
||||
"mime": "cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=4"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-db": {
|
||||
"version": "1.47.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz",
|
||||
"integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/mime-types": {
|
||||
"version": "2.1.30",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz",
|
||||
"integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==",
|
||||
"dependencies": {
|
||||
"mime-db": "1.47.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"node_modules/negotiator": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/on-finished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
|
||||
"dependencies": {
|
||||
"ee-first": "1.1.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/path-to-regexp": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
|
||||
},
|
||||
"node_modules/proxy-addr": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
|
||||
"integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
|
||||
"dependencies": {
|
||||
"forwarded": "~0.1.2",
|
||||
"ipaddr.js": "1.9.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.10"
|
||||
}
|
||||
},
|
||||
"node_modules/qs": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
|
||||
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/raw-body": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
|
||||
"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
|
||||
"dependencies": {
|
||||
"bytes": "3.1.0",
|
||||
"http-errors": "1.7.2",
|
||||
"iconv-lite": "0.4.24",
|
||||
"unpipe": "1.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"node_modules/safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"node_modules/send": {
|
||||
"version": "0.17.1",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
|
||||
"integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
|
||||
"dependencies": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"destroy": "~1.0.4",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "~1.7.2",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.1",
|
||||
"on-finished": "~2.3.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "~1.5.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/send/node_modules/ms": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
|
||||
},
|
||||
"node_modules/serve-static": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
|
||||
"integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
|
||||
"dependencies": {
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"parseurl": "~1.3.3",
|
||||
"send": "0.17.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.8.0"
|
||||
}
|
||||
},
|
||||
"node_modules/setprototypeof": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
|
||||
},
|
||||
"node_modules/statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/toidentifier": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
|
||||
"engines": {
|
||||
"node": ">=0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||
"dependencies": {
|
||||
"media-typer": "0.3.0",
|
||||
"mime-types": "~2.1.24"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
},
|
||||
"node_modules/unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
},
|
||||
"node_modules/utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=",
|
||||
"engines": {
|
||||
"node": ">= 0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=",
|
||||
"engines": {
|
||||
"node": ">= 0.8"
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"accepts": {
|
||||
"version": "1.3.7",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
|
||||
"integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
|
||||
"requires": {
|
||||
"mime-types": "~2.1.24",
|
||||
"negotiator": "0.6.2"
|
||||
}
|
||||
},
|
||||
"array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI="
|
||||
},
|
||||
"body-parser": {
|
||||
"version": "1.19.0",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
|
||||
"integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
|
||||
"requires": {
|
||||
"bytes": "3.1.0",
|
||||
"content-type": "~1.0.4",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"http-errors": "1.7.2",
|
||||
"iconv-lite": "0.4.24",
|
||||
"on-finished": "~2.3.0",
|
||||
"qs": "6.7.0",
|
||||
"raw-body": "2.4.0",
|
||||
"type-is": "~1.6.17"
|
||||
}
|
||||
},
|
||||
"bytes": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
|
||||
"integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg=="
|
||||
},
|
||||
"content-disposition": {
|
||||
"version": "0.5.3",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
|
||||
"integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.1.2"
|
||||
}
|
||||
},
|
||||
"content-type": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
|
||||
"integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA=="
|
||||
},
|
||||
"cookie": {
|
||||
"version": "0.4.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
|
||||
"integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg=="
|
||||
},
|
||||
"cookie-signature": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
"integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw="
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"depd": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
|
||||
"integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak="
|
||||
},
|
||||
"destroy": {
|
||||
"version": "1.0.4",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
|
||||
"integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA="
|
||||
},
|
||||
"ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0="
|
||||
},
|
||||
"encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k="
|
||||
},
|
||||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg="
|
||||
},
|
||||
"etag": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc="
|
||||
},
|
||||
"express": {
|
||||
"version": "4.17.1",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
|
||||
"integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
|
||||
"requires": {
|
||||
"accepts": "~1.3.7",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.19.0",
|
||||
"content-disposition": "0.5.3",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.4.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"finalhandler": "~1.1.2",
|
||||
"fresh": "0.5.2",
|
||||
"merge-descriptors": "1.0.1",
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "~2.3.0",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"proxy-addr": "~2.0.5",
|
||||
"qs": "6.7.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"safe-buffer": "5.1.2",
|
||||
"send": "0.17.1",
|
||||
"serve-static": "1.14.1",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": "~1.5.0",
|
||||
"type-is": "~1.6.18",
|
||||
"utils-merge": "1.0.1",
|
||||
"vary": "~1.1.2"
|
||||
}
|
||||
},
|
||||
"finalhandler": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
|
||||
"integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"on-finished": "~2.3.0",
|
||||
"parseurl": "~1.3.3",
|
||||
"statuses": "~1.5.0",
|
||||
"unpipe": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"forwarded": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz",
|
||||
"integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ="
|
||||
},
|
||||
"fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac="
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "1.7.2",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
|
||||
"integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
|
||||
"requires": {
|
||||
"depd": "~1.1.2",
|
||||
"inherits": "2.0.3",
|
||||
"setprototypeof": "1.1.1",
|
||||
"statuses": ">= 1.5.0 < 2",
|
||||
"toidentifier": "1.0.0"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
|
||||
"integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4="
|
||||
},
|
||||
"ipaddr.js": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
|
||||
},
|
||||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g="
|
||||
},
|
||||
"merge-descriptors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||
"integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E="
|
||||
},
|
||||
"methods": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||
"integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4="
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.47.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.47.0.tgz",
|
||||
"integrity": "sha512-QBmA/G2y+IfeS4oktet3qRZ+P5kPhCKRXxXnQEudYqUaEioAU1/Lq2us3D/t1Jfo4hE9REQPrbB7K5sOczJVIw=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.30",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.30.tgz",
|
||||
"integrity": "sha512-crmjA4bLtR8m9qLpHvgxSChT+XoSlZi8J4n/aIdn3z92e/U47Z0V/yl+Wh9W046GgFVAmoNR/fmdbZYcSSIUeg==",
|
||||
"requires": {
|
||||
"mime-db": "1.47.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.2",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
|
||||
"integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw=="
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.3.0",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
|
||||
"integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=",
|
||||
"requires": {
|
||||
"ee-first": "1.1.1"
|
||||
}
|
||||
},
|
||||
"parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
|
||||
},
|
||||
"path-to-regexp": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w="
|
||||
},
|
||||
"proxy-addr": {
|
||||
"version": "2.0.6",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.6.tgz",
|
||||
"integrity": "sha512-dh/frvCBVmSsDYzw6n926jv974gddhkFPfiN8hPOi30Wax25QZyZEGveluCgliBnqmuM+UJmBErbAUFIoDbjOw==",
|
||||
"requires": {
|
||||
"forwarded": "~0.1.2",
|
||||
"ipaddr.js": "1.9.1"
|
||||
}
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.7.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
|
||||
"integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ=="
|
||||
},
|
||||
"range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
|
||||
},
|
||||
"raw-body": {
|
||||
"version": "2.4.0",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
|
||||
"integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
|
||||
"requires": {
|
||||
"bytes": "3.1.0",
|
||||
"http-errors": "1.7.2",
|
||||
"iconv-lite": "0.4.24",
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
|
||||
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"send": {
|
||||
"version": "0.17.1",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
|
||||
"integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "~1.1.2",
|
||||
"destroy": "~1.0.4",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "~1.7.2",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.1",
|
||||
"on-finished": "~2.3.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "~1.5.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "2.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
|
||||
"integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve-static": {
|
||||
"version": "1.14.1",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
|
||||
"integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
|
||||
"requires": {
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"parseurl": "~1.3.3",
|
||||
"send": "0.17.1"
|
||||
}
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
|
||||
"integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw=="
|
||||
},
|
||||
"statuses": {
|
||||
"version": "1.5.0",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
|
||||
"integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow="
|
||||
},
|
||||
"toidentifier": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
|
||||
"integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw=="
|
||||
},
|
||||
"type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||
"requires": {
|
||||
"media-typer": "0.3.0",
|
||||
"mime-types": "~2.1.24"
|
||||
}
|
||||
},
|
||||
"unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
"integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw="
|
||||
},
|
||||
"utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
"integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM="
|
||||
},
|
||||
"vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw="
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,15 @@
|
|||
{
|
||||
"name": "ffmpeg-demo",
|
||||
"version": "0.0.1",
|
||||
"description": "Demo of ffmpeg used within node.js",
|
||||
"main": "index.js",
|
||||
"scripts": {
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "mmcwilliams",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"body-parser": "^1.19.0",
|
||||
"express": "^4.17.1"
|
||||
}
|
||||
}
|
|
@ -0,0 +1,111 @@
|
|||
#!/bin/bash
|
||||
|
||||
#################################
|
||||
#
|
||||
# From https://gist.github.com/sixteenmillimeter/d6443c6b18a7d143b3695dd9d79c3c22
|
||||
#
|
||||
# Instructions
|
||||
#
|
||||
# First, install ffmpeg and youtube-dl
|
||||
#
|
||||
# https://ffmpeg.org/download.html
|
||||
# https://ytdl-org.github.io/youtube-dl/download.html
|
||||
#
|
||||
# To capture a stream at https://yoururl and save to a dated, named TS file:
|
||||
#
|
||||
# bash capture.sh https://yoururl streamfilename
|
||||
#
|
||||
# Will create file streamfile_STARTDATE.ts and streamfilename.txt containing stream metadata.
|
||||
#
|
||||
# To capture stream and convert to an MKV file after:
|
||||
#
|
||||
# bash capture.sh https://streamurl streamfilename "convert"
|
||||
#
|
||||
# Will create TS file and streamfile_STARTDATE_to_FINISHDATE.mkv after capture complete.
|
||||
#
|
||||
# Note: Since this is capturing from a M3U8 stream you may end up retrieving more of earlier
|
||||
# parts of the stream than the metadata will indicate. This will depend on the service
|
||||
# you are capturing from.
|
||||
#
|
||||
#################################
|
||||
|
||||
THREADS="1" #set number of threads for process or comment out to utilize 100% of CPU
|
||||
QUALITY=-1 #-2 for second best, -1 for best
|
||||
|
||||
INPUT="${1}"
|
||||
OUTPUT="${2}" # filepath without extension
|
||||
|
||||
if [ "${OUTPUT}" == "" ]; then
|
||||
OUTPUT=`basename "${INPUT}"`
|
||||
fi
|
||||
|
||||
if [ "${THREADS}" == "" ]; then
|
||||
THREADS_ARG=""
|
||||
else
|
||||
THREADS_ARG="-threads ${THREADS}"
|
||||
fi
|
||||
|
||||
METADATA="${OUTPUT}.txt"
|
||||
FORMATS=`mktemp`
|
||||
|
||||
# Show the available streams using youtube-dl
|
||||
youtube-dl --list-formats "${INPUT}" > "${FORMATS}"
|
||||
|
||||
FORMAT_FULL=`tail ${QUALITY} "${FORMATS}" | head -1`
|
||||
FORMAT=`echo "${FORMAT_FULL}" | awk -F" " '{print $1}'`
|
||||
M3U8=`youtube-dl -f "${FORMAT}" -g "${INPUT}"`
|
||||
STARTED=`date "+%F-%T-%Z"`
|
||||
OUTPUT_TS="${OUTPUT}_${STARTED}.ts"
|
||||
|
||||
echo "Stream: ${INPUT}"
|
||||
echo "Format: ${FORMAT_FULL}"
|
||||
echo "Output: ${OUTPUT_TS}"
|
||||
|
||||
if [ -f "${METADATA}" ]; then
|
||||
echo " " >> "${METADATA}"
|
||||
else
|
||||
echo "==========================" > "${METADATA}"
|
||||
echo " " >> "${METADATA}"
|
||||
fi
|
||||
|
||||
echo "Stream : ${INPUT}" >> "${METADATA}"
|
||||
echo "M3U8 : ${M3U8}" >> "${METADATA}"
|
||||
echo "Format : ${FORMAT_FULL}" >> "${METADATA}"
|
||||
echo "Output : ${OUTPUT_TS}" >> "${METADATA}"
|
||||
echo "Started : ${STARTED}" >> "${METADATA}"
|
||||
|
||||
echo "Starting capture, press 'q' to finish"
|
||||
|
||||
# capture with no console output
|
||||
ffmpeg -i "${M3U8}" \
|
||||
-loglevel warning \
|
||||
-hide_banner ${THREADS_ARG} \
|
||||
-c copy \
|
||||
"${OUTPUT_TS}"
|
||||
|
||||
FINISHED=`date "+%F-%T-%Z"`
|
||||
echo "Finished capturing at ${FINISHED}"
|
||||
echo "Finished : ${FINISHED}" >> "${METADATA}"
|
||||
|
||||
if [ "${3}" == "convert" ]; then
|
||||
OUTPUT_MKV="${OUTPUT}_${STARTED}_to_${FINISHED}.mkv"
|
||||
echo "Creating MKV file ${OUTPUT_MKV}..."
|
||||
# put video in an MKV wrapper as is (not really a conversion)
|
||||
ffmpeg -i "${OUTPUT_TS}" \
|
||||
-loglevel warning \
|
||||
-hide_banner ${THREADS_ARG} \
|
||||
-map 0 \
|
||||
-c copy \
|
||||
"${OUTPUT_MKV}"
|
||||
|
||||
echo "Created ${OUTPUT_MKV}"
|
||||
echo "MKV : ${OUTPUT_MKV}" >> "${METADATA}"
|
||||
fi
|
||||
|
||||
echo " " >> "${METADATA}"
|
||||
echo "==========================" >> "${METADATA}"
|
||||
echo "Cleaning up..."
|
||||
# cleanup
|
||||
rm -f "${FORMATS}"
|
||||
|
||||
echo "Completed capturing ${INPUT}"
|
|
@ -0,0 +1,20 @@
|
|||
Welcome to Unix for Artists!
|
||||
_______ __ __ __ _ _ _ ___ _______ __ __
|
||||
| || | | || | | | | | _ | || | | || | | |
|
||||
| ___|| | | || |_| | | || || || | |_ _|| |_| |
|
||||
| |___ | |_| || | | || | | | | |
|
||||
| ___|| || _ | | || | | | | |
|
||||
| | | || | | | | _ || | | | | _ |
|
||||
|___| |_______||_| |__| |__| |__||___| |___| |__| |__|
|
||||
________ ________ __ __ _______ ________ ______
|
||||
| \| \| \ / \| \ | \ / \
|
||||
| $$$$$$$$| $$$$$$$$| $$\ / $$| $$$$$$$\| $$$$$$$$| $$$$$$\
|
||||
| $$__ | $$__ | $$$\ / $$$| $$__/ $$| $$__ | $$ __\$$
|
||||
| $$ \ | $$ \ | $$$$\ $$$$| $$ $$| $$ \ | $$| \
|
||||
| $$$$$ | $$$$$ | $$\$$ $$ $$| $$$$$$$ | $$$$$ | $$ \$$$$
|
||||
| $$ | $$ | $$ \$$$| $$| $$ | $$_____ | $$__| $$
|
||||
| $$ | $$ | $$ \$ | $$| $$ | $$ \ \$$ $$
|
||||
\$$ \$$ \$$ \$$ \$$ \$$$$$$$$ \$$$$$$
|
||||
|
||||
|
||||
|
|
@ -0,0 +1 @@
|
|||
Welcome to Unix for Artists!
|
|
@ -0,0 +1,7 @@
|
|||
_______ __ __ __ _ _ _ ___ _______ __ __
|
||||
| || | | || | | | | | _ | || | | || | | |
|
||||
| ___|| | | || |_| | | || || || | |_ _|| |_| |
|
||||
| |___ | |_| || | | || | | | | |
|
||||
| ___|| || _ | | || | | | | |
|
||||
| | | || | | | | _ || | | | | _ |
|
||||
|___| |_______||_| |__| |__| |__||___| |___| |__| |__|
|
|
@ -0,0 +1,9 @@
|
|||
________ ________ __ __ _______ ________ ______
|
||||
| \| \| \ / \| \ | \ / \
|
||||
| $$$$$$$$| $$$$$$$$| $$\ / $$| $$$$$$$\| $$$$$$$$| $$$$$$\
|
||||
| $$__ | $$__ | $$$\ / $$$| $$__/ $$| $$__ | $$ __\$$
|
||||
| $$ \ | $$ \ | $$$$\ $$$$| $$ $$| $$ \ | $$| \
|
||||
| $$$$$ | $$$$$ | $$\$$ $$ $$| $$$$$$$ | $$$$$ | $$ \$$$$
|
||||
| $$ | $$ | $$ \$$$| $$| $$ | $$_____ | $$__| $$
|
||||
| $$ | $$ | $$ \$ | $$| $$ | $$ \ \$$ $$
|
||||
\$$ \$$ \$$ \$$ \$$ \$$$$$$$$ \$$$$$$
|