Compare commits

..

10 Commits

24 changed files with 581 additions and 61 deletions

View File

@@ -353,8 +353,9 @@ make_vid_dir_and_cd_into() {
function my_transcribe_video() {
file="$1"
output="$2"
include_small=$3
if [[ $file == "" ]]; then
printf "Usage: <input video> <optional output name>\n"
error "Usage: <input video> <optional output name>"
return
fi
if [[ $output == "" ]]; then
@@ -365,14 +366,18 @@ function my_transcribe_video() {
# catches most words. Small and medium can do better word detection at
# times, but suffer from bad punctuation. Medium is particularly bad and
# not adding commas and periods.
transcribe-video "$file" "$output" tiny base
if [[ $include_small -eq 1 ]]; then
transcribe-video "$file" "$output" tiny base small
else
transcribe-video "$file" "$output" tiny base
fi
}
function my_transcribe_video_all_models() {
file="$1"
output="$2"
if [[ $file == "" ]]; then
printf "Usage: <input video> <optional output name>\n"
error "Usage: <input video> <optional output name>"
return
fi
if [[ $output == "" ]]; then
@@ -544,6 +549,14 @@ download_youtube_uploads_list() {
printf "${BOLD}Finished downloading the upload list\n${NORMAL}"
}
function download_youtube_audio() {
if [[ $1 == "" ]]; then
error "Usage: <url>"
return
fi
yt-dlp.exe -f "140" "$1"
}
# Download Twitch chat transcript
actually_download_twitch_chat() {
local url="$1"
@@ -903,7 +916,19 @@ download_mp4() {
}
# Download from m3u8 stream to mp4.
download_from_m3u8() {
# You can supply a local file or a URL to the m3u8 file. If the request requires cookies then the easiest way to do it is to
# run the ffmpeg command yourself using this as the example format:
#
# ffmpeg -protocol_whitelist file,https,crypto,tls,tcp -headers $'Cookie: CloudFront-Policy=ayJTdGF0ZW1lbnQiOlt7IlJlc291cmNlIjoiaHR0cHM6Ly92aWRlby5zdGVsbGFydGlja2V0cy5jb20vb3JnYW5pemF0aW9ucy8yYWQ0YTBhYi1iZWM3LTQ4NjMtYTBmMS0zNjI0N2NjODNkMjMvdHJhbnNjb2RlZC85MWFmYjI4MS0wNy0yMC0yM19LcmF6YW1fUHJlc2VudHMqIiwiQ29uZGl0aW9uIjp7IkRhdGVMZXNzVGhhbiI6eyJBV1M6RXBvY2hUaW1lIjoxNjkwNDk4ODAwfSwiSXBBZGRyZXNzIjp7IkFXUzpTb3VyY2VJcCI6IjY0LjEzNy4xNDkuMTkzLzMyIn19LCJTdHJlYW1Ub2tlbklkIjoiOTJlMTg2ZjUtZWZiMS00ZDAzLWE0NGQtZTg3YzQ3NzFiODI2IiwiU3RyZWFtVG9rZW5WaWV3ZXJJZCI6Ijg3NzFlMTBhLTcxNjUtNDcxOS1iMjFiLTkwNjljZDgzNzdhYyIsIlN0cmVhbVRva2VuVmlld2VyVHlwZSI6IkN1c3RvbWVyIiwiU3RyZWFtVG9rZW5SZXNvdXJjZUlkIjoiZDY3Mzc4NWMtNDEzNy00MDRhLTkzZjctNjQxN2Q4MmY2NmUxIiwiU3RyZWFtVG9rZW5SZXNvdXJjZVR5cGUiOiJWaWRlb09uRGVtYW5kIn1dfQ__; CloudFront-Signature=H0RwSHRX9y4PIqbAmxtEoGEPbO5da%7EW764sbHBXcPwnSSuq5PcjPM2UuP1YKL%7E92WcRTEiJ9FMDVbxNtPDZea2lCk9txvpHdmn7BBy6JNwKd-%7ED9RKq3SSqB00O8P1VkztKtkALYgn8lq3ihk7Nss0wYE9WxgvNNU30umcP-wSHFtuiGsbArivbWvu639Ku5bkfwm8azXI9hvz5D7OtwSyo3z%7E8trw3rALDwCgHZiqQrEQtfN4NYAWZ%7EuzdcGRgdUVmMQotBHG0WpPDItqBR9RLVel%7EWB0mQOO3Dax9DnGHlBaBs5mdR28NqOj8XCY4pAhguJQlERcANIK2WXm56dA__; CloudFront-Key-Pair-Id=APK3IWIJLRLBNXI2PR4Q\r\n' -i https://video.stellartickets.com/organizations/2ad4a0ac-bec7-4863-a0f1-36247cc83d23/transcoded/91afb281-07-20-23_Krazam_Presents_index_1080p_20230721T024151_1.m3u8 -acodec copy -vcodec copy krazam.mp4
#
# You can get the cookie header value from the browser's dev tools network
# page. I tried adding support to this function so that you can just pass the
# cookie value as an arg but it would not work and I don't want to waste more
# time on it.
#
# If you need to debug the http request then add "-v trace" to the command above.
#
download_mp4_from_m3u8() {
local m3u8_path="$1"
local filename="$2"
@@ -923,6 +948,27 @@ download_from_m3u8() {
printf "${BOLD}Finished downloading ${YELLOW}$filename${NORMAL}\n"
}
# Same notes from above regarding cookies/headers.
download_aac_from_m3u8() {
local m3u8_path="$1"
local filename="$2"
if [[ $m3u8_path == "" || $filename == "" ]]; then
error "Usage: <m3u8 path> <filename>"
return
fi
printf "${BOLD}Downloading: ${YELLOW}$filename${NORMAL}\n"
ffmpeg.exe -protocol_whitelist file,https,crypto,tls,tcp -i $m3u8_path -acodec copy "${filename}.aac"
if [[ $? -ne 0 ]]; then
error "Error: failed to download."
return
fi
printf "${BOLD}Finished downloading ${YELLOW}$filename${NORMAL}\n"
}
#-------------------------------------------------
# YouTube Vid DL
@@ -949,7 +995,7 @@ alias yt-playlist-list='download_youtube_playlist_list '
alias yt-playlist-1080='download_youtube_playlist "137+140"'
alias yt-playlist-720='download_youtube_playlist "136+140"'
alias yt-playlist-tiny='download_youtube_playlist "160+140"'
alias yt-audio='yt-dlp.exe -f "140"'
alias yt-audio='download_youtube_audio'
#-------------------------------------------------
# Twitch Vid DL
@@ -1047,7 +1093,8 @@ alias twitter='download_twitter_vid "" '
# Misc
#-------------------------------------------------
alias download-mp4='download_mp4'
alias download-from-m3u8='download_from_m3u8'
alias download-from-m3u8='download_mp4_from_m3u8'
alias download-audio-from-m3u8='download_aac_from_m3u8'
####################################################################################################
# Video Compression

6
.vimrc
View File

@@ -374,8 +374,6 @@ set complete-=i " Don't scan all included files since it's rea
set termguicolors
syntax on " Enable highlighting for syntax
let g:netrw_dirhistmax = 0 " Disable netrw
set wildmenu
set wildmode=longest,list,full
set wildignore+=*/log/*,*.so,*.swp,*.zip,*/rdoc/*
@@ -658,7 +656,7 @@ vnoremap p "_dP
" Switch between C++ source and header files.
noremap <leader>v :e %:p:s,.h$,.X123X,:s,.cpp$,.h,:s,.X123X$,.cpp,<CR>
"noremap <leader>vv :e %:p:s,.h$,.X123X,:s,.c$,.h,:s,.X123X$,.c,<CR>
noremap <leader>vv :e %:p:s,.h$,.X123X,:s,.c$,.h,:s,.X123X$,.c,<CR>
"noremap <leader>vvv :e %:p:s,.h$,.X123X,:s,.cc$,.h,:s,.X123X$,.cc,<CR>
" Replace all instances of the highlighted text with whatever you enter.
@@ -1261,7 +1259,7 @@ fu! Build(optimized=0, silent=0)
" scripts won't be looking at the user metaprogram args.
" We also don't bother adding an import directory for local modules
" because the build file should manage that sort of thing for us.
let l:cmd .= " -release - release"
let l:cmd .= " -release - -release"
let l:set_metaprogram_args = 1
else
echo "Compiling debug build.jai"

View File

@@ -0,0 +1,58 @@
#!/usr/bin/env bash
# Re-encodes the video with a new primary audio channel.
if which tput >/dev/null 2>&1; then
ncolors=$(tput colors)
fi
if [ -t 1 ] && [ -n "$ncolors" ] && [ "$ncolors" -ge 8 ]; then
RED="$(tput setaf 1)"
GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
BLUE="$(tput setaf 4)"
MAGENTA="$(tput setaf 5)"
CYAN="$(tput setaf 6)"
BOLD="$(tput bold)"
NORMAL="$(tput sgr0)"
else
RED=""
GREEN=""
YELLOW=""
BLUE=""
MAGENTA=""
CYAN=""
BOLD=""
NORMAL=""
fi
vid_filename=$(basename -- "$1")
audio_filename=$(basename -- "$2")
output_name="$3"
if [[ $vid_filename == "" || $audio_filename == "" || $output_name == "" ]]; then
printf "${BOLD}${RED}Usage: add-audio-to-video <video filename> <audio filename> <output name>${NORMAL}\n"
exit 1
fi
vid_extension="${vid_filename##*.}"
vid_filename="${vid_filename%.*}"
audio_extension="${audio_filename##*.}"
audio_filename="${audio_filename%.*}"
output="${output_name}.$vid_extension"
audio_encoding_opts="-c:a copy"
if [[ $audio_extension == "wav" ]]; then
# Re-encode the audio.
audio_encoding_opts="-c:a aac -b:a 192k"
fi
printf "\n${YELLOW}${BOLD}Adding audio '$audio_filename.$audio_extension' to '$vid_filename.$vid_extension' | output: $output${NORMAL}\n"
# -shortest handles the inputs not being the same duration. Conversion will stop when the shortest input's end is reached.
# Alternatively you can loop with "-stream_loop -1"
ffmpeg -y -stats -loglevel level+error -i "$vid_filename.$vid_extension" -i "$audio_filename.$audio_extension" -c:v copy -map 0:v:0 -map 1:a:0 $audio_encoding_opts -shortest "$output"
printf "\n${GREEN}${BOLD}Finished adding audio${NORMAL}\n\n"

View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
# Use this to get a report on the video audio volume. You can use this info
# manually normalize or increase/decrease a video's volume using the
# change-video-volume script, supplying it the volume delta you want. Typically
# you use the delta from the analysis report this script provides, e.g. if the
# max_volume is -5 db then you would call change-video-volume with a value of
# 5. I find that the two pass normalize-video-audio script works better than
# this approach...but it will take longer to run!
#
# Inspired by https://superuser.com/a/323127 and https://superuser.com/a/1312885
if which tput >/dev/null 2>&1; then
ncolors=$(tput colors)
fi
if [ -t 1 ] && [ -n "$ncolors" ] && [ "$ncolors" -ge 8 ]; then
RED="$(tput setaf 1)"
GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
BLUE="$(tput setaf 4)"
MAGENTA="$(tput setaf 5)"
CYAN="$(tput setaf 6)"
BOLD="$(tput bold)"
NORMAL="$(tput sgr0)"
else
RED=""
GREEN=""
YELLOW=""
BLUE=""
MAGENTA=""
CYAN=""
BOLD=""
NORMAL=""
fi
if [[ $1 == "" ]]; then
printf "${BOLD}${RED}Usage: analyze-video-volume <video filename>${NORMAL}\n"
exit 1
fi
filename="$1"
printf "\n${YELLOW}${BOLD}Analyzing audio in $filename${NORMAL}\n"
# -vn, -sn, and -dn tells ffmpeg to ignore non-audio streams during the analysis. This speeds things up.
cmd="ffmpeg -i \"$filename\" -af volumedetect -vn -sn -dn -f null /dev/null"
printf "\n${BOLD}Running: $cmd\n\n${NORMAL}"
eval $cmd
printf "\n${GREEN}${BOLD}Done analyzing audio in $filename\n${NORMAL}"
printf "\n${YELLOW}${BOLD}Look at the reported max_volume value. If != 0 then call the change-video-volume script, passing it the filename, an output name and the delta to bring the volume to 0.\ne.g. if the max_volume is -5 db, then you would pass 5.${NORMAL}\n\n"

View File

@@ -7,8 +7,7 @@ if not "%1"=="am_admin" (
exit /b
)
rem USE AT OWN RISK AS IS WITHOUT WARRANTY OF ANY KIND !!!!!
rem NOTE: Defender may see this file as malware, so you will likely need to exclude this before things can be disabled.
rem NOTE: Defender may see this file as malware, so you might need to exclude this before things can be disabled.
rem
rem Modified version of
rem https://raw.githubusercontent.com/mattreecebentley/win10_disable_defender/main/win10_enable_defender.bat
@@ -94,7 +93,7 @@ reg add HKLM\SYSTEM\Setup /v DisabledDefenderServices /t REG_DWORD /d 1 /f
echo.
echo Windows Defender has (hopefully) been disabled.
echo You should still be able to scan files going forward. Also, the Antimalware Service Executable should immediately stop using CPU cycles.
echo You might still be able to scan files going forward depending on your version of Windows. Also, the Antimalware Service Executable should immediately stop using CPU cycles.
echo Please restart your computer to see all changes.
goto eof

View File

@@ -1,5 +1,30 @@
#!/usr/bin/env bash
# Creates a file containing the names of all files in a specific bucket.
#
# e.g. aws-list-deep-glacier-files my-deep-glacier images image_list
#
# You'll need the aws cli tools. Download them from https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
#
# If you see an error like along the lines of "'charmap' codec can't encode
# character '\u200e' in position 42: character maps to <undefined>" then that
# means a filename has a Unicode codepoint and the dumb aws Python code is
# trying to read it using your system's locale, which is very likely not set to
# use the Windows UTF-8 beta feature. This is an ongoing issue in this tool
# that goes back to 2013!!! There's no way to fix it using environment
# variables, at least nothing worked for me. The fix provided by the devs is
# heavy handed: you change your system locale to use UTF-8... This has
# consequences though like breaking legacy apps that don't have Unicode support
# and I'm sure other weird things will happen, such as file corruption. Anyway,
# if you're getting this charmap error then I suggest changing your system
# locale, run this again, then switch back to your previous locale. If you
# don't get the canonical file name then you won't be able to restore it.
#
# You can enable the UTF-8 locale with:
#
# win+r -> intl.cpl -> Administrative tab -> Change system locale -> Beta: Use Unicode UTF-8 box.
#
if which tput >/dev/null 2>&1; then
ncolors=$(tput colors)
fi

View File

@@ -1,10 +1,49 @@
#!/usr/bin/env bash
#
# Restores all files/folders inside a particular bucket path,
# e.g. aws-restore-deep-glacier-folder mcampagnaro-deep-glacier images restored_images
# will restore all files inside the images folder of the mcampagnaro-deep-glacier bucket, saving
# temp restoration data in the local "restored_images" directory.
# Restores all files/folders inside a particular bucket path for the next 7 days. This uses the bulk retreival tier:
#
# Bulk retrievals are the lowest-cost retrieval option when restoring objects
# from S3 Glacier Deep Archive. They typically finish within 48 hours for
# objects stored in the S3 Glacier Deep Archive storage class or S3
# Intelligent-Tiering Deep Archive tier.
#
# If you need faster access then use the `Expedited` or `Standard` tiers.
#
# Example usage:
#
# aws-restore-deep-glacier-folder my-deep-glacier-bucket path/to/images restored_images
#
# This will create a run.sh script in a folder called "restored_images". Run that to restore all files inside the `path/to/images` folder inside the my-deep-glacier bucket.
#
# After you run the generated script, you have to wait for AWS to make the files available for download. You can check the status of a file with:
#
# aws s3api head-object --bucket my-deep-glacier --key path/to/images/photo1.jpg
#
# (obviously change the bucket and path to suit your needs).
#
# Once the files are restored you can download them on the S3 website or better yet use RcloneBrowser. I'm sure there's also a way to do it over cli too, I just haven't checked.
#
# You'll need the aws cli tools for this script. Download them from https://docs.aws.amazon.com/cli/latest/userguide/getting-started-install.html
# Once installed, open a new shell and verify that you can run the `aws` command.
#
# If you see an error like along the lines of "'charmap' codec can't encode
# character '\u200e' in position 42: character maps to <undefined>" then that
# means a filename has a Unicode codepoint and the dumb aws Python code is
# trying to read it using your system's locale, which is very likely not set to
# use the Windows UTF-8 beta feature. This is an ongoing issue in this tool
# that goes back to 2013!!! There's no way to fix it using environment
# variables, at least nothing worked for me. The fix provided by the devs is
# heavy handed: you change your system locale to use UTF-8... This has
# consequences though like breaking legacy apps that don't have Unicode support
# and I'm sure other weird things will happen, such as file corruption. Anyway,
# if you're getting this charmap error then I suggest changing your system
# locale, run this again, then switch back to your previous locale. If you
# don't get the canonical file name then you won't be able to restore it.
#
# You can enable the UTF-8 locale with:
#
# win+r -> intl.cpl -> Administrative tab -> Change system locale -> Beta: Use Unicode UTF-8 box.
#
if which tput >/dev/null 2>&1; then
@@ -46,7 +85,7 @@ path="$2"
temp_dir="$3"
number_of_objects_per_file=100
days_available=7
restore_tier="Bulk" # Can also be "Standard"
restore_tier="Bulk" # Can also be "Standard" or "Expedited"
if [[ $bucket == "" || $path == "" || $temp_dir == "" ]]; then
error "Usage: aws-restore-deep-glacier-folder <bucket-name> <path-in-bucket> <local-temp-dir>"
@@ -61,7 +100,7 @@ pushd "$temp_dir" &>/dev/null
aws s3api list-objects-v2 --bucket $bucket --prefix $path --query "Contents[?StorageClass=='DEEP_ARCHIVE']" --output text | LC_ALL=C awk '{print substr($0, index($0, $2))}' | awk '{NF-=3};3' > all_objects_list.txt
# Generate the main script that will kick off the restoration.
printf "while read x; do\n printf \"aws s3api restore-object --restore-request '{\\\\\"Days\\\\\":$days_available,\\\\\"GlacierJobParameters\\\\\":{\\\\\"Tier\\\\\":\\\\\"$restore_tier\\\\\"}}' --bucket $bucket --key \\\\\"\$x\\\\\"\\\\n\"\n aws s3api restore-object --restore-request \"{\\\\\"Days\\\\\":$days_available,\\\\\"GlacierJobParameters\\\\\":{\\\\\"Tier\\\\\":\\\\\"$restore_tier\\\\\"}}\" --bucket $bucket --key \"\$x\"\ndone < all_objects_list.txt\nprintf \"\\\\nDone! You can now delete this folder.\\\\n\"\n" > run.sh
printf "while read x; do\n printf \"aws s3api restore-object --restore-request '{\\\\\"Days\\\\\":$days_available,\\\\\"GlacierJobParameters\\\\\":{\\\\\"Tier\\\\\":\\\\\"$restore_tier\\\\\"}}' --bucket $bucket --key \\\\\"\$x\\\\\"\\\\n\"\n aws s3api restore-object --restore-request \"{\\\\\"Days\\\\\":$days_available,\\\\\"GlacierJobParameters\\\\\":{\\\\\"Tier\\\\\":\\\\\"$restore_tier\\\\\"}}\" --bucket $bucket --key \"\$x\"\ndone < all_objects_list.txt\nprintf \"\\\\nDone! You can now delete this folder.\\\\nYour files are currently being restored. The time it takes to restore can be found in the AWS docs - just look for the $restore_tier restore tier, which is what you used.\\\\nOnce restored, download the files from the S3 site or better yet use RCloneBrowser.\\\\n\"\n" > run.sh
chmod +x run.sh
printf "${BOLD}You can now run ${GREEN}$temp_dir/run.sh${NORMAL}${BOLD} to start the restoration process.\n"

View File

@@ -0,0 +1,59 @@
#!/usr/bin/env bash
# Re-encodes the audio, modify the volume based on the supplied db delta. The
# video is copied as-is. If you want to bring the max_volume to 0 db then call
# analyze-video-volume prior to this and pass a delta based on the reported
# max_volume.
#
# Inspired by https://superuser.com/a/323127 and https://superuser.com/a/1312885
if which tput >/dev/null 2>&1; then
ncolors=$(tput colors)
fi
if [ -t 1 ] && [ -n "$ncolors" ] && [ "$ncolors" -ge 8 ]; then
RED="$(tput setaf 1)"
GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
BLUE="$(tput setaf 4)"
MAGENTA="$(tput setaf 5)"
CYAN="$(tput setaf 6)"
BOLD="$(tput bold)"
NORMAL="$(tput sgr0)"
else
RED=""
GREEN=""
YELLOW=""
BLUE=""
MAGENTA=""
CYAN=""
BOLD=""
NORMAL=""
fi
if [[ $1 == "" ]]; then
printf "${BOLD}${RED}Usage: change-video-volume <filename> <output name> <volume delta in db>${NORMAL}\n"
exit 1
fi
filename=$(basename -- "$1")
extension="${filename##*.}"
filename="${filename%.*}"
output_name="$2"
delta_db="$3"
if [[ $output_name == "" ]]; then
output="${filename}_normalized_audio.$extension"
else
output="${output_name}.$extension"
fi
printf "\n${YELLOW}${BOLD}Modifying audio volume in $filename.$extension | output: $output | delta: $delta_db${NORMAL}\n"
# Since we're re-encoding the audio we have to specify a codec to use.
cmd="ffmpeg -i \"$filename.$extension\" -af \"volume=${delta_db}dB\" -c:v copy -c:a aac -map 0 \"$output\""
printf "\n${BOLD}Running: $cmd\n\n${NORMAL}"
eval $cmd
printf "\n${GREEN}${BOLD}Done modifying volume in $filename.$extension | output: $output | delta: $delta_db${NORMAL}\n"

View File

@@ -26,7 +26,7 @@ fi
use_gpu=0
if [[ $# < 2 || $# > 3 ]]; then
printf "${BOLD}${RED}Usage: $0 <filename> <output name> <optional: use-gpu (1|0), defaults to $use_gpu> ${NORMAL}\n"
printf "${BOLD}${RED}Usage: compress-video <filename> <output name> <optional: use-gpu (1|0), defaults to $use_gpu> ${NORMAL}\n"
exit 1
fi

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env bash
if which tput >/dev/null 2>&1; then
ncolors=$(tput colors)
fi
if [ -t 1 ] && [ -n "$ncolors" ] && [ "$ncolors" -ge 8 ]; then
RED="$(tput setaf 1)"
GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
BLUE="$(tput setaf 4)"
MAGENTA="$(tput setaf 5)"
CYAN="$(tput setaf 6)"
BOLD="$(tput bold)"
NORMAL="$(tput sgr0)"
else
RED=""
GREEN=""
YELLOW=""
BLUE=""
MAGENTA=""
CYAN=""
BOLD=""
NORMAL=""
fi
filename=$(basename -- "$1")
output_name="$2"
width="$3"
if [[ $filename == "" || $output_name == "" ]]; then
printf "${BOLD}${RED}Usage: create-gif-from-video <filename> <output name> <optional width, defaults to 240>${NORMAL}\n"
exit 1
fi
output="${output_name}.gif"
if [[ $width == "" ]]; then
width=240
fi
printf "\n${YELLOW}${BOLD}Creating a gif from '$filename' | output: $output | width: $width${NORMAL}\n"
ffmpeg -y -stats -loglevel level+error -i "$filename" -vf "fps=24,scale=$width:-1:flags=lanczos,split[s0][s1];[s0]palettegen[p];[s1][p]paletteuse" -loop 0 "$output"
printf "\n${GREEN}${BOLD}Finished!${NORMAL}\n\n"

View File

@@ -0,0 +1,63 @@
#!/usr/bin/env bash
# Adds subtitles to a video. You can pass multiple srt files in one go. This
# preserves all existing streams, so if you've already added subtitle tracks to
# the video then these new ones will be appended. I haven't extensively tested
# appending yet (not sure if the mapping arg is correct), so I recommend adding
# all of your tracks in one go.
if which tput >/dev/null 2>&1; then
ncolors=$(tput colors)
fi
if [ -t 1 ] && [ -n "$ncolors" ] && [ "$ncolors" -ge 8 ]; then
RED="$(tput setaf 1)"
GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
BLUE="$(tput setaf 4)"
MAGENTA="$(tput setaf 5)"
CYAN="$(tput setaf 6)"
BOLD="$(tput bold)"
NORMAL="$(tput sgr0)"
else
RED=""
GREEN=""
YELLOW=""
BLUE=""
MAGENTA=""
CYAN=""
BOLD=""
NORMAL=""
fi
filename=$(basename -- "$1")
extension="${filename##*.}"
filename="${filename%.*}"
output_name="$2"
output="${output_name}.$extension"
shift 2
subtitles=("$@")
if [[ $filename == "" || $output_name == "" || ${#subtitles[@]} -eq 0 ]]; then
printf "${BOLD}${RED}Usage: embed-subtitles <video filename> <output name> <subtitle filenames>${NORMAL}\n"
exit 1
fi
printf "\n${YELLOW}${BOLD}Adding subtitles to $filename.$extension | output: $output${NORMAL}\n"
mapping="-map 0"
tracks=""
map_index=1
for track in "$@"; do
tracks+="-i \"$track\" "
mapping+=" -map $map_index"
map_index=$((map_index+1))
done
cmd="ffmpeg -i \"$filename.$extension\" $tracks $mapping -c copy -c:s mov_text \"$output\""
printf "\n${BOLD}Running: $cmd\n\n${NORMAL}"
eval $cmd
printf "\n${GREEN}${BOLD}Done adding subtitles to $filename.$extension | output: $output\n${NORMAL}"

View File

@@ -45,6 +45,7 @@ fi
printf "\n${YELLOW}${BOLD}Extracting 16-bit WAV from $input | output: $output_name${NORMAL}\n"
# -ac 1 mixes audio to a single channel.
ffmpeg -i "$input" -ar 16000 -ac 1 -c:a pcm_s16le "$output_name"
printf "${GREEN}${BOLD}Done extracting 16-bit WAV from $input | output: $output_name${NORMAL}\n"

View File

@@ -45,7 +45,7 @@ fi
printf "\n${YELLOW}${BOLD}Repairing audio in $filename.$extension | output: $output${NORMAL}\n"
ffmpeg -i "$filename.$extension" -c:v copy -ac 1 "$output"
ffmpeg -i "$filename.$extension" -c:v copy -ac 1 -map 0 "$output"
printf "\n${GREEN}${BOLD}Done repairing audio in $filename.$extension | output: $output${NORMAL}\n\n"

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env bash
# Re-encodes the video to get a more accurate timeline. If you want fast video joining at the expense of accuracy then use join-video-fast.
if which tput >/dev/null 2>&1; then
ncolors=$(tput colors)
fi
@@ -35,7 +37,7 @@ output="${output_name}.mp4"
printf "\n${YELLOW}${BOLD}Joining contents of '$filename'| output: $output${NORMAL}\n"
ffmpeg -f concat -safe 0 -i "$filename" -c copy "$output"
ffmpeg -f concat -safe 0 -accurate_seek -i "$filename.$extension" -c:v libx264 -c:a copy "$output"
printf "\n${GREEN}${BOLD}Finished joining${NORMAL}\n\n"

View File

@@ -0,0 +1,46 @@
#!/usr/bin/env bash
# A fast way to join video clips that might result in some weird playback cursor timings,
# e.g. video player might show negative seconds at the start of the vid or the
# playback time might oscillate a bit. Use join-video for accurate joining at
# the cost of a much slower processing time.
if which tput >/dev/null 2>&1; then
ncolors=$(tput colors)
fi
if [ -t 1 ] && [ -n "$ncolors" ] && [ "$ncolors" -ge 8 ]; then
RED="$(tput setaf 1)"
GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
BLUE="$(tput setaf 4)"
MAGENTA="$(tput setaf 5)"
CYAN="$(tput setaf 6)"
BOLD="$(tput bold)"
NORMAL="$(tput sgr0)"
else
RED=""
GREEN=""
YELLOW=""
BLUE=""
MAGENTA=""
CYAN=""
BOLD=""
NORMAL=""
fi
filename=$(basename -- "$1")
output_name="$2"
if [[ $filename == "" || $output_name == "" ]]; then
printf "${BOLD}${RED}Usage: create a text file that lists the input video paths on separate lines using the format: file '/path/to/video'. Then call:\n\n$0 <list name> <output name>${NORMAL}\n"
exit 1
fi
output="${output_name}.mp4"
printf "\n${YELLOW}${BOLD}Joining contents of '$filename'| output: $output${NORMAL}\n"
ffmpeg -f concat -safe 0 -i "$filename" -c copy "$output"
printf "\n${GREEN}${BOLD}Finished joining${NORMAL}\n\n"

View File

@@ -1,6 +1,8 @@
#!/usr/bin/env bash
# Use this to normalize the audio of a video using the average loudness, or RMS-based normalization.
# Use this to normalize the audio of a video using the average loudness, or RMS-based normalization. It does a pretty good job!
# If you want to modify the volume yourself then checkout the analyze-video-volume and change-video-volume scripts.
#
# This does not re-encode the video.
#
# Inspired by https://superuser.com/a/323127 and https://superuser.com/a/1312885
@@ -50,21 +52,26 @@ printf "\n${YELLOW}${BOLD}Normalizing audio in $filename.$extension | output: $o
# This is done in two passes. The first pass will compute the mean loudness and
# the second pass will normalize the audio using the mean as the target.
# -vn, -sn, and -dn tells ffmpeg to ignore non-audio streams during the analysis. This speeds things up.
ffmpeg -i "$filename.$extension" -af "volumedetect" -vn -sn -dn -f null /dev/null
temp_file="/tmp/_audio_info_$RANDOM"
#ffmpeg -i "$filename.$extension" -c:v copy -ac 1 "$output"
# 1st pass:
cmd="ffmpeg -i \"$filename.$extension\" -pass 1 -filter:a loudnorm=print_format=json -vn -sn -dn -f null /dev/null 2>&1 | sed -n '/{/,/}/p' > $temp_file"
printf "\n${BOLD}Running 1st pass:\n$cmd\n\n${NORMAL}"
eval $cmd
printf "\n${GREEN}${BOLD}Done normalizing audio in $filename.$extension | output: $output${NORMAL}\n\n"
printf "\n${BOLD}${GREEN}Done.\n\n${NORMAL}"
ii=`grep \"input_i\" $temp_file | cut -d: -f2 | tr -cd [:digit:].-`
itp=`grep \"input_tp\" $temp_file | cut -d: -f2 | tr -cd [:digit:].-`
ilra=`grep \"input_lra\" $temp_file | cut -d: -f2 | tr -cd [:digit:].-`
it=`grep \"input_thresh\" $temp_file | cut -d: -f2 | tr -cd [:digit:].-`
to=`grep \"target_offset\" $temp_file | cut -d: -f2 | tr -cd [:digit:].-`
# 2nd pass:
cmd="ffmpeg -i \"$filename.$extension\" -c:v copy -pass 2 -filter:a loudnorm=linear=true:I=-16:LRA=11:tp=-1.5:measured_I=$ii:measured_LRA=$ilra:measured_tp=$itp:measured_thresh=$it:offset=$to:print_format=summary -map 0 \"$output\""
printf "${BOLD}Re-encoding audio:\n$cmd\n\n${NORMAL}"
eval $cmd
#---------------------------------------
# This seems better. 2 pass using loudnorm filter.
printf "\n${GREEN}${BOLD}Done normalizing volume in $filename.$extension | output: $output${NORMAL}\n"
rm $temp_file
# 1st pass: ffmpeg -i "$filename.$extension" -pass 1 -filter:a loudnorm=print_format=json -vn -sn -dn -f null /dev/null
# 2nd pass: ffmpeg -i "$filename.$extension" -c:v copy -pass 2 -filter:a loudnorm=linear=true:measured_I=$input_i:measured_LRA=$input_lra:measured_tp=$input_tp:measured_thresh=$input_thresh "$output"
# TODO: extract the $input_i, input_lra, etc from the 1st pass output so that this can be automated.
# TODO: stackoverflow said if there are subtitles or multiple vid streams then add "-map 0" before the output name. Test this.
# TODO: disable the log file or just delete it after normalizing.

View File

@@ -43,7 +43,7 @@ fi
printf "\n${YELLOW}${BOLD}Removing audio from '$filename.$extension' | output: '$output'${NORMAL}\n"
# -an removes the audio.
ffmpeg -i "$filename.$extension" -c:v copy -an "$output"
ffmpeg -i "$filename.$extension" -c:v copy -an -map 0 "$output"
printf "\n${GREEN}${BOLD}Done removing audio from '$filename.$extension' | output: '$output'${NORMAL}\n\n"

View File

@@ -52,9 +52,6 @@ output_name_without_ext="$2"
model="$3"
threads=$4
# 4 seems to be the sweet spot for most models, except medium might be faster with 8.
default_thread_count=4
if [[ $input_wav == "" || $output_name_without_ext == "" || $model == "" ]]; then
printf "${BOLD}${RED}Usage: $0 <input.wav> <output name without extension> <model name> <optional: thread count>${NORMAL}\n"
exit 1
@@ -65,19 +62,27 @@ if [[ ! -f "$input_wav" ]]; then
exit 1
fi
if [[ $threads == "" ]]; then
threads=$default_thread_count
fi
output_name="$output_name_without_ext.${model}"
# 1 core 31 threads has very fast pcm_to_mel conversion and then just one core doing most of the work. You get more accurate results this way.
# 2 core 16 is about half the time but it can have errors where the two pieces come together. This only gets more likely as the core count is increased.
# 8 threads, 4 cores is good too for tiny,small and 2 threads, 4 cores for medium.
threads=31 #keep a thread for me
# 4 seems to be the sweet spot for most models, except medium might be faster with 8.
# But on my 5950x, running 1 core with 31 threads is quite fast.
#default_thread_count=4
cores=1
default_thread_count=31
if [[ $threads == "" ]]; then
threads=$default_thread_count
# This is only useful when not setting the core count and defaulting to 4 threads.
#if [[ $model == "medium" || $model == "large" ]]; then
# threads=8
#fi
fi
printf "\n${YELLOW}${BOLD}Transcribing $input_wav | model: $model | cores: $cores | threads: $threads | output: $output_name ${NORMAL}\n"
@@ -85,7 +90,12 @@ whisper_fullname="$(expand_path $(which whisper.exe))"
whisper_path="$(dirname $whisper_fullname)"
models_path="$whisper_path/models"
whisper.exe --processors ${cores} --threads ${threads} -m "$models_path/ggml-${model}.en.bin" -otxt -osrt -f "$input_wav" -of "$output_name" --print-colors --print-progress
if [[ $model != "large" ]]; then
model="${model}.en"
fi
whisper.exe --processors ${cores} --threads ${threads} -m "$models_path/ggml-${model}.bin" -otxt -osrt -f "$input_wav" -of "$output_name" --print-colors --print-progress
error=$?
if [[ error -eq 0 ]]; then
printf "${GREEN}${BOLD}Done transcribing $input_wav | model: $model | cores: $cores | threads: $threads | output: $output_name${NORMAL}\n"

View File

@@ -47,13 +47,7 @@ extract-16bit-wav-from-video "$input_video" "$wav_name"
if [[ $? == 1 ]]; then exit 1; fi
for model in "$@"; do
# Tweak thread count based on model size.
thread_count=4
if [[ $model == "medium" ]]; then
thread_count=8
fi
transcribe-audio "$wav_name" "$output_name_without_ext" "${model}" $thread_count
transcribe-audio "$wav_name" "$output_name_without_ext" "${model}"
if [[ $? == 1 ]]; then
printf "${RED}${BOLD}Saving the audio file \"$wav_name\" in case you want to reuse it for debugging.\n${NORMAL}"

View File

@@ -1,6 +1,6 @@
#!/usr/bin/env bash
# Reencodes the video with a more accurate length.
# Re-encodes the audio to get a more accurate seek time.
if which tput >/dev/null 2>&1; then
ncolors=$(tput colors)
@@ -31,7 +31,7 @@ start_time="$3"
end_time="$4"
if [[ $filename == "" || $output_name == "" || $start_time == "" || $end_time == "" ]]; then
printf "${BOLD}${RED}Usage: $0 <filename> <output name> <start time HH:MM:SS> <end time HH:MM:SS>${NORMAL}\n"
printf "${BOLD}${RED}Usage: trim-audio <filename> <output name> <start time HH:MM:SS> <end time HH:MM:SS>${NORMAL}\n"
exit 1
fi
@@ -42,7 +42,10 @@ timing_args="-ss $start_time -to $end_time"
printf "\n${YELLOW}${BOLD}Trimming '$filename.$extension' | output: $output | start: $start_time | end: $end_time${NORMAL}\n"
ffmpeg -y -stats -loglevel level+error $timing_args -accurate_seek -i "$filename.$extension" -c:v libx264 -c:a copy "$output"
# You might have issues if the file has multiple video streams or embedded subtitles. The -map 0 arg is typically given
# when copying a video stream, but I'm not sure if it's appropriate to use here.
# Trying out async to keep video and audio synced.
ffmpeg -y -stats -loglevel level+error $timing_args -accurate_seek -async 1 -i "$filename.$extension" -c copy "$output"
printf "\n${GREEN}${BOLD}Finished trimming${NORMAL}\n\n"

View File

@@ -1,5 +1,7 @@
#!/usr/bin/env bash
# Re-encodes the video to get a more accurate seek time. If you want fast trimming at the expense of accuracy then use trim-video-fast.
if which tput >/dev/null 2>&1; then
ncolors=$(tput colors)
fi
@@ -29,7 +31,7 @@ start_time="$3"
end_time="$4"
if [[ $filename == "" || $output_name == "" || $start_time == "" || $end_time == "" ]]; then
printf "${BOLD}${RED}Usage: $0 <filename> <output name> <start time HH:MM:SS> <end time HH:MM:SS>${NORMAL}\n"
printf "${BOLD}${RED}Usage: trim-video <filename> <output name> <start time HH:MM:SS> <end time HH:MM:SS>${NORMAL}\n"
exit 1
fi
@@ -40,7 +42,10 @@ timing_args="-ss $start_time -to $end_time"
printf "\n${YELLOW}${BOLD}Trimming '$filename.$extension' | output: $output | start: $start_time | end: $end_time${NORMAL}\n"
ffmpeg -y -stats -loglevel level+error $timing_args -i "$filename.$extension" -c copy "$output"
# You might have issues if the file has multiple video streams or embedded subtitles. The -map 0 arg is typically given
# when copying a video stream, but I'm not sure if it's appropriate to use here.
# Trying out async to keep video and audio synced.
ffmpeg -y -stats -loglevel level+error $timing_args -accurate_seek -async 1 -i "$filename.$extension" -c:v libx264 -c:a copy "$output"
printf "\n${GREEN}${BOLD}Finished trimming${NORMAL}\n\n"

View File

@@ -0,0 +1,53 @@
#!/usr/bin/env bash
# A fast video trim that might result in some weird seek timings, e.g. video
# player might show negative seconds at the start of the vid or the playback
# time might oscillate a bit. Use trim-video for accurate trimming at the cost
# of a much slower processing time.
if which tput >/dev/null 2>&1; then
ncolors=$(tput colors)
fi
if [ -t 1 ] && [ -n "$ncolors" ] && [ "$ncolors" -ge 8 ]; then
RED="$(tput setaf 1)"
GREEN="$(tput setaf 2)"
YELLOW="$(tput setaf 3)"
BLUE="$(tput setaf 4)"
MAGENTA="$(tput setaf 5)"
CYAN="$(tput setaf 6)"
BOLD="$(tput bold)"
NORMAL="$(tput sgr0)"
else
RED=""
GREEN=""
YELLOW=""
BLUE=""
MAGENTA=""
CYAN=""
BOLD=""
NORMAL=""
fi
filename=$(basename -- "$1")
output_name="$2"
start_time="$3"
end_time="$4"
if [[ $filename == "" || $output_name == "" || $start_time == "" || $end_time == "" ]]; then
printf "${BOLD}${RED}Usage: trim-video-fast <filename> <output name> <start time HH:MM:SS> <end time HH:MM:SS>${NORMAL}\n"
exit 1
fi
extension="${filename##*.}"
filename="${filename%.*}"
output="${output_name}.$extension"
timing_args="-ss $start_time -to $end_time"
printf "\n${YELLOW}${BOLD}Trimming '$filename.$extension' | output: $output | start: $start_time | end: $end_time${NORMAL}\n"
# You might have issues if the file has multiple video streams or embedded subtitles. The -map 0 arg is typically given
# when copying a video stream, but I'm not sure if it's appropriate to use here.
ffmpeg -y -stats -loglevel level+error $timing_args -i "$filename.$extension" -c copy "$output"
printf "\n${GREEN}${BOLD}Finished trimming${NORMAL}\n\n"

View File

@@ -11,8 +11,9 @@
built this for them. There's no way to stop this from happening other than to disable the platform entirely.
* Run `disable-windows-platform-binary-table.reg` and reboot.
* Change PC name and reboot
* Change PC name
* Open settings -> System -> About -> Rename this PC
* Reboot
* Disable the annoying Windows alert sound that plays when doing things like using a terminal, hitting tab to autocomplete and it has no match.
* Open C:/windows/media
@@ -21,6 +22,13 @@
* Back in the previous Security tab, click Edit to change permisisons -> add your user account and grant all permissions
* Now you can delete the file or rename it.
* Maybe disable swapfile
* Not a good idea to have this turned on for SSDs since it's extra writes, and writing to an SSD degrades the drive. Probably best to put this on a spinning disk.
It's unclear if it's a bad idea to entirely disable on Windows 10 & 11. You likely won't have an issue if you have lots of RAM, but apparently its used for other
things like sleeping apps, kernel dumps, etc. It's possible that disabling it will affect your PC performance. Whether that's noticeable is something I'm unsure of.
* Advanced System Settings -> Advanced -> Performance settings -> Advanced -> Change paging settings -> set the drives to none
* Reboot
* Disable `Enhance Pointer Precision`:
* Mouse Properties -> Pointer Options -> Motion section
@@ -48,6 +56,12 @@
* Pin "This PC" to taskbar
* In Win 10 start menu, search for "This PC", right click top result and pin to taskbar
* Disable collection of recently opened files
* winkey+r -> `gpedit.msc`.
* User Configuration > Administrative Templates > Start Menu and Taskbar
* Double-click the `Do no keep history of recently opened documents` policy.
* Select Enabled.
* Configure Explorer's options
* Open file explorer, click on File menu then options or "Change folder and search options"
* General tab