Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Library updates and additional install experience robustness. #96

Merged
merged 3 commits into from
Oct 14, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 37 additions & 44 deletions build-ffmpeg
Original file line number Diff line number Diff line change
Expand Up @@ -788,35 +788,27 @@ if ${NONFREE_AND_GPL}; then

if build "x264" "latest"; then

clone "https://code.videolan.org/videolan/x264.git" "x264-latest"
clone "https://code.videolan.org/videolan/x264.git" "x264-${CURRENT_PACKAGE_VERSION}"
execute ./configure --prefix="${WORKSPACE}" --enable-static --enable-pic

execute make -j ${MJOBS}
execute make install
execute make install-lib-static

build_done "x264" "latest"
build_done "x264" "${CURRENT_PACKAGE_VERSION}"
fi

CONFIGURE_OPTIONS+=("--enable-libx264")
fi

if ${NONFREE_AND_GPL} && (isAppleSilicon || [[ ! "${TARGET_ARCH}" == "arm"* ]]) ; then
# 32-bit ARM platforms like Raspberry Pi don't build x265 cleanly.
if ${NONFREE_AND_GPL} && [[ ! "${TARGET_ARCH}" == "armv7l" ]] ; then

if build "x265" "latest"; then

if isAppleSilicon; then

download "https://bitbucket.org/multicoreware/x265_git/get/931178347b3f73e40798fd5180209654536bbaa5.tar.gz" "x265-3.5.tar.gz" # This is actually 3.4 if looking at x265Versio
else

clone "https://bitbucket.org/multicoreware/x265_git.git" "x265-latest"
fi
clone "https://bitbucket.org/multicoreware/x265_git.git" "x265-${CURRENT_PACKAGE_VERSION}"

cd build/linux || exit
execute cmake -G "Unix Makefiles" ../../source
# execute env CMAKE_INSTALL_PREFIX="${WORKSPACE}" bash ./multilib.sh

rm -rf 8bit 10bit 12bit 2>/dev/null
mkdir -p 8bit 10bit 12bit

Expand Down Expand Up @@ -858,32 +850,33 @@ EOF
sed -i.backup 's/-lgcc_s/-lgcc_eh/g' "${WORKSPACE}/lib/pkgconfig/x265.pc" # The -i.backup is intended and required on macOS: https://stackoverflow.com/questions/5694228/sed-in-place-flag-that-works-both-on-mac-bsd-and-linux
fi

build_done "x265" "latest"
build_done "x265" "${CURRENT_PACKAGE_VERSION}"
fi

CONFIGURE_OPTIONS+=("--enable-libx265")
fi

if [[ ! "${TARGET_ARCH}" == "arm"* ]]; then
if build "libvpx" "1.13.0"; then

download "https://github.com/webmproject/libvpx/archive/refs/tags/v1.13.0.tar.gz" "libvpx-1.13.0.tar.gz"
if build "libvpx" "1.13.0"; then

if [[ "${TARGET_OS}" == "darwin" ]]; then
download "https://github.com/webmproject/libvpx/archive/refs/tags/v1.13.0.tar.gz" "libvpx-1.13.0.tar.gz"

echo "Applying Darwin patch"
sed "s/,--version-script//g" build/make/Makefile > build/make/Makefile.patched
sed "s/-Wl,--no-undefined -Wl,-soname/-Wl,-undefined,error -Wl,-install_name/g" build/make/Makefile.patched > build/make/Makefile
fi
if [[ "${TARGET_OS}" == "darwin" ]]; then

execute ./configure --prefix="${WORKSPACE}" --disable-unit-tests --disable-shared --disable-examples --as=yasm --enable-vp9-highbitdepth
execute make -j ${MJOBS}
execute make install
echo "Applying Darwin patch"
sed "s/,--version-script//g" build/make/Makefile > build/make/Makefile.patched
sed "s/-Wl,--no-undefined -Wl,-soname/-Wl,-undefined,error -Wl,-install_name/g" build/make/Makefile.patched > build/make/Makefile
fi

build_done "libvpx" "1.13.0"
fi
execute ./configure --prefix="${WORKSPACE}" --disable-unit-tests --disable-shared --disable-examples --as=yasm --enable-vp9-highbitdepth
execute make -j ${MJOBS}
execute make install

build_done "libvpx" "1.13.0"
fi

CONFIGURE_OPTIONS+=("--enable-libvpx")
CONFIGURE_OPTIONS+=("--enable-libvpx")
fi

if ${NONFREE_AND_GPL}; then
Expand Down Expand Up @@ -1073,13 +1066,13 @@ if ! isLinux; then

if build "opencore" "0.1.6"; then

download "https://downloads.sourceforge.net/project/opencore-amr/opencore-amr/opencore-amr-0.1.6.tar.gz" "opencore-amr-0.1.6.tar.gz"
download "https://downloads.sourceforge.net/project/opencore-amr/opencore-amr/opencore-amr-${CURRENT_PACKAGE_VERSION}.tar.gz"

execute ./configure --prefix="${WORKSPACE}" --disable-shared --enable-static
execute make -j ${MJOBS}
execute make install

build_done "opencore" "0.1.6"
build_done "opencore" "${CURRENT_PACKAGE_VERSION}"
fi
fi

Expand All @@ -1089,40 +1082,40 @@ if ! isLinux; then

if build "lame" "3.100"; then

download "https://downloads.sourceforge.net/project/lame/lame/3.100/lame-3.100.tar.gz" "lame-3.100.tar.gz"
download "https://downloads.sourceforge.net/project/lame/lame/3.100/lame-${CURRENT_PACKAGE_VERSION}.tar.gz"

execute ./configure --prefix="${WORKSPACE}" --disable-shared --enable-static
execute make -j ${MJOBS}
execute make install

build_done "lame" "3.100"
build_done "lame" "${CURRENT_PACKAGE_VERSION}"
fi
fi

CONFIGURE_OPTIONS+=("--enable-libmp3lame")

if build "opus" "1.4"; then

download "https://downloads.xiph.org/releases/opus/opus-1.4.tar.gz"
download "https://downloads.xiph.org/releases/opus/opus-${CURRENT_PACKAGE_VERSION}.tar.gz"

execute ./configure --prefix="${WORKSPACE}" --disable-shared --enable-static
execute make -j ${MJOBS}
execute make install

build_done "opus" "1.4"
build_done "opus" "${CURRENT_PACKAGE_VERSION}"
fi

CONFIGURE_OPTIONS+=("--enable-libopus")

if build "speex" "1.2.1"; then

download "https://ftp.osuosl.org/pub/xiph/releases/speex/speex-1.2.1.tar.gz"
download "https://ftp.osuosl.org/pub/xiph/releases/speex/speex-${CURRENT_PACKAGE_VERSION}.tar.gz"

execute ./configure --prefix="${WORKSPACE}" --disable-shared --enable-static
execute make -j ${MJOBS}
execute make install

build_done "speex" "1.2.1"
build_done "speex" "${CURRENT_PACKAGE_VERSION}"
fi

CONFIGURE_OPTIONS+=("--enable-libspeex")
Expand All @@ -1131,18 +1124,18 @@ if ! isLinux; then

if build "libogg" "1.3.5"; then

download "https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-1.3.5.tar.xz"
download "https://ftp.osuosl.org/pub/xiph/releases/ogg/libogg-${CURRENT_PACKAGE_VERSION}.tar.xz"

execute ./configure --prefix="${WORKSPACE}" --disable-shared --enable-static
execute make -j ${MJOBS}
execute make install

build_done "libogg" "1.3.5"
build_done "libogg" "${CURRENT_PACKAGE_VERSION}"
fi

if build "libvorbis" "1.3.7"; then

download "https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-1.3.7.tar.gz"
download "https://ftp.osuosl.org/pub/xiph/releases/vorbis/libvorbis-${CURRENT_PACKAGE_VERSION}.tar.gz"

if [[ "${TARGET_OS}" == "darwin" ]]; then

Expand All @@ -1153,7 +1146,7 @@ if ! isLinux; then
execute make -j ${MJOBS}
execute make install

build_done "libvorbis" "1.3.7"
build_done "libvorbis" "${CURRENT_PACKAGE_VERSION}"
fi
fi

Expand All @@ -1163,7 +1156,7 @@ if ! isLinux; then

if build "libtheora" "1.1.1"; then

download "https://ftp.osuosl.org/pub/xiph/releases/theora/libtheora-1.1.1.tar.gz"
download "https://ftp.osuosl.org/pub/xiph/releases/theora/libtheora-${CURRENT_PACKAGE_VERSION}.tar.gz"

sed "s/-fforce-addr//g" configure > configure.patched
chmod +x configure.patched
Expand Down Expand Up @@ -1193,23 +1186,23 @@ if ! isLinux; then
execute make -j ${MJOBS}
execute make install

build_done "libtheora" "1.1.1"
build_done "libtheora" "${CURRENT_PACKAGE_VERSION}"
fi
fi

CONFIGURE_OPTIONS+=("--enable-libtheora")

if ${NONFREE_AND_GPL}; then

if build "fdk_aac" "2.0.2"; then
if build "fdk_aac" "2.0.3"; then

download "https://downloads.sourceforge.net/project/opencore-amr/fdk-aac/fdk-aac-2.0.2.tar.gz" "fdk-aac-2.0.2.tar.gz"
download "https://downloads.sourceforge.net/project/opencore-amr/fdk-aac/fdk-aac-${CURRENT_PACKAGE_VERSION}.tar.gz" "fdk-aac-${CURRENT_PACKAGE_VERSION}.tar.gz"

execute ./configure --prefix="${WORKSPACE}" --disable-shared --enable-static --enable-pic
execute make -j ${MJOBS}
execute make install

build_done "fdk_aac" "2.0.2"
build_done "fdk_aac" "${CURRENT_PACKAGE_VERSION}"
fi

CONFIGURE_OPTIONS+=("--enable-libfdk-aac")
Expand Down
100 changes: 68 additions & 32 deletions install.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ const dotenv = require("dotenv");
const get = require("simple-get");
const tar = require("tar");

const DOWNLOAD_RETRY_ATTEMPTS = 2;

function targetFfmpegRelease() {

return "v" + process.env.npm_package_version;
Expand Down Expand Up @@ -111,63 +113,97 @@ async function getDownloadFileName() {
}
}

async function downloadFfmpeg(downloadUrl, ffmpegDownloadPath) {
async function downloadFfmpeg(downloadUrl, ffmpegDownloadPath, retries = DOWNLOAD_RETRY_ATTEMPTS) {

// Open a write stream to the download location.
const tempFile = path.resolve(ffmpegCache(), ".download");
const file = fs.createWriteStream(tempFile);

console.log("Downloading FFmpeg from: %s", downloadUrl);
console.log("Downloading FFmpeg from: " + downloadUrl);

return new Promise((resolve, reject) => {

get({
url: downloadUrl,
}, (err, res) => {
const file = fs.createWriteStream(tempFile);

if(err || res.statusCode !== 200) {
const attemptDownload = () => {

return reject(err);
}
// Download the file.
get(downloadUrl, (err, res) => {

const totalBytes = parseInt(res.headers["content-length"], 10);
let downloadedBytes = 0;
if(err || (res.statusCode !== 200)) {

res.on("data", (chunk) => {
console.log("Download failed. Retrying.");

downloadedBytes = downloadedBytes + chunk.length;
const percent = Math.round((downloadedBytes / totalBytes) * 100) + "%";
process.stdout.write("\r" + percent);
});
// Clean up the incomplete download before proceeding.
if(retries > 0) {

file.on("finish", () => {
file.close();
fs.unlinkSync(tempFile);

console.log(" - Download Complete");
file.close();
});
return downloadFfmpeg(downloadUrl, ffmpegDownloadPath, retries - 1)
.then(resolve)
.catch(reject);
}

return reject(err || new Error("Failed to download after " + (DOWNLOAD_RETRY_ATTEMPTS + 1).toString() + " attempts."));
}

// We ensure totalBytes is never zero so we avoid divide-by-zero errors.
const totalBytes = parseInt(res.headers["content-length"], 10) || 1;
let downloadedBytes = 0;

// Inform users of our progress.
res.on("data", (chunk) => {

downloadedBytes += chunk.length;
process.stdout.write("\r" + Math.round((downloadedBytes / totalBytes) * 100).toString() + "%.");
});

file.on("close", () => {
// Download complete and the file is now closed, rename it.
file.on("close", () => {

fs.renameSync(tempFile, ffmpegDownloadPath);
resolve();
})
fs.renameSync(tempFile, ffmpegDownloadPath);
resolve();
});

file.on("error", (error) => {
// Error handling.
file.on("error", (error) => {

console.log(error);
reject(error)
console.log(error);
reject(error);
});

// All data written - we've completed the download.
file.on("finish", () => console.log(" - download complete."));

res.pipe(file);
}).on("error", (error) => {

console.log("Request error: ", error);

// Clean up the incomplete download before proceeding.
if(retries > 0) {

console.log("Retrying download.");
fs.unlinkSync(tempFile); // Clean up on error

return downloadFfmpeg(downloadUrl, ffmpegDownloadPath, retries - 1)
.then(resolve)
.catch(reject);
}

reject(new Error("Failed after " + (DOWNLOAD_RETRY_ATTEMPTS + 1).toString() + " attempts."));
});
};

res.pipe(file);
})
})
attemptDownload();
});
}

function binaryOk(ffmpegTempPath) {

try {

child_process.execSync(ffmpegTempPath + " -buildconf");

return true;
} catch (e) {

Expand Down Expand Up @@ -273,7 +309,7 @@ async function install() {
// Bootstrap the installation process.
async function bootstrap() {

console.log("Building for version: %s.", targetFfmpegRelease());
console.log("Retrieving FFmpeg from ffmpeg-for-homebridge release: %s.", targetFfmpegRelease());

try {

Expand Down