Введение
FFmpeg — это мощный инструмент для работы с мультимедиа, который используют для кодирования, декодирования, перекодирования и применения фильтров к видео и аудио. Но если вы работаете с Rust, интеграция с C API FFmpeg может стать настоящей головной болью: управление памятью, проблемы безопасности и крутая кривая обучения. Особенно сложно реализовать пользовательские фильтры — для этого обычно нужно писать код на C и разбираться во внутренностях FFmpeg. А что, если я скажу, что с Rust и библиотекой ez-ffmpeg вы можете забыть про эти трудности и писать фильтры прямо на любимом языке?
В этой статье мы разберём, как использовать Rust и ez-ffmpeg для создания собственных видеофильтров. Мы начнём с основ, дойдём до продвинутых решений и покажем, как это может пригодиться именно вам. Готовы упростить свою жизнь? Тогда поехали!
Почему это сложно и где пригодится?
Проблемы старого подхода
Сложность: C API FFmpeg заставляет вас вручную управлять памятью. Один неверный шаг — и привет, утечки или краш программы!
Безопасность: В Rust для работы с C нужно использовать FFI и unsafe-блоки. Это как играть с огнём — ошибки дорого обходятся.
Высокий порог входа: Чтобы сделать свой фильтр, нужно знать, как FFmpeg устроен внутри. Не каждый готов копаться в документации и коде на C.
Где это нужно?
Видео в реальном времени: Добавляйте эффекты вроде яркости или серого тона прямо во время стрима.
Машинное обучение: Преобразуйте видео для создания данных для нейросетей.
Игры: Делайте крутые визуальные эффекты для видеоконтента.
Аудио: Настраивайте громкость или добавляйте звуковые эффекты.
Системы наблюдения: Анализируйте видео для обнаружения движения или объектов.
Если вы хотите надёжное и простое решение, ez-ffmpeg и Rust — это то, что вам нужно.
Основа: Фильтр яркости для YUV420
Давайте начнём с простого — создадим фильтр, который регулирует яркость видео в формате YUV420 (его использует большинство видео). Это отличный способ понять, как всё работает.
Настраиваем проект
Добавьте в Cargo.toml
:
[dependencies]
ez-ffmpeg = "*"
Убедитесь, что у вас установлены FFmpeg 7.0+ и Rust 1.80.0+.
Пишем код
Этот фильтр увеличит яркость, изменяя Y-компоненту:
use ez_ffmpeg::core::filter::frame_filter::FrameFilter;
use ez_ffmpeg::core::frame::Frame;
use ez_ffmpeg::core::filter::frame_filter::FrameFilterContext;
use ffmpeg_sys_next::AVMediaType;
struct BrightnessFilter {
increment: i32, // На сколько увеличиваем яркость
}
impl FrameFilter for BrightnessFilter {
fn media_type(&self) -> AVMediaType {
AVMediaType::AVMEDIA_TYPE_VIDEO
}
fn filter_frame(&self, mut frame: Frame, _ctx: &FrameFilterContext) -> Result<Option<Frame>, String> {
if frame.format() != ffmpeg_sys_next::AVPixelFormat::AV_PIX_FMT_YUV420P {
return Err("Формат пикселей не поддерживается".to_string());
}
let data = frame.get_data_mut(0).ok_or("Не удалось получить данные кадра")?;
for y in data.iter_mut() {
*y = (*y as i32 + self.increment).clamp(0, 255) as u8; // Регулируем Y, не выходя за пределы
}
Ok(Some(frame))
}
}
Применяем фильтр
Пример полной программы:
uuse ez_ffmpeg::{FfmpegContext, Output};
fn main() -> Result<(), Box<dyn std::error::Error>> {
let brightness = BrightnessFilter { increment: 50 };
FfmpegContext::builder()
.input("input.mp4")
.filter(Box::new(brightness))
.output(Output::from("output.mp4"))
.build()?
.start()?
.wait()?;
Ok(())
}
Видео станет ярче — и всё это без единой строчки C!
Продвинутый уровень: Фильтры на GPU
Простые фильтры на CPU — это круто, но что делать, если нужно обрабатывать видео в реальном времени? Тут на помощь приходит GPU и OpenGL в ez-ffmpeg.
Проблемы
Скорость: CPU может не справляться с большими потоками данных.
Совместимость: Разные видеокарты по-разному поддерживают OpenGL.
Решаем с помощью GPU: Серый фильтр
Добавим поддержку OpenGL в Cargo.toml
:
[dependencies]
ez-ffmpeg = { version = "*", features = ["opengl"] }
Шейдер для серого тона:
#version 330 core
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D texture1;
void main() {
vec4 color = texture(texture1, TexCoord);
float gray = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b;
FragColor = vec4(gray, gray, gray, color.a);
}
Применяем в Rust:
let fragment_shader = r#"
#version 330 core
in vec2 TexCoord;
out vec4 FragColor;
uniform sampler2D texture1;
void main() {
vec4 color = texture(texture1, TexCoord);
float gray = 0.299 * color.r + 0.587 * color.g + 0.114 * color.b;
FragColor = vec4(gray, gray, gray, color.a);
}
"#;
let filter = OpenGLFrameFilter::new_simple(fragment_shader);
frame_pipeline_builder.filter("opengl", Box::new(filter));
Теперь ваше видео станет чёрно-белым, а обработка пойдёт на GPU — быстро и эффективно!
Что мы получили и что дальше?
С Rust и ez-ffmpeg вы можете легко создавать фильтры для FFmpeg, не мучаясь с C. От простых эффектов на CPU до мощных решений на GPU — всё в ваших руках. Это идеально для стримов, анализа данных или просто экспериментов с видео.
Хотите больше? Загляните в ez-ffmpeg на GitHub — там куча примеров и идей. Пора сделать ваши проекты ещё круче!