docker reworking

This commit is contained in:
2025-09-11 19:45:35 -05:00
parent 0e97fb8c91
commit 82ff7d4f43
10 changed files with 214 additions and 123 deletions

2
Jenkinsfile vendored
View File

@@ -61,7 +61,7 @@ pipeline {
agent { label "linux && ${ARCH}" } agent { label "linux && ${ARCH}" }
steps { steps {
withDockerCreds { withDockerCreds {
sh "${OPT_LTO} ./scripts/docker_run_image.sh ${DISTRO}" sh "${OPT_LTO} ./scripts/build_with_docker.sh ${DISTRO}"
} }
} }
} }

View File

@@ -1 +1,45 @@
# ffmpeg-builder
A collection of scripts for building ffmpeg and encoding content with the built ffmpeg
Tested on:
- linux x86_64/aarch64 on:
- ubuntu
- fedora
- debian
- archlinux
- darwin aarch64
```bash
~~~ Usable Commands ~~~
print_cmds:
print usable commands
do_build:
build a specific project
build:
build ffmpeg with desired configuration
docker_build_image:
build docker image with required dependencies pre-installed
docker_save_image:
save docker image into tar.zst
docker_load_image:
load docker image from tar.zst
docker_run_image:
run docker image with given flags
build_with_docker:
run docker image with given flags
docker_build_multiarch_image:
build multiarch docker image
efg:
estimate the film grain of a given file
encode:
encode a file using libsvtav1_psy and libopus
print_pkg_mgr:
print out evaluated package manager commands and required packages
install_deps:
install required dependencies
gen_readme:
generate project README.md
```

View File

@@ -285,7 +285,7 @@ download_release() {
done done
# enabling a clean build # enabling a clean build
if [[ ${CLEAN} == 'true' ]]; then if [[ ${CLEAN} == true ]]; then
DO_CLEAN="rm -rf" DO_CLEAN="rm -rf"
else else
DO_CLEAN='void' DO_CLEAN='void'
@@ -738,7 +738,8 @@ build_ffmpeg() {
--enable-nonfree \ --enable-nonfree \
--disable-htmlpages \ --disable-htmlpages \
--disable-podpages \ --disable-podpages \
--disable-txtpages || return 1 --disable-txtpages \
--disable-autodetect || return 1
ccache make -j"${JOBS}" || return 1 ccache make -j"${JOBS}" || return 1
${SUDO_MODIFY} make -j"${JOBS}" install || return 1 ${SUDO_MODIFY} make -j"${JOBS}" install || return 1
} }

View File

@@ -70,15 +70,15 @@ echo_platform() {
echo "${platKernel}/${platCpu}" echo "${platKernel}/${platCpu}"
} }
# sets DISTROS
validate_selected_image() { validate_selected_image() {
local selectedImage="${1:-}" local selectedImage="$1"
local valid=1
for distro in "${VALID_DOCKER_IMAGES[@]}"; do for distro in "${VALID_DOCKER_IMAGES[@]}"; do
if [[ ${selectedImage} == "${distro}" ]]; then if [[ ${selectedImage} == "${distro}" ]]; then
DISTROS+=("${distro}") valid=0
fi fi
done done
if [[ ${DISTROS[*]} == '' ]]; then if [[ valid -eq 1 ]]; then
echo_fail "${selectedImage} is not valid" echo_fail "${selectedImage} is not valid"
echo_info "valid images:" "${VALID_DOCKER_IMAGES[@]}" echo_info "valid images:" "${VALID_DOCKER_IMAGES[@]}"
return 1 return 1
@@ -96,155 +96,168 @@ FB_FUNC_NAMES+=('docker_build_image')
FB_FUNC_DESCS['docker_build_image']='build docker image with required dependencies pre-installed' FB_FUNC_DESCS['docker_build_image']='build docker image with required dependencies pre-installed'
FB_FUNC_COMPLETION['docker_build_image']="${VALID_DOCKER_IMAGES[*]}" FB_FUNC_COMPLETION['docker_build_image']="${VALID_DOCKER_IMAGES[*]}"
docker_build_image() { docker_build_image() {
validate_selected_image "$@" || return 1 local image="$1"
validate_selected_image "${image}" || return 1
check_docker || return 1 check_docker || return 1
test -d "${DOCKER_DIR}" || mkdir -p "${DOCKER_DIR}" test -d "${DOCKER_DIR}" || mkdir -p "${DOCKER_DIR}"
PLATFORM="${PLATFORM:-$(echo_platform)}" PLATFORM="${PLATFORM:-$(echo_platform)}"
for distro in "${DISTROS[@]}"; do echo_info "sourcing package manager for ${distro}"
echo_info "sourcing package manager for ${distro}" local dockerDistro="$(get_docker_image_tag "${distro}")"
local dockerDistro="$(get_docker_image_tag "${distro}")" # specific file for evaluated package manager info
# specific file for evaluated package manager info distroPkgMgr="${DOCKER_DIR}/$(bash_basename "${distro}")-pkg_mgr"
distroPkgMgr="${DOCKER_DIR}/$(bash_basename "${distro}")-pkg_mgr" # get package manager info
# get package manager info docker run \
docker run \ "${DOCKER_RUN_FLAGS[@]}" \
"${DOCKER_RUN_FLAGS[@]}" \ "${dockerDistro}" \
"${dockerDistro}" \ bash -c "./scripts/print_pkg_mgr.sh" | tr -d '\r' >"${distroPkgMgr}"
bash -c "./scripts/print_pkg_mgr.sh" | tr -d '\r' >"${distroPkgMgr}" # shellcheck disable=SC1090
# shellcheck disable=SC1090 cat "${distroPkgMgr}"
cat "${distroPkgMgr}" # shellcheck disable=SC1090
# shellcheck disable=SC1090 source "${distroPkgMgr}"
source "${distroPkgMgr}"
dockerfile="${DOCKER_DIR}/Dockerfile_$(bash_basename "${distro}")" dockerfile="${DOCKER_DIR}/Dockerfile_$(bash_basename "${distro}")"
{ {
echo "FROM ${dockerDistro}" echo "FROM ${dockerDistro}"
echo 'SHELL ["/bin/bash", "-c"]' echo 'SHELL ["/bin/bash", "-c"]'
echo 'RUN ln -sf /bin/bash /bin/sh' echo 'RUN ln -sf /bin/bash /bin/sh'
echo 'ENV DEBIAN_FRONTEND=noninteractive' echo 'ENV DEBIAN_FRONTEND=noninteractive'
# arch is rolling release, so highly likely # arch is rolling release, so highly likely
# an updated is required between pkg changes # an updated is required between pkg changes
if line_contains "${dockerDistro}" 'arch'; then if line_contains "${dockerDistro}" 'arch'; then
local archRuns='' local archRuns=''
archRuns+="${pkg_mgr_update}" archRuns+="${pkg_mgr_update}"
archRuns+=" && ${pkg_mgr_upgrade}" archRuns+=" && ${pkg_mgr_upgrade}"
archRuns+=" && ${pkg_install} ${req_pkgs[*]}" archRuns+=" && ${pkg_install} ${req_pkgs[*]}"
echo "RUN ${archRuns}" echo "RUN ${archRuns}"
else else
echo "RUN ${pkg_mgr_update}" echo "RUN ${pkg_mgr_update}"
echo "RUN ${pkg_mgr_upgrade}" echo "RUN ${pkg_mgr_upgrade}"
printf "RUN ${pkg_install} %s\n" "${req_pkgs[@]}" printf "RUN ${pkg_install} %s\n" "${req_pkgs[@]}"
fi fi
echo 'RUN pipx install virtualenv' echo 'RUN pipx install virtualenv'
echo 'RUN pipx ensurepath' echo 'RUN pipx ensurepath'
echo 'ENV CARGO_HOME="/root/.cargo"' echo 'ENV CARGO_HOME="/root/.cargo"'
echo 'ENV RUSTUP_HOME="/root/.rustup"' echo 'ENV RUSTUP_HOME="/root/.rustup"'
echo 'ENV PATH="/root/.cargo/bin:$PATH"' echo 'ENV PATH="/root/.cargo/bin:$PATH"'
local cargoInst='' local cargoInst=''
cargoInst+='curl https://sh.rustup.rs -sSf | bash -s -- -y' cargoInst+='curl https://sh.rustup.rs -sSf | bash -s -- -y'
cargoInst+=' && rustup update stable' cargoInst+=' && rustup update stable'
cargoInst+=' && cargo install cargo-c' cargoInst+=' && cargo install cargo-c'
cargoInst+=' && rm -rf "${CARGO_HOME}"/registry "${CARGO_HOME}"/git' cargoInst+=' && rm -rf "${CARGO_HOME}"/registry "${CARGO_HOME}"/git'
echo "RUN ${cargoInst}" echo "RUN ${cargoInst}"
# since any user may run this image, # since any user may run this image,
# open up root tools to everyone # open up root tools to everyone
echo 'ENV PATH="/root/.local/bin:$PATH"' echo 'ENV PATH="/root/.local/bin:$PATH"'
echo 'RUN chmod 777 -R /root/' echo 'RUN chmod 777 -R /root/'
echo "WORKDIR ${DOCKER_WORKDIR}" echo "WORKDIR ${DOCKER_WORKDIR}"
} >"${dockerfile}" } >"${dockerfile}"
image_tag="$(set_distro_image_tag "${distro}")" image_tag="$(set_distro_image_tag "${distro}")"
docker buildx build \
--platform "${PLATFORM}" \
-t "${image_tag}" \
-f "${dockerfile}" \
. || return 1
# if a docker registry is defined, push to it
if [[ ${DOCKER_REGISTRY} != '' ]]; then
docker_login || return 1
docker buildx build \ docker buildx build \
--push \
--platform "${PLATFORM}" \ --platform "${PLATFORM}" \
-t "${image_tag}" \ -t "${DOCKER_REGISTRY}/${image_tag}" \
-f "${dockerfile}" \ -f "${dockerfile}" \
. || return 1 . || return 1
fi
# if a docker registry is defined, push to it docker system prune -f
if [[ ${DOCKER_REGISTRY} != '' ]]; then
docker_login || return 1
docker buildx build \
--push \
--platform "${PLATFORM}" \
-t "${DOCKER_REGISTRY}/${image_tag}" \
-f "${dockerfile}" \
. || return 1
fi
docker system prune -f
done
} }
FB_FUNC_NAMES+=('docker_save_image') FB_FUNC_NAMES+=('docker_save_image')
FB_FUNC_DESCS['docker_save_image']='save docker image into tar.zst' FB_FUNC_DESCS['docker_save_image']='save docker image into tar.zst'
FB_FUNC_COMPLETION['docker_save_image']="${VALID_DOCKER_IMAGES[*]}" FB_FUNC_COMPLETION['docker_save_image']="${VALID_DOCKER_IMAGES[*]}"
docker_save_image() { docker_save_image() {
validate_selected_image "$@" || return 1 local image="$1"
validate_selected_image "${image}" || return 1
check_docker || return 1 check_docker || return 1
for distro in "${DISTROS[@]}"; do image_tag="$(set_distro_image_tag "${distro}")"
image_tag="$(set_distro_image_tag "${distro}")" echo_info "saving docker image for ${image_tag}"
echo_info "saving docker image for ${image_tag}" docker save "${image_tag}" |
docker save "${image_tag}" | zstd -T0 >"${DOCKER_DIR}/$(docker_image_archive_name "${image_tag}")" ||
zstd -T0 >"${DOCKER_DIR}/$(docker_image_archive_name "${image_tag}")" || return 1
return 1
done
} }
FB_FUNC_NAMES+=('docker_load_image') FB_FUNC_NAMES+=('docker_load_image')
FB_FUNC_DESCS['docker_load_image']='load docker image from tar.zst' FB_FUNC_DESCS['docker_load_image']='load docker image from tar.zst'
FB_FUNC_COMPLETION['docker_load_image']="${VALID_DOCKER_IMAGES[*]}" FB_FUNC_COMPLETION['docker_load_image']="${VALID_DOCKER_IMAGES[*]}"
docker_load_image() { docker_load_image() {
validate_selected_image "$@" || return 1 local image="$1"
validate_selected_image "${image}" || return 1
check_docker || return 1 check_docker || return 1
for distro in "${DISTROS[@]}"; do image_tag="$(set_distro_image_tag "${distro}")"
image_tag="$(set_distro_image_tag "${distro}")" echo_info "loading docker image for ${image_tag}"
echo_info "loading docker image for ${image_tag}" local archive="${DOCKER_DIR}/$(docker_image_archive_name "${image_tag}")"
local archive="${DOCKER_DIR}/$(docker_image_archive_name "${image_tag}")" test -f "$archive" || return 1
test -f "$archive" || return 1 zstdcat -T0 "$archive" |
zstdcat -T0 "$archive" | docker load || return 1
docker load || return 1 docker system prune -f
docker system prune -f
done
} }
FB_FUNC_NAMES+=('docker_run_image') FB_FUNC_NAMES+=('docker_run_image')
FB_FUNC_DESCS['docker_run_image']='run docker image to build ffmpeg' FB_FUNC_DESCS['docker_run_image']='run docker image with given flags'
FB_FUNC_COMPLETION['docker_run_image']="${VALID_DOCKER_IMAGES[*]}" FB_FUNC_COMPLETION['docker_run_image']="${VALID_DOCKER_IMAGES[*]}"
docker_run_image() { docker_run_image() {
validate_selected_image "$@" || return 1 local image="$1"
validate_selected_image "${image}" || return 1
check_docker || return 1 check_docker || return 1
for distro in "${DISTROS[@]}"; do local cmd="${2}"
dockerDistro="${distro//-/:}" local runCmd=()
image_tag="$(set_distro_image_tag "${distro}")" if [[ ${cmd} == '' ]]; then
DOCKER_RUN_FLAGS+=("-it")
else
runCmd+=(bash -c "${cmd}")
fi
# if a docker registry is defined, pull from it dockerDistro="${distro//-/:}"
if [[ ${DOCKER_REGISTRY} != '' ]]; then image_tag="$(set_distro_image_tag "${distro}")"
docker_login || return 1
docker pull \
"${DOCKER_REGISTRY}/${image_tag}" || return 1
docker tag "${DOCKER_REGISTRY}/${image_tag}" "${image_tag}"
fi
echo_info "running ffmpeg build with ${image_tag}" # if a docker registry is defined, pull from it
docker run \ if [[ ${DOCKER_REGISTRY} != '' ]]; then
"${DOCKER_RUN_FLAGS[@]}" \ docker_login || return 1
-u "$(id -u):$(id -g)" \ docker pull \
"${image_tag}" \ "${DOCKER_REGISTRY}/${image_tag}" || return 1
./scripts/build.sh || return 1 docker tag "${DOCKER_REGISTRY}/${image_tag}" "${image_tag}"
fi
docker system prune -f echo_info "running ffmpeg build with ${image_tag}"
docker run \
"${DOCKER_RUN_FLAGS[@]}" \
-u "$(id -u):$(id -g)" \
"${image_tag}" \
"${runCmd[@]}" || return 1
return 0 docker system prune -f
done
return 0
}
FB_FUNC_NAMES+=('build_with_docker')
FB_FUNC_DESCS['build_with_docker']='run docker image with given flags'
FB_FUNC_COMPLETION['build_with_docker']="${VALID_DOCKER_IMAGES[*]}"
build_with_docker() {
local image="$1"
docker_run_image "${image}" ./scripts/build.sh
} }
FB_FUNC_NAMES+=('docker_build_multiarch_image') FB_FUNC_NAMES+=('docker_build_multiarch_image')
FB_FUNC_DESCS['docker_build_multiarch_image']='build multiarch docker image' FB_FUNC_DESCS['docker_build_multiarch_image']='build multiarch docker image'
FB_FUNC_COMPLETION['docker_build_multiarch_image']="${VALID_DOCKER_IMAGES[*]}" FB_FUNC_COMPLETION['docker_build_multiarch_image']="${VALID_DOCKER_IMAGES[*]}"
docker_build_multiarch_image() { docker_build_multiarch_image() {
validate_selected_image "$@" || return 1 local image="$1"
validate_selected_image "${image}" || return 1
check_docker || return 1 check_docker || return 1
PLATFORM='linux/amd64,linux/arm64' PLATFORM='linux/amd64,linux/arm64'

View File

@@ -175,7 +175,8 @@ efg_encode() {
for ((grain = LOW; grain <= HIGH; grain += STEP)); do for ((grain = LOW; grain <= HIGH; grain += STEP)); do
local file="$(bash_basename "${vid}")" local file="$(bash_basename "${vid}")"
local out="${EFG_DIR}/grain-${grain}-${file}" local out="${EFG_DIR}/grain-${grain}-${file}"
encode -P 10 -g ${grain} -i "${vid}" "${out}" echo_info "encoding ${file} with grain ${grain}"
echo_if_fail encode -P 10 -g ${grain} -i "${vid}" "${out}"
echo -e "\tgrain: ${grain}, bitrate: $(get_avg_bitrate "${out}")" >>"${GRAIN_LOG}" echo -e "\tgrain: ${grain}, bitrate: $(get_avg_bitrate "${out}")" >>"${GRAIN_LOG}"
rm "${out}" rm "${out}"
done done
@@ -200,7 +201,7 @@ efg_plot() {
IFS=',' read -r grainText bitrateText <<<"${noWhite}" IFS=',' read -r grainText bitrateText <<<"${noWhite}"
IFS=':' read -r _ grain <<<"${grainText}" IFS=':' read -r _ grain <<<"${grainText}"
IFS=':' read -r _ bitrate <<<"${bitrateText}" IFS=':' read -r _ bitrate <<<"${bitrateText}"
if [[ ${setNewReference} == 'true' ]]; then if [[ ${setNewReference} == true ]]; then
referenceBitrate="${bitrate}" referenceBitrate="${bitrate}"
setNewReference=false setNewReference=false
fi fi
@@ -248,7 +249,7 @@ efg() {
GRAIN_LOG="${EFG_DIR}/${LOW}-${STEP}-${HIGH}-grains.txt" GRAIN_LOG="${EFG_DIR}/${LOW}-${STEP}-${HIGH}-grains.txt"
if [[ ${PLOT} == 'true' && -f ${GRAIN_LOG} ]]; then if [[ ${PLOT} == true && -f ${GRAIN_LOG} ]]; then
efg_plot efg_plot
return $? return $?
fi fi
@@ -256,7 +257,7 @@ efg() {
efg_segment || return 1 efg_segment || return 1
efg_encode || return 1 efg_encode || return 1
if [[ ${PLOT} == 'true' && -f ${GRAIN_LOG} ]]; then if [[ ${PLOT} == true && -f ${GRAIN_LOG} ]]; then
efg_plot || return 1 efg_plot || return 1
fi fi
} }

View File

@@ -381,7 +381,7 @@ gen_encode_script() {
# actually do ffmpeg commmand # actually do ffmpeg commmand
echo echo
if [[ ${DISABLE_DV} == 'false' ]]; then if [[ ${DISABLE_DV} == false ]]; then
echo 'ffmpeg "${ffmpegParams[@]}" -dolbyvision 1 "${OUTPUT}" || \' echo 'ffmpeg "${ffmpegParams[@]}" -dolbyvision 1 "${OUTPUT}" || \'
fi fi
echo 'ffmpeg "${ffmpegParams[@]}" -dolbyvision 0 "${OUTPUT}" || exit 1' echo 'ffmpeg "${ffmpegParams[@]}" -dolbyvision 0 "${OUTPUT}" || exit 1'
@@ -398,7 +398,7 @@ gen_encode_script() {
echo echo
} >"${genScript}" } >"${genScript}"
if [[ ${PRINT_OUT} == 'true' ]]; then if [[ ${PRINT_OUT} == true ]]; then
echo_info "${genScript} contents:" echo_info "${genScript} contents:"
echo "$(<"${genScript}")" echo "$(<"${genScript}")"
else else

22
lib/readme.sh Normal file
View File

@@ -0,0 +1,22 @@
#!/usr/bin/env bash
FB_FUNC_NAMES+=('gen_readme')
FB_FUNC_DESCS['gen_readme']='generate project README.md'
gen_readme() {
local readme="${REPO_DIR}/README.md"
echo "
A collection of scripts for building ffmpeg and encoding content with the built ffmpeg
Tested on:
- linux x86_64/aarch64 on:
$(printf ' - %s\n' "${VALID_DOCKER_IMAGES[@]}")
- darwin aarch64
\`\`\`bash
$(print_cmds false)
\`\`\`
" >"${readme}"
}

14
main.sh
View File

@@ -55,14 +55,22 @@ $cmd "$@"' >"${ENTRY_SCRIPT}"
FB_FUNC_NAMES+=('print_cmds') FB_FUNC_NAMES+=('print_cmds')
FB_FUNC_DESCS['print_cmds']='print usable commands' FB_FUNC_DESCS['print_cmds']='print usable commands'
print_cmds() { print_cmds() {
echo -e "\n~~~ Usable Commands ~~~" local color="${1:-true}"
local uncolor=''
if [[ ${color} == true ]]; then
color="${CYAN}"
uncolor="${NC}"
else
color=''
fi
echo -e "~~~ Usable Commands ~~~\n"
for funcname in "${FB_FUNC_NAMES[@]}"; do for funcname in "${FB_FUNC_NAMES[@]}"; do
echo -e "${CYAN}${funcname}${NC}:\n\t" "${FB_FUNC_DESCS[${funcname}]}" echo -e "${color}${funcname}${uncolor}:\n\t" "${FB_FUNC_DESCS[${funcname}]}"
if [[ $FB_RUNNING_AS_SCRIPT -eq 0 ]]; then if [[ $FB_RUNNING_AS_SCRIPT -eq 0 ]]; then
(cd "$SCRIPT_DIR" && ln -sf entry.sh "${funcname}.sh") (cd "$SCRIPT_DIR" && ln -sf entry.sh "${funcname}.sh")
fi fi
done done
echo -e "~~~~~~~~~~~~~~~~~~~~~~~\n" echo -e "\n"
} }
set_completions() { set_completions() {

View File

@@ -0,0 +1 @@
entry.sh

1
scripts/gen_readme.sh Symbolic link
View File

@@ -0,0 +1 @@
entry.sh