Compare commits
No commits in common. "6adf7401a5068c7eb752fec7cdb29f2bfc885fa1" and "7e8cffa07f230001328c4d5e1f02617f9d81f96e" have entirely different histories.
6adf7401a5
...
7e8cffa07f
84
Dockerfile
84
Dockerfile
@ -1,85 +1,13 @@
|
|||||||
FROM alpine:3.20 AS builder
|
FROM alpine:latest AS builder
|
||||||
|
|
||||||
# Build FFmpeg.
|
|
||||||
RUN apk add --no-cache \
|
|
||||||
rust \
|
|
||||||
cargo \
|
|
||||||
fdk-aac \
|
|
||||||
fdk-aac-dev \
|
|
||||||
clang16 \
|
|
||||||
clang16-static \
|
|
||||||
clang16-libclang \
|
|
||||||
llvm16-dev \
|
|
||||||
libc-dev \
|
|
||||||
pkgconf \
|
|
||||||
git \
|
|
||||||
build-base \
|
|
||||||
nasm \
|
|
||||||
yasm \
|
|
||||||
aom-dev \
|
|
||||||
dav1d-dev \
|
|
||||||
lame-dev \
|
|
||||||
opus-dev \
|
|
||||||
svt-av1-dev \
|
|
||||||
libvorbis-dev \
|
|
||||||
libvpx-dev \
|
|
||||||
x264-dev \
|
|
||||||
x265-dev \
|
|
||||||
numactl-dev \
|
|
||||||
libass-dev \
|
|
||||||
libunistring-dev \
|
|
||||||
gnutls-dev && \
|
|
||||||
mkdir -p /ffmpeg/{ffmpeg_build,bin} && \
|
|
||||||
cd /ffmpeg && \
|
|
||||||
wget -O ffmpeg-7.0.1.tar.bz2 https://ffmpeg.org/releases/ffmpeg-7.0.1.tar.bz2 && \
|
|
||||||
tar xjvf ffmpeg-7.0.1.tar.bz2 && \
|
|
||||||
cd ffmpeg-7.0.1 && \
|
|
||||||
PKG_CONFIG_PATH="/ffmpeg/ffmpeg_build/lib/pkgconfig" ./configure \
|
|
||||||
--prefix="/ffmpeg/ffmpeg_build" \
|
|
||||||
--pkg-config-flags="--static" \
|
|
||||||
--extra-cflags="-I/ffmpeg/ffmpeg_build/include" \
|
|
||||||
--extra-ldflags="-L/ffmpeg/ffmpeg_build/lib" \
|
|
||||||
--extra-libs="-lpthread -lm" \
|
|
||||||
--ld="g++" \
|
|
||||||
--bindir="/ffmpeg/bin" \
|
|
||||||
--enable-gpl \
|
|
||||||
--enable-gnutls \
|
|
||||||
--enable-libaom \
|
|
||||||
--enable-libass \
|
|
||||||
--enable-libfdk-aac \
|
|
||||||
--enable-libfreetype \
|
|
||||||
--enable-libmp3lame \
|
|
||||||
--enable-libopus \
|
|
||||||
--enable-libsvtav1 \
|
|
||||||
--enable-libdav1d \
|
|
||||||
--enable-libvorbis \
|
|
||||||
--enable-libvpx \
|
|
||||||
--enable-libx264 \
|
|
||||||
--enable-libx265 \
|
|
||||||
--enable-nonfree && \
|
|
||||||
PATH="/ffmpeg/bin:$PATH" make -j$(nproc) && \
|
|
||||||
make install && \
|
|
||||||
hash -r
|
|
||||||
|
|
||||||
# Build the app.
|
|
||||||
WORKDIR /build
|
WORKDIR /build
|
||||||
COPY ./ ./
|
COPY ./ ./
|
||||||
RUN cd /build && \
|
ARG PKG_CONFIG_PATH=/usr/lib/pkgconfig
|
||||||
export PKG_CONFIG_PATH="/ffmpeg/ffmpeg_build/lib/pkgconfig" && \
|
RUN apk add --no-cache ffmpeg-libs ffmpeg-dev clang16 clang16-libclang pkgconf rust cargo
|
||||||
cargo build --verbose --release
|
RUN cd /build && cargo build --release
|
||||||
|
|
||||||
FROM alpine:3.20
|
FROM alpine:latest
|
||||||
WORKDIR /
|
WORKDIR /
|
||||||
RUN apk add --no-cache \
|
RUN apk add --no-cache ffmpeg-libavutil ffmpeg-libavformat ffmpeg-libavfilter ffmpeg-libavdevice dumb-init mailcap tzdata
|
||||||
ffmpeg-libavutil \
|
|
||||||
ffmpeg-libavformat \
|
|
||||||
ffmpeg-libavfilter \
|
|
||||||
ffmpeg-libavdevice \
|
|
||||||
fdk-aac \
|
|
||||||
dumb-init \
|
|
||||||
mailcap \
|
|
||||||
tzdata \
|
|
||||||
gnutls
|
|
||||||
COPY --from=builder /build/target/release/atranscoder-rpc /usr/local/bin
|
COPY --from=builder /build/target/release/atranscoder-rpc /usr/local/bin
|
||||||
EXPOSE 8090
|
EXPOSE 8090
|
||||||
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/atranscoder-rpc"]
|
ENTRYPOINT ["/usr/bin/dumb-init", "--", "/usr/local/bin/atranscoder-rpc"]
|
||||||
|
75
Dockerfile.scratch
Normal file
75
Dockerfile.scratch
Normal file
@ -0,0 +1,75 @@
|
|||||||
|
# Initially I wanted to build a slim image using this Dockerfile and static linking.
|
||||||
|
# It would use something like this in Cargo.toml:
|
||||||
|
#
|
||||||
|
# [build-dependencies.clang]
|
||||||
|
# version = "2.0.0"
|
||||||
|
# default-features = false
|
||||||
|
# features = ["static"]
|
||||||
|
#
|
||||||
|
# [build-dependencies.clang-sys]
|
||||||
|
# version = "1.7.0"
|
||||||
|
# default-features = false
|
||||||
|
# features = ["clang_16_0", "static"]
|
||||||
|
#
|
||||||
|
# But there are a lot of problems with static linking and clang & clang-sys crates:
|
||||||
|
# - https://github.com/KyleMayes/clang-sys/issues/174
|
||||||
|
# - https://github.com/KyleMayes/clang-rs/issues/17
|
||||||
|
# - https://github.com/KyleMayes/clang-sys/issues/148 (this is the one I *like* the most!)
|
||||||
|
#
|
||||||
|
# So, no static linking for now, but I don't wanna erase all this gorgeous Dockerfile code, so... I'll let it linger
|
||||||
|
# in the repo for now.
|
||||||
|
|
||||||
|
# Stage 1: Build the Rust application
|
||||||
|
FROM rust:1.78-alpine AS builder
|
||||||
|
|
||||||
|
# Set the working directory
|
||||||
|
WORKDIR /usr/src/
|
||||||
|
|
||||||
|
# Install necessary packages
|
||||||
|
RUN apk add --no-cache \
|
||||||
|
ffmpeg-libs \
|
||||||
|
ffmpeg-dev \
|
||||||
|
pkgconf \
|
||||||
|
musl-dev \
|
||||||
|
clang16-static \
|
||||||
|
llvm-dev \
|
||||||
|
zlib-dev \
|
||||||
|
libffi-dev \
|
||||||
|
ncurses-dev \
|
||||||
|
gcc \
|
||||||
|
g++ \
|
||||||
|
git \
|
||||||
|
build-base
|
||||||
|
|
||||||
|
# Add target for musl
|
||||||
|
RUN rustup target add x86_64-unknown-linux-musl
|
||||||
|
|
||||||
|
# Create a new Rust project
|
||||||
|
RUN USER=root cargo new atranscoder-rpc
|
||||||
|
WORKDIR /usr/src/atranscoder-rpc
|
||||||
|
|
||||||
|
# Copy the manifest and lock files
|
||||||
|
COPY Cargo.toml Cargo.lock ./
|
||||||
|
|
||||||
|
# Set the environment variable for libclang path
|
||||||
|
ENV LIBCLANG_PATH=/usr/lib/llvm16/lib
|
||||||
|
ENV PKG_CONFIG_PATH=/usr/lib/pkgconfig
|
||||||
|
|
||||||
|
# Build dependencies to cache them
|
||||||
|
RUN cargo build --release --target x86_64-unknown-linux-musl
|
||||||
|
|
||||||
|
# Copy the source code
|
||||||
|
COPY src ./src
|
||||||
|
|
||||||
|
# Build the project and install the binary
|
||||||
|
RUN cargo install --target x86_64-unknown-linux-musl --path . && \
|
||||||
|
mkdir -p /result/{tmp,bin} && \
|
||||||
|
mv /usr/local/cargo/bin/atranscoder-rpc /result/bin
|
||||||
|
|
||||||
|
# Stage 2: Create the final minimal image
|
||||||
|
FROM scratch
|
||||||
|
COPY --from=builder /usr/bin/dumb-init /bin/
|
||||||
|
COPY --from=builder /result/bin /bin
|
||||||
|
COPY --from=builder /result/tmp /tmp
|
||||||
|
EXPOSE 8090
|
||||||
|
ENTRYPOINT ["/bin/dumb-init", "--", "/bin/atranscoder-rpc"]
|
@ -8,7 +8,7 @@ Audio transcoder with simple HTTP API. Work in progress.
|
|||||||
# How to Use
|
# How to Use
|
||||||
|
|
||||||
Transcoding can be done like this:
|
Transcoding can be done like this:
|
||||||
1. Use [`neur0toxine/atranscoder-rpc`](https://hub.docker.com/r/neur0toxine/atranscoder-rpc/) Docker image.
|
1. Use `cargo run` or [`neur0toxine/atranscoder-rpc`](https://hub.docker.com/r/neur0toxine/atranscoder-rpc/) Docker image.
|
||||||
2. Upload file for transcoding:
|
2. Upload file for transcoding:
|
||||||
```bash
|
```bash
|
||||||
curl --location 'http://localhost:8090/enqueue' \
|
curl --location 'http://localhost:8090/enqueue' \
|
||||||
|
@ -95,7 +95,6 @@ impl Task {
|
|||||||
&mut octx,
|
&mut octx,
|
||||||
TranscoderParams {
|
TranscoderParams {
|
||||||
codec: self.params.codec,
|
codec: self.params.codec,
|
||||||
codec_opts: self.params.codec_opts,
|
|
||||||
bit_rate: self.params.bit_rate,
|
bit_rate: self.params.bit_rate,
|
||||||
max_bit_rate: self.params.max_bit_rate,
|
max_bit_rate: self.params.max_bit_rate,
|
||||||
sample_rate: self.params.sample_rate,
|
sample_rate: self.params.sample_rate,
|
||||||
@ -249,10 +248,10 @@ fn upload_file<P: AsRef<Path>>(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn params_to_avdictionary(input: &str) -> Dictionary {
|
fn params_to_avdictionary(input: &str) -> Dictionary {
|
||||||
let mut dict: Dictionary = Dictionary::new();
|
let mut dict: Dictionary = Dictionary::new();
|
||||||
for pair in input.split(';') {
|
for pair in input.split(';') {
|
||||||
let mut parts = pair.split('=');
|
let mut parts = pair.split(':');
|
||||||
|
|
||||||
if let (Some(key), Some(value)) = (parts.next(), parts.next()) {
|
if let (Some(key), Some(value)) = (parts.next(), parts.next()) {
|
||||||
dict.set(key, value);
|
dict.set(key, value);
|
||||||
|
@ -43,14 +43,7 @@ impl Worker {
|
|||||||
let thread = thread::spawn(move || {
|
let thread = thread::spawn(move || {
|
||||||
ffmpeg_next::init()
|
ffmpeg_next::init()
|
||||||
.unwrap_or_else(|err| tracing::error!("couldn't init FFmpeg: {:?}", err));
|
.unwrap_or_else(|err| tracing::error!("couldn't init FFmpeg: {:?}", err));
|
||||||
|
ffmpeg_next::util::log::set_level(Level::Quiet);
|
||||||
ffmpeg_next::util::log::set_level(
|
|
||||||
if std::env::var("FFMPEG_VERBOSE").unwrap_or_default() == "1" {
|
|
||||||
Level::Trace
|
|
||||||
} else {
|
|
||||||
Level::Quiet
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
let task = {
|
let task = {
|
||||||
|
@ -1,14 +1,9 @@
|
|||||||
extern crate ffmpeg_next as ffmpeg;
|
extern crate ffmpeg_next as ffmpeg;
|
||||||
|
|
||||||
use std::any::Any;
|
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
|
|
||||||
use crate::task::params_to_avdictionary;
|
|
||||||
use ffmpeg::{codec, filter, format, frame, media};
|
use ffmpeg::{codec, filter, format, frame, media};
|
||||||
use ffmpeg_next::codec::Parameters;
|
|
||||||
use ffmpeg_next::error::EAGAIN;
|
use ffmpeg_next::error::EAGAIN;
|
||||||
use ffmpeg_next::Dictionary;
|
|
||||||
use tracing::log::debug;
|
|
||||||
|
|
||||||
pub struct Transcoder {
|
pub struct Transcoder {
|
||||||
pub(crate) stream: usize,
|
pub(crate) stream: usize,
|
||||||
@ -21,7 +16,6 @@ pub struct Transcoder {
|
|||||||
|
|
||||||
pub struct TranscoderParams {
|
pub struct TranscoderParams {
|
||||||
pub codec: String,
|
pub codec: String,
|
||||||
pub codec_opts: Option<String>,
|
|
||||||
pub bit_rate: usize,
|
pub bit_rate: usize,
|
||||||
pub max_bit_rate: usize,
|
pub max_bit_rate: usize,
|
||||||
pub sample_rate: i32,
|
pub sample_rate: i32,
|
||||||
@ -73,6 +67,9 @@ impl Transcoder {
|
|||||||
encoder.set_rate(sample_rate);
|
encoder.set_rate(sample_rate);
|
||||||
encoder.set_channel_layout(params.channel_layout);
|
encoder.set_channel_layout(params.channel_layout);
|
||||||
|
|
||||||
|
#[cfg(not(feature = "ffmpeg_7_0"))]
|
||||||
|
encoder.set_channels(params.channel_layout.channels());
|
||||||
|
|
||||||
encoder.set_format(
|
encoder.set_format(
|
||||||
codec
|
codec
|
||||||
.formats()
|
.formats()
|
||||||
@ -100,11 +97,7 @@ impl Transcoder {
|
|||||||
output.set_time_base((1, sample_rate));
|
output.set_time_base((1, sample_rate));
|
||||||
|
|
||||||
let in_time_base = decoder.time_base();
|
let in_time_base = decoder.time_base();
|
||||||
let encoder = if let Some(codec_opts) = params.codec_opts {
|
let encoder = encoder.open_as(codec)?;
|
||||||
encoder.open_as_with(codec, params_to_avdictionary(codec_opts.as_str()))?
|
|
||||||
} else {
|
|
||||||
encoder.open_as(codec)?
|
|
||||||
};
|
|
||||||
output.set_parameters(&encoder);
|
output.set_parameters(&encoder);
|
||||||
|
|
||||||
let filter = filter_graph("anull", &decoder, &encoder)?;
|
let filter = filter_graph("anull", &decoder, &encoder)?;
|
||||||
|
Loading…
Reference in New Issue
Block a user