mirror of
https://github.com/CCExtractor/ccextractor.git
synced 2026-02-04 05:44:53 +00:00
OCR build fix: - linuxdeploy was failing with "Invalid magic bytes in file header" because it was passed the wrapper script instead of the actual binary - When OCR is enabled, ccextractor is renamed to ccextractor.bin and a wrapper script sets TESSDATA_PREFIX before executing the binary - Now correctly passes ccextractor.bin to linuxdeploy when it exists HardSubX build fix: - Add libavdevice-dev to FFmpeg dependencies in CI workflow - rusty_ffmpeg requires libavdevice which was missing 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
231 lines
6.7 KiB
Bash
Executable File
231 lines
6.7 KiB
Bash
Executable File
#!/bin/bash
|
|
#
|
|
# CCExtractor AppImage Build Script
|
|
#
|
|
# Build variants via BUILD_TYPE environment variable:
|
|
# - minimal: Basic CCExtractor without OCR (smallest size)
|
|
# - ocr: CCExtractor with OCR support (default)
|
|
# - hardsubx: CCExtractor with burned-in subtitle extraction (requires FFmpeg)
|
|
#
|
|
# Usage:
|
|
# ./build_appimage.sh # Builds 'ocr' variant (default)
|
|
# BUILD_TYPE=minimal ./build_appimage.sh
|
|
# BUILD_TYPE=hardsubx ./build_appimage.sh
|
|
#
|
|
# Requirements:
|
|
# - CMake, GCC, pkg-config, Rust toolchain
|
|
# - For OCR: tesseract-ocr, libtesseract-dev, libleptonica-dev
|
|
# - For HardSubX: libavcodec-dev, libavformat-dev, libswscale-dev, etc.
|
|
# - wget for downloading linuxdeploy
|
|
#
|
|
|
|
set -e
|
|
|
|
# Build type: minimal, ocr, hardsubx (default: ocr)
|
|
BUILD_TYPE="${BUILD_TYPE:-ocr}"
|
|
|
|
echo "=========================================="
|
|
echo "CCExtractor AppImage Builder"
|
|
echo "Build type: $BUILD_TYPE"
|
|
echo "=========================================="
|
|
|
|
# Validate build type
|
|
case "$BUILD_TYPE" in
|
|
minimal|ocr|hardsubx)
|
|
;;
|
|
*)
|
|
echo "Error: Invalid BUILD_TYPE '$BUILD_TYPE'"
|
|
echo "Valid options: minimal, ocr, hardsubx"
|
|
exit 1
|
|
;;
|
|
esac
|
|
|
|
# Store paths
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(dirname "$SCRIPT_DIR")"
|
|
BUILD_DIR="$SCRIPT_DIR/appimage_build"
|
|
|
|
# Clean up function
|
|
cleanup() {
|
|
if [ -d "$BUILD_DIR" ]; then
|
|
echo "Cleaning up build directory..."
|
|
rm -rf "$BUILD_DIR"
|
|
fi
|
|
}
|
|
|
|
# Cleanup on exit (comment out for debugging)
|
|
trap cleanup EXIT
|
|
|
|
# Create fresh build directory
|
|
rm -rf "$BUILD_DIR" 2>/dev/null || true
|
|
mkdir -p "$BUILD_DIR"
|
|
|
|
cd "$BUILD_DIR"
|
|
|
|
# Determine CMake options based on build type
|
|
CMAKE_OPTIONS=""
|
|
case "$BUILD_TYPE" in
|
|
minimal)
|
|
CMAKE_OPTIONS=""
|
|
;;
|
|
ocr)
|
|
CMAKE_OPTIONS="-DWITH_OCR=ON"
|
|
;;
|
|
hardsubx)
|
|
CMAKE_OPTIONS="-DWITH_OCR=ON -DWITH_HARDSUBX=ON -DWITH_FFMPEG=ON"
|
|
;;
|
|
esac
|
|
|
|
echo "CMake options: $CMAKE_OPTIONS"
|
|
|
|
# Configure with CMake
|
|
echo "Configuring with CMake..."
|
|
cmake $CMAKE_OPTIONS "$REPO_ROOT/src"
|
|
|
|
# Build
|
|
echo "Building CCExtractor..."
|
|
make -j$(nproc)
|
|
|
|
# Verify binary was built
|
|
if [ ! -f "$BUILD_DIR/ccextractor" ]; then
|
|
echo "Error: ccextractor binary not found after build"
|
|
exit 1
|
|
fi
|
|
|
|
echo "Build successful!"
|
|
"$BUILD_DIR/ccextractor" --version
|
|
|
|
# Download linuxdeploy
|
|
echo "Downloading linuxdeploy..."
|
|
LINUXDEPLOY_URL="https://github.com/linuxdeploy/linuxdeploy/releases/download/continuous/linuxdeploy-x86_64.AppImage"
|
|
wget -q --show-progress "$LINUXDEPLOY_URL" -O linuxdeploy-x86_64.AppImage
|
|
chmod +x linuxdeploy-x86_64.AppImage
|
|
|
|
# Create AppDir structure
|
|
echo "Creating AppDir structure..."
|
|
mkdir -p AppDir/usr/bin
|
|
mkdir -p AppDir/usr/share/icons/hicolor/256x256/apps
|
|
mkdir -p AppDir/usr/share/applications
|
|
mkdir -p AppDir/usr/share/tessdata
|
|
|
|
# Copy binary
|
|
cp "$BUILD_DIR/ccextractor" AppDir/usr/bin/
|
|
|
|
# Download icon
|
|
echo "Downloading icon..."
|
|
PNG_URL="https://ccextractor.org/images/ccextractor.png"
|
|
if wget -q "$PNG_URL" -O AppDir/usr/share/icons/hicolor/256x256/apps/ccextractor.png 2>/dev/null; then
|
|
echo "Icon downloaded successfully"
|
|
else
|
|
# Create a simple placeholder icon if download fails
|
|
echo "Warning: Could not download icon, creating placeholder"
|
|
convert -size 256x256 xc:navy -fill white -gravity center -pointsize 40 -annotate 0 "CCX" \
|
|
AppDir/usr/share/icons/hicolor/256x256/apps/ccextractor.png 2>/dev/null || \
|
|
echo "P3 256 256 255" > AppDir/usr/share/icons/hicolor/256x256/apps/ccextractor.ppm
|
|
fi
|
|
|
|
# Create desktop file
|
|
cat > AppDir/usr/share/applications/ccextractor.desktop << 'EOF'
|
|
[Desktop Entry]
|
|
Type=Application
|
|
Name=CCExtractor
|
|
Comment=Extract closed captions and subtitles from video files
|
|
Exec=ccextractor
|
|
Icon=ccextractor
|
|
Categories=AudioVideo;Video;
|
|
Terminal=true
|
|
NoDisplay=true
|
|
EOF
|
|
|
|
# Copy desktop file to AppDir root (required by linuxdeploy)
|
|
cp AppDir/usr/share/applications/ccextractor.desktop AppDir/
|
|
|
|
# Copy icon to AppDir root
|
|
cp AppDir/usr/share/icons/hicolor/256x256/apps/ccextractor.png AppDir/ 2>/dev/null || true
|
|
|
|
# For OCR builds, bundle tessdata
|
|
if [ "$BUILD_TYPE" = "ocr" ] || [ "$BUILD_TYPE" = "hardsubx" ]; then
|
|
echo "Bundling tessdata for OCR support..."
|
|
|
|
# Try to find system tessdata
|
|
TESSDATA_PATHS=(
|
|
"/usr/share/tesseract-ocr/5/tessdata"
|
|
"/usr/share/tesseract-ocr/4.00/tessdata"
|
|
"/usr/share/tessdata"
|
|
"/usr/local/share/tessdata"
|
|
)
|
|
|
|
TESSDATA_SRC=""
|
|
for path in "${TESSDATA_PATHS[@]}"; do
|
|
if [ -d "$path" ] && [ -f "$path/eng.traineddata" ]; then
|
|
TESSDATA_SRC="$path"
|
|
break
|
|
fi
|
|
done
|
|
|
|
if [ -n "$TESSDATA_SRC" ]; then
|
|
echo "Found tessdata at: $TESSDATA_SRC"
|
|
# Copy English language data (most common)
|
|
cp "$TESSDATA_SRC/eng.traineddata" AppDir/usr/share/tessdata/ 2>/dev/null || true
|
|
# Copy OSD (orientation and script detection) if available
|
|
cp "$TESSDATA_SRC/osd.traineddata" AppDir/usr/share/tessdata/ 2>/dev/null || true
|
|
else
|
|
echo "Warning: tessdata not found, downloading English language data..."
|
|
wget -q "https://github.com/tesseract-ocr/tessdata/raw/main/eng.traineddata" \
|
|
-O AppDir/usr/share/tessdata/eng.traineddata || true
|
|
fi
|
|
|
|
# Create wrapper script that sets TESSDATA_PREFIX
|
|
mv AppDir/usr/bin/ccextractor AppDir/usr/bin/ccextractor.bin
|
|
cat > AppDir/usr/bin/ccextractor << 'WRAPPER'
|
|
#!/bin/bash
|
|
SELF_DIR="$(dirname "$(readlink -f "$0")")"
|
|
export TESSDATA_PREFIX="${SELF_DIR}/../share/tessdata"
|
|
exec "${SELF_DIR}/ccextractor.bin" "$@"
|
|
WRAPPER
|
|
chmod +x AppDir/usr/bin/ccextractor
|
|
fi
|
|
|
|
# Determine output name based on build type
|
|
ARCH="x86_64"
|
|
case "$BUILD_TYPE" in
|
|
minimal)
|
|
OUTPUT_NAME="ccextractor-minimal-${ARCH}.AppImage"
|
|
;;
|
|
ocr)
|
|
OUTPUT_NAME="ccextractor-${ARCH}.AppImage"
|
|
;;
|
|
hardsubx)
|
|
OUTPUT_NAME="ccextractor-hardsubx-${ARCH}.AppImage"
|
|
;;
|
|
esac
|
|
|
|
# Build AppImage
|
|
echo "Building AppImage..."
|
|
export OUTPUT="$OUTPUT_NAME"
|
|
|
|
# Determine which executable to pass to linuxdeploy
|
|
# For OCR builds, we have a wrapper script, so pass the actual binary (.bin)
|
|
if [ -f "AppDir/usr/bin/ccextractor.bin" ]; then
|
|
LINUXDEPLOY_EXEC="AppDir/usr/bin/ccextractor.bin"
|
|
else
|
|
LINUXDEPLOY_EXEC="AppDir/usr/bin/ccextractor"
|
|
fi
|
|
|
|
./linuxdeploy-x86_64.AppImage \
|
|
--appdir=AppDir \
|
|
--executable="$LINUXDEPLOY_EXEC" \
|
|
--desktop-file=AppDir/ccextractor.desktop \
|
|
--icon-file=AppDir/ccextractor.png \
|
|
--output=appimage
|
|
|
|
# Move to output directory
|
|
mv "$OUTPUT_NAME" "$SCRIPT_DIR/"
|
|
|
|
echo "=========================================="
|
|
echo "AppImage built successfully!"
|
|
echo "Output: $SCRIPT_DIR/$OUTPUT_NAME"
|
|
echo ""
|
|
echo "Test with: $SCRIPT_DIR/$OUTPUT_NAME --version"
|
|
echo "=========================================="
|