<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Yeauty YE</title>
    <description>The latest articles on DEV Community by Yeauty YE (@yeauty).</description>
    <link>https://dev.to/yeauty</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2932171%2Fe3eedc22-29d9-4208-a808-b30b6d3116b7.png</url>
      <title>DEV Community: Yeauty YE</title>
      <link>https://dev.to/yeauty</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yeauty"/>
    <language>en</language>
    <item>
      <title>🚀 Double Your Performance with One Line of Code? The Memory Superpower Every Rust Developer Should Know!</title>
      <dc:creator>Yeauty YE</dc:creator>
      <pubDate>Wed, 02 Jul 2025 11:42:11 +0000</pubDate>
      <link>https://dev.to/yeauty/double-your-performance-with-one-line-of-code-the-memory-superpower-every-rust-developer-should-1g93</link>
      <guid>https://dev.to/yeauty/double-your-performance-with-one-line-of-code-the-memory-superpower-every-rust-developer-should-1g93</guid>
      <description>&lt;p&gt;In the world of high-performance Rust programming, you often hear about &lt;em&gt;hardcore&lt;/em&gt; optimization techniques: asynchronous magic with Tokio, blazing-fast SIMD instructions, lock-free concurrency, and more.&lt;/p&gt;

&lt;p&gt;Yet there’s one &lt;strong&gt;often-overlooked tool&lt;/strong&gt; lurking in your stack that can deliver a massive, sometimes &lt;em&gt;game-changing&lt;/em&gt; performance boost with &lt;em&gt;minimal&lt;/em&gt; effort:&lt;/p&gt;

&lt;p&gt;👉 &lt;strong&gt;The Memory Allocator.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Yes, really—by simply swapping out Rust’s default allocator, your application can achieve &lt;strong&gt;multi-fold throughput improvements&lt;/strong&gt; and &lt;strong&gt;significantly lower latency&lt;/strong&gt; in high-concurrency or large-data workloads. This isn’t hype—it’s backed by serious benchmarks:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;Authoritative Benchmark Highlights&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://www.microsoft.com/en-us/research/uploads/prod/2019/06/mimalloc-tr-v1.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;Microsoft mimalloc report&lt;/strong&gt;&lt;/a&gt;: Under heavy multithreaded workloads on Linux, mimalloc delivered &lt;strong&gt;5.3× faster average performance&lt;/strong&gt; compared to glibc malloc, while cutting &lt;strong&gt;RSS memory usage by ~50%&lt;/strong&gt;. More performance, less cost.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;a href="https://github.com/tpn/pdfs/blob/master/A%20Scalable%20Concurrent%20malloc%20Implementation%20for%20FreeBSD%20%28jemalloc%29.pdf" rel="noopener noreferrer"&gt;&lt;strong&gt;jemalloc research paper&lt;/strong&gt;&lt;/a&gt;: In real-world tests on a 4-core server, glibc malloc achieved only &lt;strong&gt;15% of jemalloc’s throughput&lt;/strong&gt;—a night-and-day difference for latency-sensitive services.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;In this post, you’ll discover &lt;strong&gt;why allocators matter so much&lt;/strong&gt;, what makes modern allocators radically faster, and how you can unlock their benefits with &lt;strong&gt;literally one line of code&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  🧠 1. Memory Allocators: Your Program’s &lt;em&gt;Invisible Power Broker&lt;/em&gt;
&lt;/h2&gt;

&lt;p&gt;Whenever you write something like &lt;code&gt;Vec::with_capacity(100)&lt;/code&gt;, you’re calling the allocator: the engine that manages heap memory behind the scenes.&lt;/p&gt;

&lt;p&gt;Rust’s default allocator is usually the system allocator—e.g., glibc malloc on Linux. It’s reliable and general-purpose, but under concurrency, it can quickly become a bottleneck.&lt;/p&gt;




&lt;h3&gt;
  
  
  ❌ The Problem with Traditional Allocators: &lt;em&gt;Global Lock Contention&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Under high concurrency, all threads compete for &lt;strong&gt;a single global lock&lt;/strong&gt; to allocate or free memory. It’s like the entire country trying to buy train tickets from &lt;em&gt;one window&lt;/em&gt; during the holidays:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;      +-------------------------------------------+
      |      Traditional Allocator (glibc malloc) |
      |          One Big Global Lock 🔒           |
      +-------------------------------------------+
          ^          ^          ^          ^
          |          |          |          |
      [Thread1]  [Thread2]   [Thread3]   [Thread4]
      (waiting)  (waiting)   (holding)   (waiting)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Result: threads pile up, CPUs spend more time context switching than doing real work, and throughput plummets.&lt;/p&gt;




&lt;h3&gt;
  
  
  ✅ Modern Allocators to the Rescue: &lt;em&gt;Thread-Local Caches&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;Allocators like &lt;code&gt;jemalloc&lt;/code&gt; and &lt;code&gt;mimalloc&lt;/code&gt; assign each thread its own fast, lock-free cache:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+------------------+ +------------------+ +------------------+
| Thread 1 Cache   | | Thread 2 Cache   | | Thread 3 Cache   |
| (No locks here!) | | (No locks here!) | | (No locks here!) |
+------------------+ +------------------+ +------------------+
        |                  |                  |
        +------------------+------------------+
                           |
                           v
             +-----------------------------+
             |    Global Memory Pool       |
             |   (accessed infrequently)   |
             +-----------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Most allocations happen &lt;strong&gt;without any locking&lt;/strong&gt;, so threads can operate at full speed. Only when the local cache runs out does it fetch more memory from the global pool.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔍 2. Why Does Swapping Allocators Make You So Much Faster?
&lt;/h2&gt;

&lt;p&gt;Let’s break down the core reasons:&lt;/p&gt;




&lt;h3&gt;
  
  
  🔒 2.1 Escaping the &lt;em&gt;Global Lock Hell&lt;/em&gt;
&lt;/h3&gt;

&lt;p&gt;This is the biggest win. With thread-local caches, modern allocators eliminate lock contention, unleashing the full power of multi-core CPUs.&lt;/p&gt;

&lt;p&gt;In languages like Rust or Go that thrive on concurrency, this difference is especially dramatic.&lt;/p&gt;




&lt;h3&gt;
  
  
  🧩 2.2 Fighting Memory Fragmentation
&lt;/h3&gt;

&lt;p&gt;Frequent allocations and deallocations can leave memory full of tiny gaps:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Memory State: | Used | Free(1) | Used | Free(2) | Used |
              +------+--------+------+--------+------+

New Request: "I need 3 contiguous blocks..."

Result: Even though total free space &amp;gt;3, allocation fails—classic fragmentation.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Modern allocators prevent this by using &lt;strong&gt;binning&lt;/strong&gt;: pre-categorizing memory into size classes (e.g., 8B, 16B, 32B) and reusing those buckets.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;+------------------------------------------------------+
|        Modern Allocator Memory Pools (Size Classes)  |
+------------------------------------------------------+
| [8B Bin][16B Bin][32B Bin][64B Bin][...more bins...] |
+------------------------------------------------------+
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This not only reduces fragmentation but also improves cache locality and speeds up memory access.&lt;/p&gt;




&lt;h3&gt;
  
  
  ⚡ 2.3 Optimizing Large Allocations
&lt;/h3&gt;

&lt;p&gt;Traditional allocators often call the kernel (&lt;code&gt;mmap&lt;/code&gt;) every time you need a large chunk of memory—an expensive syscall.&lt;/p&gt;

&lt;p&gt;Modern allocators instead &lt;strong&gt;reserve large arenas up front&lt;/strong&gt; and manage them in user space, reducing system call overhead.&lt;/p&gt;




&lt;h2&gt;
  
  
  🔧 3. Rust Made It Simple: One Line to Swap Your Allocator
&lt;/h2&gt;

&lt;p&gt;Using a faster allocator in Rust is ridiculously easy. For example, to enable &lt;code&gt;mimalloc&lt;/code&gt;:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add it to &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;mimalloc&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Declare the global allocator in your &lt;code&gt;main.rs&lt;/code&gt;:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nd"&gt;#[global_allocator]&lt;/span&gt;
&lt;span class="k"&gt;static&lt;/span&gt; &lt;span class="n"&gt;GLOBAL&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nn"&gt;mimalloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MiMalloc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;mimalloc&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;MiMalloc&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// No other code changes needed!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That’s it. Build and run—your program is now supercharged.&lt;/p&gt;

&lt;p&gt;⚠️ &lt;em&gt;Note&lt;/em&gt;: You can only have one global allocator per binary. But what if you need to support different allocators per platform without messy &lt;code&gt;#[cfg]&lt;/code&gt; flags everywhere? There’s a better way.&lt;/p&gt;




&lt;h2&gt;
  
  
  ✨ 4. The Ultimate Solution: &lt;code&gt;auto-allocator&lt;/code&gt;—No More Conditional Compilation Hell
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/YeautyYE/auto-allocator" rel="noopener noreferrer"&gt;&lt;code&gt;auto-allocator&lt;/code&gt;&lt;/a&gt; is a smart Rust library that &lt;strong&gt;auto-detects your target platform&lt;/strong&gt; and picks the best allocator automatically. Whether you’re building high-concurrency servers, mobile apps, WebAssembly frontends, or embedded devices, it just works.&lt;/p&gt;

&lt;p&gt;🌍 &lt;strong&gt;Platform-Aware Optimizations:&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Linux/Windows/macOS&lt;/strong&gt;: Enables &lt;code&gt;mimalloc&lt;/code&gt; for up to 6× throughput improvements.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;iOS&lt;/strong&gt;: Uses Apple’s optimized &lt;code&gt;libmalloc&lt;/code&gt; for stability and performance.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Android&lt;/strong&gt;: Switches to &lt;code&gt;scudo&lt;/code&gt; for efficient and secure allocation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;WebAssembly&lt;/strong&gt;: Retains the default allocator for maximum compatibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Embedded (&lt;code&gt;no_std&lt;/code&gt;)&lt;/strong&gt;: Selects &lt;code&gt;embedded-alloc&lt;/code&gt; for resource-constrained environments.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;How It Works&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;Auto-Allocator uses a &lt;em&gt;two-stage optimization pipeline&lt;/em&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;🛠️ Compile Time                     ⚡ Runtime                    ✅ Final Result
┌────────────────────────┐          ┌───────────────────────┐     ┌─────────────────────────┐
│ Platform Detection.    │          │ CPU Core Analysis     │     │                         │
│                        │─────────▶│                       │     │                         │
│ Feature Analysis       │          │ Memory Detection      │────▶│ Best Allocator Selected │
│                        │─────────▶│                       │     │                         │
│ Compiler Capabilities  │          │ Hardware Optimization │     │                         │
└────────────────────────┘          └───────────────────────┘     └─────────────────────────┘
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✅ &lt;em&gt;90% of decisions happen at compile time—no runtime overhead.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;&lt;strong&gt;Usage:&lt;/strong&gt;&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Add it to your &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;auto-allocator&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Import in &lt;code&gt;main.rs&lt;/code&gt;:&lt;/strong&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="n"&gt;auto_allocator&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;auto_allocator&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;get_allocator_info&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Using allocator: {:?} | Reason: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="py"&gt;.allocator_type&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;info&lt;/span&gt;&lt;span class="py"&gt;.reason&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;Vec&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;..&lt;/span&gt;&lt;span class="mi"&gt;1_000_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.collect&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="s"&gt;"Created Vec with {} elements—allocation optimized automatically!"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;✨ That’s it. One &lt;code&gt;use&lt;/code&gt; statement—done.&lt;/p&gt;

&lt;p&gt;For additional security (e.g., guard pages, canary checks), enable the secure feature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;auto-allocator&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"secure"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  🏁 5. Wrapping Up: Time for a &lt;em&gt;Free&lt;/em&gt; Performance Upgrade
&lt;/h2&gt;

&lt;p&gt;By swapping your memory allocator, you can unlock:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;🚀 &lt;strong&gt;Higher throughput&lt;/strong&gt;: Handle more traffic on the same hardware.&lt;/li&gt;
&lt;li&gt;💰 &lt;strong&gt;Lower latency and costs&lt;/strong&gt;: Faster response times and reduced memory footprint.&lt;/li&gt;
&lt;li&gt;🧩 &lt;strong&gt;Better stability&lt;/strong&gt;: Less fragmentation over long-running workloads.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you care about performance, this is one of the &lt;em&gt;highest ROI optimizations you’ll ever make.&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;👇 Give it a try—add &lt;code&gt;auto-allocator&lt;/code&gt; to your &lt;code&gt;Cargo.toml&lt;/code&gt; today and see the results yourself!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/YeautyYE/auto-allocator" rel="noopener noreferrer"&gt;👉 GitHub Repository – auto-allocator&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>memory</category>
      <category>allocator</category>
      <category>mimalloc</category>
    </item>
    <item>
      <title>Implementing FFmpeg Filters with Rust: A New Approach to Video and Audio Processing</title>
      <dc:creator>Yeauty YE</dc:creator>
      <pubDate>Wed, 09 Apr 2025 12:11:51 +0000</pubDate>
      <link>https://dev.to/yeauty/implementing-ffmpeg-filters-with-rust-a-new-approach-to-video-and-audio-processing-1hk4</link>
      <guid>https://dev.to/yeauty/implementing-ffmpeg-filters-with-rust-a-new-approach-to-video-and-audio-processing-1hk4</guid>
      <description>&lt;p&gt;Hey there, fellow developers! If you’ve ever wrestled with FFmpeg’s C API in Rust—or shuddered at the thought of memory leaks and &lt;code&gt;unsafe&lt;/code&gt; blocks—this one’s for you. Today, we’re diving into &lt;code&gt;ez-ffmpeg&lt;/code&gt;, a Rust library that makes implementing custom video and audio filters a breeze. Think safety, simplicity, and yes, even GPU acceleration—all wrapped in Rust’s ergonomic goodness. Ready to level up your multimedia game? Let’s get started.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why This Matters: The Pain of Traditional FFmpeg
&lt;/h2&gt;

&lt;p&gt;FFmpeg is a powerhouse for multimedia processing—encoding, decoding, filtering, you name it. But using its C API directly in Rust? That’s a different story:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Complexity Overload&lt;/strong&gt;: Manual memory management can feel like defusing a bomb—one wrong move, and boom, leaks or crashes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety Risks&lt;/strong&gt;: Foreign Function Interface (FFI) means &lt;code&gt;unsafe&lt;/code&gt; blocks, inviting bugs that Rust usually shields us from.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steep Learning Curve&lt;/strong&gt;: Custom filters demand deep FFmpeg knowledge—filter graphs, frame handling—not exactly beginner-friendly.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Enter &lt;code&gt;ez-ffmpeg&lt;/code&gt;. It’s like a friendly guide that takes you from “FFmpeg newbie” to “filter pro” without the headaches. Whether you’re tweaking live streams, augmenting ML datasets, or spicing up game visuals, this library’s got your back.&lt;/p&gt;

&lt;h2&gt;
  
  
  What You’ll Learn
&lt;/h2&gt;

&lt;p&gt;We’ll walk through three killer examples:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Brighten Up&lt;/strong&gt;: A CPU-based brightness filter for YUV420 video.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Go Gray&lt;/strong&gt;: A GPU-accelerated grayscale filter with OpenGL.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Turn It Down&lt;/strong&gt;: An audio volume adjustment filter.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Plus, we’ll explore real-world use cases and why &lt;code&gt;ez-ffmpeg&lt;/code&gt; is a game-changer. Let’s dive in!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting Started: Setup
&lt;/h2&gt;

&lt;p&gt;First, add &lt;code&gt;ez-ffmpeg&lt;/code&gt; to your &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;ez-ffmpeg&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;For GPU fun later, enable the &lt;code&gt;opengl&lt;/code&gt; feature:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="py"&gt;ez-ffmpeg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"opengl"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You’ll need FFmpeg 7.0+ and Rust 1.80.0+ installed. Got that? Great—let’s code.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example 1: Brighten Your Video (YUV420)
&lt;/h2&gt;

&lt;p&gt;Most videos use YUV420, so let’s start with a brightness filter that tweaks the Y (luminance) component.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Code
&lt;/h3&gt;

&lt;p&gt;Here’s how we define the filter:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;frame_filter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FrameFilter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Frame&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;frame_filter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FrameFilterContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ffmpeg_sys_next&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;AVMediaType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AVPixelFormat&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;BrightnessFilter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;FrameFilter&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;BrightnessFilter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;media_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AVMediaType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;AVMediaType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AVMEDIA_TYPE_VIDEO&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;filter_frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Frame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;FrameFilterContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Frame&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="nf"&gt;.format&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nn"&gt;AVPixelFormat&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AV_PIX_FMT_YUV420P&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unsupported pixel format"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;y_data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="nf"&gt;.get_data_mut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.ok_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to get Y plane"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;y_data&lt;/span&gt;&lt;span class="nf"&gt;.iter_mut&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;new_y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i32&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.increment&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;255&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;u8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_y&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And here’s how to run it:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FramePipelineBuilder&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ffmpeg_sys_next&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AVMediaType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;frame_pipeline_builder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FramePipelineBuilder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;AVMediaType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AVMEDIA_TYPE_VIDEO&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;brightness_filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;BrightnessFilter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;increment&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;20&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;frame_pipeline_builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frame_pipeline_builder&lt;/span&gt;&lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"brightness"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;brightness_filter&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.add_frame_pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame_pipeline_builder&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  What’s Happening?
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Filter Logic&lt;/strong&gt;: We grab the Y plane, bump each value by 20, and clamp it between 0-255.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pipeline&lt;/strong&gt;: We plug the filter into a video processing pipeline, transforming &lt;code&gt;input.mp4&lt;/code&gt; into a brighter &lt;code&gt;output.mp4&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Run it, and bam—your video’s glowing!&lt;/p&gt;

&lt;h2&gt;
  
  
  Example 2: Grayscale with GPU Power (OpenGL)
&lt;/h2&gt;

&lt;p&gt;For real-time magic, let’s use the GPU. This grayscale filter leverages OpenGL for speed.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Shader
&lt;/h3&gt;

&lt;p&gt;Here’s the fragment shader:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="cp"&gt;#version 330 core
&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;TexCoord&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;vec4&lt;/span&gt; &lt;span class="n"&gt;FragColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;uniform&lt;/span&gt; &lt;span class="kt"&gt;sampler2D&lt;/span&gt; &lt;span class="n"&gt;texture1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;vec4&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texture1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TexCoord&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;gray&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;299&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;587&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;114&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;FragColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;vec4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;gray&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;a&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  The Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FramePipelineBuilder&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;opengl&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OpenGLFrameFilter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ffmpeg_sys_next&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AVMediaType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;fragment_shader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;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);
    }"#&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;OpenGLFrameFilter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new_simple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fragment_shader&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;frame_pipeline_builder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FramePipelineBuilder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;AVMediaType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AVMEDIA_TYPE_VIDEO&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;frame_pipeline_builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frame_pipeline_builder&lt;/span&gt;&lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"opengl"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.add_frame_pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame_pipeline_builder&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Why It Rocks
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Speed&lt;/strong&gt;: GPU acceleration handles big frames fast—perfect for live streams.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt;: No fiddly CPU loops; the shader does the heavy lifting.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Your video’s now a stylish black-and-white masterpiece.&lt;/p&gt;

&lt;h2&gt;
  
  
  Example 3: Lower the Volume (Audio)
&lt;/h2&gt;

&lt;p&gt;Let’s switch gears to audio with a volume adjustment filter.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Code
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;frame_filter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FrameFilter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Frame&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;core&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;frame_filter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FrameFilterContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ffmpeg_sys_next&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;AVMediaType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AVSampleFormat&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;VolumeFilter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;gain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nb"&gt;f32&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;impl&lt;/span&gt; &lt;span class="n"&gt;FrameFilter&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;VolumeFilter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;media_type&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;AVMediaType&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nn"&gt;AVMediaType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AVMEDIA_TYPE_AUDIO&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;filter_frame&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Frame&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_ctx&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;FrameFilterContext&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nb"&gt;Option&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Frame&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nb"&gt;String&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="nf"&gt;.format&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="nn"&gt;AVSampleFormat&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AV_SAMPLE_FMT_S16&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Unsupported sample format"&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="nf"&gt;.get_data_mut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.ok_or&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Failed to get audio data"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;samples&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;unsafe&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;slice&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from_raw_parts_mut&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="nf"&gt;.as_mut_ptr&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="nb"&gt;i16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="nf"&gt;.len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;/&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;sample&lt;/span&gt; &lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="n"&gt;samples&lt;/span&gt;&lt;span class="nf"&gt;.iter_mut&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;new_sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;f32&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;self&lt;/span&gt;&lt;span class="py"&gt;.gain&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.clamp&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="mf"&gt;32768.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mf"&gt;32767.0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;as&lt;/span&gt; &lt;span class="nb"&gt;i16&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
            &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;sample&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;new_sample&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nf"&gt;Some&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FramePipelineBuilder&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ffmpeg_sys_next&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AVMediaType&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;frame_pipeline_builder&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FramePipelineBuilder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;AVMediaType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AVMEDIA_TYPE_AUDIO&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;volume_filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;VolumeFilter&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;gain&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;0.5&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;frame_pipeline_builder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frame_pipeline_builder&lt;/span&gt;&lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"volume"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;volume_filter&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.add_frame_pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame_pipeline_builder&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  How It Works
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Gain Factor&lt;/strong&gt;: &lt;code&gt;gain: 0.5&lt;/code&gt; halves the volume (range: -32768 to 32767).&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety&lt;/strong&gt;: Rust keeps us crash-free while tweaking samples.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Now your audio’s perfectly chilled.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where This Shines: Use Cases
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Live Streaming&lt;/strong&gt;: Add effects like brightness or grayscale in real time.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Machine Learning&lt;/strong&gt;: Transform video frames for data augmentation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Gaming&lt;/strong&gt;: Dynamic video effects for immersive experiences.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Audio Tweaks&lt;/strong&gt;: Fine-tune sound for podcasts or videos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Surveillance&lt;/strong&gt;: Process feeds for motion detection.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;With &lt;code&gt;ez-ffmpeg&lt;/code&gt;, you skip FFmpeg’s filter graph maze and get straight to the fun stuff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why &lt;code&gt;ez-ffmpeg&lt;/code&gt; Wins
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Safety First&lt;/strong&gt;: Rust’s guarantees mean no memory woes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Use&lt;/strong&gt;: Ergonomic APIs lower the entry barrier.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: CPU or GPU, pick your speed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt;: Video, audio, real-time—handle it all.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What’s Next?
&lt;/h2&gt;

&lt;p&gt;This is just the start. Explore &lt;code&gt;ez-ffmpeg&lt;/code&gt;’s hardware encoding, streaming, or metadata tools. Check out the &lt;a href="https://github.com/YeautyYE/ez-ffmpeg" rel="noopener noreferrer"&gt;GitHub repo&lt;/a&gt; for more examples and docs.&lt;/p&gt;

&lt;p&gt;So, what do you think? Ready to ditch the C API and go Rust? Drop a comment—I’d love to hear your ideas or projects!&lt;/p&gt;

&lt;p&gt;Happy coding!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ffmpeg</category>
    </item>
    <item>
      <title>How to Easily Implement RTMP Live Streaming in Rust: A Practical Guide</title>
      <dc:creator>Yeauty YE</dc:creator>
      <pubDate>Fri, 04 Apr 2025 08:06:00 +0000</pubDate>
      <link>https://dev.to/yeauty/how-to-easily-implement-rtmp-live-streaming-in-rust-a-practical-guide-4ed1</link>
      <guid>https://dev.to/yeauty/how-to-easily-implement-rtmp-live-streaming-in-rust-a-practical-guide-4ed1</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;With the rapid growth of live streaming, RTMP (Real-Time Messaging Protocol) has become a standard choice for broadcasting real-time media content. However, directly working with low-level APIs to implement RTMP streaming can be complex, error-prone, and may introduce memory safety issues, posing significant challenges for developers.&lt;/p&gt;

&lt;p&gt;This article explores how you can leverage Rust’s safety, efficiency, and developer-friendly features to simplify RTMP live streaming. We'll discuss common streaming scenarios, technical challenges, and provide practical solutions with ready-to-use examples.&lt;/p&gt;

&lt;h2&gt;
  
  
  Why Use Rust for RTMP Streaming?
&lt;/h2&gt;

&lt;p&gt;Common pain points when implementing RTMP streaming include:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Complex low-level APIs with a steep learning curve.&lt;/li&gt;
&lt;li&gt;Memory management and safety risks when directly interfacing with FFmpeg APIs.&lt;/li&gt;
&lt;li&gt;High demands for real-time performance and stability.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Rust, by its very design, addresses these challenges effectively:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Offers zero-cost abstractions and built-in memory safety.&lt;/li&gt;
&lt;li&gt;Performance comparable to C/C++ with a significantly improved developer experience.&lt;/li&gt;
&lt;li&gt;Rich ecosystem and seamless integration with existing C/C++ libraries.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Thus, Rust is an excellent choice for developing robust and efficient RTMP streaming applications.&lt;/p&gt;

&lt;h2&gt;
  
  
  Common RTMP Streaming Scenarios
&lt;/h2&gt;

&lt;p&gt;Based on real-world requirements, RTMP streaming usually falls into two scenarios:&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Streaming to Public Platforms
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Case:&lt;/strong&gt; Platforms like Twitch, YouTube, or Facebook Live for large audience broadcasts.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Requirements:&lt;/strong&gt; Stability, low latency, ease of use.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  2. Local or Internal Streaming
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Use Case:&lt;/strong&gt; Suitable for internal live streams, testing, development, or LAN video monitoring.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Key Requirements:&lt;/strong&gt; Easy deployment, flexibility, quick setup, and convenient debugging.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Solution: Rust with ez-ffmpeg
&lt;/h2&gt;

&lt;p&gt;To address these challenges and requirements, we introduce &lt;code&gt;ez-ffmpeg&lt;/code&gt;, a Rust library providing a clean abstraction over FFmpeg, significantly simplifying RTMP streaming through user-friendly interfaces and automatic memory management.&lt;/p&gt;

&lt;h3&gt;
  
  
  Technical Highlights:
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;FFI Bindings:&lt;/strong&gt; Safe and efficient interfacing with native FFmpeg APIs.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Automatic Memory Management:&lt;/strong&gt; Eliminates manual memory handling, enhancing safety and productivity.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Ergonomic Design:&lt;/strong&gt; Chainable method calls, improving developer experience.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Quick Start Examples
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Environment Setup
&lt;/h3&gt;

&lt;h4&gt;
  
  
  Install FFmpeg
&lt;/h4&gt;

&lt;ul&gt;
&lt;li&gt;macOS:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;Windows:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vcpkg &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Rust Dependency
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;ez-ffmpeg&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="py"&gt;version&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="py"&gt;features&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"rtmp"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scenario 1: Stream to Public RTMP Servers
&lt;/h3&gt;

&lt;p&gt;The following example shows how to push a local video file to public RTMP platforms (e.g., YouTube, Twitch):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"video.mp4"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"rtmp://your-platform-address/app/stream_key"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  Scenario 2: Embedded Local RTMP Server
&lt;/h3&gt;

&lt;p&gt;Ideal for local testing and quick setup:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;rtmp&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;embed_rtmp_server&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;EmbedRtmpServer&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;EmbedRtmpServer&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"localhost:1935"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;server&lt;/span&gt;&lt;span class="nf"&gt;.create_rtmp_input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test-app"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"test-stream"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"video.mp4"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Clients can access the stream using the URL:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rtmp://localhost:1935/test-app/test-stream
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;By leveraging Rust and the ez-ffmpeg library, developers can easily and safely implement RTMP streaming applications. Whether targeting public platforms or setting up local streaming environments, this approach makes development faster and more reliable.&lt;/p&gt;

&lt;p&gt;🔗 Project Repository: &lt;a href="https://github.com/YeautyYE/ez-ffmpeg" rel="noopener noreferrer"&gt;https://github.com/YeautyYE/ez-ffmpeg&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ffmpeg</category>
      <category>rtmp</category>
    </item>
    <item>
      <title>Efficient Video Processing in Rust: Leveraging Hardware Acceleration for High-Resolution Content</title>
      <dc:creator>Yeauty YE</dc:creator>
      <pubDate>Wed, 02 Apr 2025 07:03:04 +0000</pubDate>
      <link>https://dev.to/yeauty/efficient-video-processing-in-rust-leveraging-hardware-acceleration-for-high-resolution-content-53fe</link>
      <guid>https://dev.to/yeauty/efficient-video-processing-in-rust-leveraging-hardware-acceleration-for-high-resolution-content-53fe</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In the world of video processing, the rise of 4K, 8K, and even higher-resolution content has pushed traditional CPU-based approaches to their limits. Whether it’s video editing, live streaming, or format conversion, developers often grapple with excessive CPU usage under heavy workloads. Hardware acceleration steps in as a game-changer, offloading encoding and decoding tasks to GPUs or specialized chips, boosting performance while freeing up CPU resources for a smoother user experience. Rust, with its blend of performance and safety, offers a robust ecosystem for tackling these demands—tools like &lt;a href="https://github.com/YeautyYE/ez-ffmpeg" rel="noopener noreferrer"&gt;&lt;code&gt;ez-ffmpeg&lt;/code&gt;&lt;/a&gt; make hardware-accelerated video processing accessible and efficient.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;The Problem: Why Hardware Acceleration Matters&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Picture this: you’re building a video transcoding tool to convert a 4K clip into H.264 format. Relying solely on the CPU, the process could take minutes, with usage spiking to 100%, slowing down everything else on the system. Or consider a real-time streaming app—high latency and dropped frames can ruin the viewer’s experience. These challenges highlight a key truth: modern video processing often exceeds what CPUs alone can handle. By tapping into GPUs or dedicated hardware like Intel Quick Sync or Nvidia NVENC, hardware acceleration slashes processing times and eases system strain, delivering results in a fraction of the time.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;How It Works: Implementing Hardware Acceleration&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;At its core, hardware acceleration leverages hardware-specific APIs (think VideoToolbox, CUDA, or Direct3D) and codecs to streamline video workflows. In Rust, FFmpeg serves as a powerful foundation, and higher-level wrappers simplify its use. Here’s a quick example of hardware-accelerated transcoding in Rust:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"test.mp4"&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"output.mp4"&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="c1"&gt;// Example for macOS: Use VideoToolbox for hardware acceleration&lt;/span&gt;
    &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.set_hwaccel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"videotoolbox"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="nf"&gt;.set_video_codec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"h264_videotoolbox"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Breaking It Down&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;set_hwaccel("videotoolbox")&lt;/code&gt;&lt;/strong&gt;: Activates VideoToolbox on macOS for decoding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;set_video_codec("h264_videotoolbox")&lt;/code&gt;&lt;/strong&gt;: Sets the H.264 codec with VideoToolbox for encoding.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Outcome&lt;/strong&gt;: The input &lt;code&gt;test.mp4&lt;/code&gt; is transcoded to &lt;code&gt;output.mp4&lt;/code&gt; with hardware acceleration, far outpacing CPU-only methods.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Cross-Platform Flexibility: Adapting to Different Hardware&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Hardware acceleration varies across platforms and devices, posing a common hurdle for developers. Fortunately, it’s adaptable to diverse setups:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows&lt;/strong&gt;: Use Direct3D 12 Video Acceleration (d3d12va) for decoding and Media Foundation for encoding:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;  &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.set_hwaccel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"d3d12va"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="nf"&gt;.set_video_codec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"h264_mf"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Nvidia GPUs&lt;/strong&gt;: Pair CUDA decoding with NVENC encoding:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;  &lt;span class="n"&gt;input&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;input&lt;/span&gt;&lt;span class="nf"&gt;.set_hwaccel&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cuda"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.set_video_codec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"h264_cuvid"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="nf"&gt;.set_video_codec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"h264_nvenc"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Heads-Up&lt;/strong&gt;: Availability depends on your hardware and system. Nvidia GPUs require proper drivers, while VideoToolbox needs Apple hardware. Always verify compatibility before diving in.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;strong&gt;Wrapping Up&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;From speeding up video workflows to cutting resource usage, hardware acceleration is a must-have in today’s development toolkit. Rust’s clean APIs and strong ecosystem make it a breeze to harness this power for high-performance video processing. If you’re on the hunt for a practical solution, check out open-source projects like &lt;a href="https://github.com/YeautyYE/ez-ffmpeg" rel="noopener noreferrer"&gt;&lt;code&gt;ez-ffmpeg&lt;/code&gt;&lt;/a&gt;—it’s a solid launchpad for Rust developers looking to dive in.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Explore More&lt;/strong&gt;: &lt;a href="https://github.com/YeautyYE/ez-ffmpeg" rel="noopener noreferrer"&gt;ez-ffmpeg&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ffmpeg</category>
    </item>
    <item>
      <title>Mastering Video Effects in Rust: Unleashing FFmpeg and OpenGL Like a Pro</title>
      <dc:creator>Yeauty YE</dc:creator>
      <pubDate>Mon, 31 Mar 2025 13:51:27 +0000</pubDate>
      <link>https://dev.to/yeauty/mastering-video-effects-in-rust-unleashing-ffmpeg-and-opengl-like-a-pro-1fl0</link>
      <guid>https://dev.to/yeauty/mastering-video-effects-in-rust-unleashing-ffmpeg-and-opengl-like-a-pro-1fl0</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction: The Video Effects Struggle Is Real&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Video effects are everywhere—think short-form video filters, live-stream beauty enhancements, cinematic color grading, or even AI-generated dynamic visuals. They’re the secret sauce that hooks viewers. But let’s be honest: building them as a developer can feel like a nightmare. Sound familiar?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Bulk Processing Woes&lt;/strong&gt;: Need to slap a blur on hundreds of videos? Manual tools like Premiere or After Effects laugh in your face—way too slow.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;FFmpeg Command-Line Hell&lt;/strong&gt;: Sure, it’s powerful, but those endless cryptic flags? One typo, and you’re debugging for hours.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;C API Madness&lt;/strong&gt;: Calling FFmpeg’s C API directly? Good luck with FFI headaches and memory leaks that haunt your dreams.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Dynamic Effects Bottleneck&lt;/strong&gt;: Want real-time wave distortions or cyberpunk flickers? CPU-only processing crawls, and GPU acceleration feels like a distant dream.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If you’re a Rust developer, you’ve likely hit these walls. In this post, I’ll show you how to wield Rust, FFmpeg, and OpenGL to craft video effects with elegance and speed—basic filters to hardcore dynamic visuals, all in a few minutes. Let’s dive in.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why Rust + FFmpeg + OpenGL? The Holy Trinity of Video Magic&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Rust brings safety and performance. FFmpeg is the Swiss Army knife of multimedia. OpenGL unlocks GPU power. Together, they’re a dream team for video effects—efficient, scalable, and developer-friendly. Here’s how to make them work for you.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Get Started: Video Effects in 3 Steps&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s say you’ve got an &lt;code&gt;input.mp4&lt;/code&gt; and want to add a Gaussian blur, saving it as &lt;code&gt;output.mp4&lt;/code&gt;. Here’s the no-nonsense breakdown:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Set Up FFmpeg&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Not installed yet? It’s quick:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  brew &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  vcpkg &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
  &lt;span class="c"&gt;# First-time vcpkg users: set the VCPKG_ROOT env variable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;2. Add Rust Dependencies&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In your &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;ez-ffmpeg&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;3. Write the Code&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Blur that video in a handful of lines:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="c1"&gt;// Input file&lt;/span&gt;
        &lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"boxblur=10:10"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Gaussian blur&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;         &lt;span class="c1"&gt;// Output file&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it, and boom—&lt;code&gt;output.mp4&lt;/code&gt; has a slick blur. Chained API calls, no FFmpeg flag memorization required. Done.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;5 Real-World Use Cases and How to Nail Them&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Video effects vary wildly by project. Here are five practical scenarios with code snippets every dev can relate to:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Privacy Blur: Gaussian Effect&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"boxblur=10:10"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Live streams or videos need obscured backgrounds or sensitive areas.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result&lt;/strong&gt;: Smooth, professional blur—privacy secured, visuals intact.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Retro Vibes: Black-and-White Filter&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"format=gray"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Need a nostalgic look for a video reel, but manual grading takes forever.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result&lt;/strong&gt;: Instant monochrome magic, old-school feels in one line.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Cinematic Polish: Color Grading&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"curves=all='0/0 0.5/0.75 1/1'"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Post-production color tweaks are a slog, especially in bulk.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result&lt;/strong&gt;: Film-like brightness and contrast, effortlessly applied.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Pixel Art Style: Mosaic&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"scale=iw/10:ih/10,scale=iw*10:ih*10"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Want a stylized look or subtle obfuscation without heavy tools.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result&lt;/strong&gt;: Pixelated charm, perfect for art or privacy.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;5. Sci-Fi Twist: Negative (Night Vision)&lt;/strong&gt;
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"negate"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Craving a futuristic vibe but stuck on implementation.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result&lt;/strong&gt;: Colors inverted, night-vision style—done in a snap.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These FFmpeg filters are lightweight, fast, and ideal for batch jobs or quick prototypes.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Level Up: Dynamic Effects with OpenGL&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Static filters not cutting it? Crank things up with OpenGL and GLSL shaders for real-time, GPU-accelerated effects.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Use Case 1: Wavy Distortion&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;GLSL shader (&lt;code&gt;fragment.glsl&lt;/code&gt;):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="cp"&gt;#version 330 core
&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;TexCoord&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;vec4&lt;/span&gt; &lt;span class="n"&gt;FragColor&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;uniform&lt;/span&gt; &lt;span class="kt"&gt;sampler2D&lt;/span&gt; &lt;span class="n"&gt;screenTexture&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;uniform&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;playTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;uv&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;TexCoord&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;uv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playTime&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;uv&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;y&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mo"&gt;02&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="c1"&gt;// Wavy motion&lt;/span&gt;
    &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;texColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;screenTexture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;uv&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;FragColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;vec4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Rust code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;opengl&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;opengl_frame_filter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;OpenGLFrameFilter&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;AVMediaType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;frame_pipeline_builder&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FramePipelineBuilder&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;fragment_shader&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;include_str!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"../fragment.glsl"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;frame_pipeline&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;FramePipelineBuilder&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;AVMediaType&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AVMEDIA_TYPE_VIDEO&lt;/span&gt;&lt;span class="nf"&gt;.into&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;filter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;OpenGLFrameFilter&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new_simple&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fragment_shader&lt;/span&gt;&lt;span class="nf"&gt;.to_string&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;frame_pipeline&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;frame_pipeline&lt;/span&gt;&lt;span class="nf"&gt;.filter&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"wave"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nn"&gt;Box&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;filter&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt;

    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.add_frame_pipeline&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;frame_pipeline&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Static effects feel flat; users want motion.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result&lt;/strong&gt;: A rippling wave effect—think water or dreamy sequences.&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Use Case 2: Cyberpunk Flicker&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;GLSL shader:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight glsl"&gt;&lt;code&gt;&lt;span class="cp"&gt;#version 330 core
&lt;/span&gt;&lt;span class="k"&gt;in&lt;/span&gt; &lt;span class="kt"&gt;vec2&lt;/span&gt; &lt;span class="n"&gt;TexCoord&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;out&lt;/span&gt; &lt;span class="kt"&gt;vec4&lt;/span&gt; &lt;span class="n"&gt;color&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;uniform&lt;/span&gt; &lt;span class="kt"&gt;sampler2D&lt;/span&gt; &lt;span class="n"&gt;screenTexture&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="k"&gt;uniform&lt;/span&gt; &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;playTime&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;vec3&lt;/span&gt; &lt;span class="n"&gt;texColor&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;texture&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;screenTexture&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;TexCoord&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="n"&gt;rgb&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;r_shift&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playTime&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;g_shift&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;cos&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playTime&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;b_shift&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playTime&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;8&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;texColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;r_shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;texColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;g&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;g_shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;texColor&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;b&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;b_shift&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;float&lt;/span&gt; &lt;span class="n"&gt;brightness&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;sin&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playTime&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;95&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;texColor&lt;/span&gt; &lt;span class="o"&gt;*=&lt;/span&gt; &lt;span class="n"&gt;brightness&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;color&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;vec4&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;texColor&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Problem&lt;/strong&gt;: Short-form content needs eye-catching flair; traditional tools are clunky.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Result&lt;/strong&gt;: Pulsing colors and flickers—pure cyberpunk energy.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why This Combo Wins&lt;/strong&gt;
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Scalability&lt;/strong&gt;: Process hundreds of videos with code, not clicks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Developer Joy&lt;/strong&gt;: Chained APIs beat command-line chaos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Performance&lt;/strong&gt;: GPU via OpenGL smokes CPU-only workflows.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety&lt;/strong&gt;: Rust handles memory, sparing you C’s nightmares.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Wrap-Up: Your New Rust Superpower&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Whether it’s filters for TikTok-style apps, live-stream enhancements, or AI video pipelines, Rust with FFmpeg and OpenGL delivers. Professional effects in a few lines, GPU speed boosts, and no low-level grunt work—every dev’s dream.&lt;/p&gt;

&lt;p&gt;Curious to dig deeper? Check out this open-source gem:&lt;br&gt;&lt;br&gt;
🔗 &lt;a href="https://github.com/YeautyYE/ez-ffmpeg" rel="noopener noreferrer"&gt;https://github.com/YeautyYE/ez-ffmpeg&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ffmpeg</category>
    </item>
    <item>
      <title>Simplify Video Frame Rate Adjustment in Rust: A Practical Guide for Developers</title>
      <dc:creator>Yeauty YE</dc:creator>
      <pubDate>Fri, 28 Mar 2025 15:44:09 +0000</pubDate>
      <link>https://dev.to/yeauty/simplify-video-frame-rate-adjustment-in-rust-a-practical-guide-for-developers-20gm</link>
      <guid>https://dev.to/yeauty/simplify-video-frame-rate-adjustment-in-rust-a-practical-guide-for-developers-20gm</guid>
      <description>&lt;h2&gt;
  
  
  Introduction
&lt;/h2&gt;

&lt;p&gt;Adjusting video frame rates (FPS) is a common task in video processing, whether to ensure smooth playback or meet specific platform requirements. For instance, converting a 60 FPS video to 30 FPS might be necessary for compatibility or efficiency. While the FFmpeg command-line tool (&lt;code&gt;ffmpeg -i input.mp4 -r 30 output.mp4&lt;/code&gt;) is a popular choice, integrating this functionality directly into Rust projects can offer more control and automation.&lt;/p&gt;

&lt;p&gt;In Rust, calling FFmpeg’s C libraries via FFI (Foreign Function Interface) provides access to its full capabilities, though it can be complex and time-consuming. For simpler tasks like frame rate adjustments, &lt;code&gt;ez-ffmpeg&lt;/code&gt; offers a more straightforward approach. Built on top of FFI, it provides a user-friendly interface that streamlines common video processing tasks, making it a practical option for developers looking to avoid the intricacies of direct FFI calls.&lt;/p&gt;

&lt;h2&gt;
  
  
  FFI vs. ez-ffmpeg: Choosing the Right Tool
&lt;/h2&gt;

&lt;h3&gt;
  
  
  The Challenges of FFI
&lt;/h3&gt;

&lt;p&gt;FFI allows direct interaction with FFmpeg’s C libraries, offering maximum flexibility:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Full Control&lt;/strong&gt;: Access every feature of FFmpeg, ideal for advanced use cases.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Complexity&lt;/strong&gt;: Requires managing structs, pointers, and memory manually, which can lead to verbose and error-prone code.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Steep Learning Curve&lt;/strong&gt;: Developers need a solid understanding of FFmpeg’s low-level API.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For example, adjusting frame rates via FFI involves configuring &lt;code&gt;AVCodecContext&lt;/code&gt; and &lt;code&gt;AVFrame&lt;/code&gt;, where mistakes can easily lead to issues.&lt;/p&gt;

&lt;h3&gt;
  
  
  How ez-ffmpeg Helps
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;ez-ffmpeg&lt;/code&gt; is designed to simplify common tasks without replacing FFI entirely:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Ease of Use&lt;/strong&gt;: Its API mirrors FFmpeg command-line syntax, making it intuitive for those familiar with the tool.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Safety&lt;/strong&gt;: Handles memory management automatically, reducing risks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Focus&lt;/strong&gt;: Lets developers concentrate on application logic rather than FFmpeg internals.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While FFI is better for intricate, custom workflows, &lt;code&gt;ez-ffmpeg&lt;/code&gt; shines in scenarios where simplicity and speed are priorities, such as basic frame rate adjustments.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Started: Adjust Video Frame Rates in Rust
&lt;/h2&gt;

&lt;p&gt;Let’s say you need to convert a 60 FPS video to 30 FPS. Here’s how &lt;code&gt;ez-ffmpeg&lt;/code&gt; can help.&lt;/p&gt;

&lt;h3&gt;
  
  
  1. Install FFmpeg
&lt;/h3&gt;

&lt;h4&gt;
  
  
  macOS:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Windows:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vcpkg &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
&lt;span class="c"&gt;# Set the VCPKG_ROOT environment variable if using vcpkg for the first time&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  2. Add the Rust Dependency
&lt;/h3&gt;

&lt;p&gt;In your &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;ez-ffmpeg&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  3. Code Examples
&lt;/h3&gt;

&lt;p&gt;Below are two ways to adjust frame rates using &lt;code&gt;ez-ffmpeg&lt;/code&gt;:&lt;/p&gt;

&lt;h4&gt;
  
  
  Method 1: Set Frame Rate via Output
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;
&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ffmpeg_sys_next&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;AVRational&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Input file&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="nf"&gt;.set_framerate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;AVRational&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="n"&gt;num&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;30&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;den&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt; &lt;span class="p"&gt;}))&lt;/span&gt; &lt;span class="c1"&gt;// Set to 30 FPS&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  Method 2: Use a Filter to Set Frame Rate
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Input file&lt;/span&gt;
        &lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fps=30"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Use "fps" filter to set 30 FPS&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.mp4"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// Output file&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  When to Use Each Method
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Method 1&lt;/strong&gt;: Straightforward for basic frame rate changes. Best when that’s the only adjustment needed.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Method 2&lt;/strong&gt;: More flexible, allowing frame rate changes alongside other filters (e.g., resizing). Ideal for combined operations.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Both methods produce a 30 FPS &lt;code&gt;output.mp4&lt;/code&gt; from &lt;code&gt;test.mp4&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;For Rust developers working with video, &lt;code&gt;ez-ffmpeg&lt;/code&gt; provides a convenient way to handle tasks like frame rate adjustments. It builds on FFI to offer a simpler, safer interface for common operations, complementing the power of direct FFmpeg calls. While it’s not a solution for every scenario, it can be a valuable tool in your toolkit, especially when ease of use is a priority.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Learn more&lt;/strong&gt;: &lt;a href="https://github.com/YeautyYE/ez-ffmpeg" rel="noopener noreferrer"&gt;ez-ffmpeg on GitHub&lt;/a&gt;&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ffmpeg</category>
      <category>github</category>
    </item>
    <item>
      <title>Video Watermarking with Rust and FFmpeg: A Deep Dive into Techniques and Applications</title>
      <dc:creator>Yeauty YE</dc:creator>
      <pubDate>Wed, 26 Mar 2025 15:06:33 +0000</pubDate>
      <link>https://dev.to/yeauty/video-watermarking-with-rust-and-ffmpeg-a-deep-dive-into-techniques-and-applications-166j</link>
      <guid>https://dev.to/yeauty/video-watermarking-with-rust-and-ffmpeg-a-deep-dive-into-techniques-and-applications-166j</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In fields like short-form video platforms, live streaming, and filmmaking, watermarks play a vital role. They safeguard copyright, boost brand visibility, and ensure compliance with various requirements. However, implementing watermarking isn’t always straightforward for developers:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Manually adding watermarks with tools like Photoshop is painfully slow and impractical for large-scale tasks.&lt;/li&gt;
&lt;li&gt;FFmpeg, the industry-standard tool, excels at overlaying watermarks efficiently, but its command-line syntax is intricate, and its C API can be daunting.&lt;/li&gt;
&lt;li&gt;Calling FFmpeg directly from Rust involves foreign function interfaces (FFI), memory management, and format conversions—mistakes here can lead to frustrating pitfalls.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This article explores how to leverage Rust and FFmpeg to add video watermarks efficiently and securely. Through technical insights, code examples, and real-world scenarios, we’ll uncover a practical approach to tackling these challenges.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Scenarios and Technical Needs&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Watermarking requirements vary across use cases, each presenting unique hurdles:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Short-Form Video Platforms&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Need&lt;/strong&gt;: Automatically apply brand watermarks to user-uploaded videos.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Challenges&lt;/strong&gt;: Videos come in diverse resolutions, requiring adaptive watermark sizing and positioning; batch processing demands high efficiency.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Live Streaming&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Need&lt;/strong&gt;: Overlay streamer IDs or watermarks in real time to deter piracy.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Challenges&lt;/strong&gt;: Low latency is critical, yet watermarking involves decoding and encoding overhead; stability over long sessions is a must.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Filmmaking&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Need&lt;/strong&gt;: Add temporary watermarks to preview clips, often with transparency or animated effects.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Challenges&lt;/strong&gt;: High-quality output is non-negotiable; customization varies by project; support for multiple codecs (e.g., H.264, H.265) is essential.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;These scenarios highlight the need for a solution that harnesses FFmpeg’s power while integrating seamlessly into Rust’s safe and concise ecosystem.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Setting Up Dependencies&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Before diving into the implementation, ensure your environment is ready with these dependencies:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Install FFmpeg&lt;/strong&gt;
&lt;/h3&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;vcpkg &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
&lt;span class="c"&gt;# If using vcpkg for the first time, set the VCPKG_ROOT environment variable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;2. Add Rust Dependency&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In your Rust project, edit &lt;code&gt;Cargo.toml&lt;/code&gt; to include &lt;code&gt;ez-ffmpeg&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;ez-ffmpeg&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Implementation: From FFmpeg Commands to Rust Code&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s start with a practical example: adding a watermark (&lt;code&gt;logo.png&lt;/code&gt;) to the top-left corner of a video (&lt;code&gt;input.mp4&lt;/code&gt;), saving the result as &lt;code&gt;output.mp4&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;FFmpeg Command-Line Approach&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;FFmpeg handles watermarking via its filter system:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 &lt;span class="nt"&gt;-i&lt;/span&gt; logo.png &lt;span class="nt"&gt;-filter_complex&lt;/span&gt; &lt;span class="s2"&gt;"[1:v]scale=100:-1[wm];[0:v][wm]overlay=10:10"&lt;/span&gt; output.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Breakdown&lt;/strong&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;[1:v]scale=100:-1[wm]&lt;/code&gt;: Scales the watermark to a width of 100 pixels, with height adjusted proportionally.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[0:v][wm]overlay=10:10&lt;/code&gt;: Overlays the watermark at coordinates (10, 10) on the main video.&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;/ul&gt;

&lt;p&gt;While effective, this approach is cumbersome to debug and hard to automate programmatically.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Rust Implementation&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Using &lt;code&gt;ez-ffmpeg&lt;/code&gt;, the same task becomes more elegant in Rust:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;              &lt;span class="c1"&gt;// Main video&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"logo.png"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;              &lt;span class="c1"&gt;// Watermark image&lt;/span&gt;
        &lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[1:v]scale=100:-1[wm];[0:v][wm]overlay=10:10"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Apply filter&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.mp4"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="c1"&gt;// Output file&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;

    &lt;span class="k"&gt;match&lt;/span&gt; &lt;span class="n"&gt;result&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;mut&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.and_then&lt;/span&gt;&lt;span class="p"&gt;(|&lt;/span&gt;&lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;|&lt;/span&gt; &lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Processing failed: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="nd"&gt;println!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Watermark added successfully!"&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nf"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="k"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nd"&gt;eprintln!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Build failed: {}"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;h2&gt;
  
  
  &lt;strong&gt;Code Breakdown and Key Insights&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here’s what’s happening under the hood, along with some technical takeaways:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Input and Stream Handling&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.input("input.mp4")&lt;/code&gt; and &lt;code&gt;.input("logo.png")&lt;/code&gt; load the video and watermark.&lt;/li&gt;
&lt;li&gt;In the filter, &lt;code&gt;[0:v]&lt;/code&gt; refers to the video stream from the first input, and &lt;code&gt;[1:v]&lt;/code&gt; is the watermark stream from the second.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;FFmpeg Filter Syntax&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;.filter_desc("[1:v]scale=100:-1[wm];[0:v][wm]overlay=10:10")&lt;/code&gt;:

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;[1:v]scale=100:-1[wm]&lt;/code&gt;: Resizes the watermark to 100 pixels wide, maintaining aspect ratio.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;[0:v][wm]overlay=10:10&lt;/code&gt;: Places the watermark at (10, 10) on the video.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Pro Tip&lt;/strong&gt;: FFmpeg filters support advanced features like transparency (&lt;code&gt;format=yuva420p&lt;/code&gt;) or time-based effects (&lt;code&gt;enable='between(t,5,10)'&lt;/code&gt;).&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Rust’s Safety Guarantees&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FfmpegContext&lt;/code&gt; manages FFmpeg resources automatically, preventing memory leaks.&lt;/li&gt;
&lt;li&gt;The &lt;code&gt;Result&lt;/code&gt; type ensures errors (e.g., missing files) are handled explicitly.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Performance Notes&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;FFmpeg’s C-based core handles the heavy lifting, keeping performance optimal.&lt;/li&gt;
&lt;li&gt;Rust adds minimal overhead, acting solely as a coordinator for inputs, filters, and outputs.&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;/ol&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Advanced Customization: Adjusting Watermark Position&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;To move the watermark to the bottom-right corner, tweak the &lt;code&gt;overlay&lt;/code&gt; parameters:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[1:v]scale=100:-1[wm];[0:v][wm]overlay=W-w-10:H-h-10"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;W&lt;/code&gt; and &lt;code&gt;H&lt;/code&gt; are the video’s width and height.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;w&lt;/code&gt; and &lt;code&gt;h&lt;/code&gt; are the watermark’s dimensions.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;W-w-10&lt;/code&gt; and &lt;code&gt;H-h-10&lt;/code&gt; align the watermark 10 pixels from the bottom-right edge.&lt;/li&gt;
&lt;/ul&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Conclusion&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Combining Rust with FFmpeg offers a powerful way to implement video watermarking, addressing needs from batch processing on short-video platforms to real-time overlays in live streams. Tools like &lt;code&gt;ez-ffmpeg&lt;/code&gt; streamline this process, letting developers focus on functionality rather than wrestling with FFmpeg’s complexities—all while preserving Rust’s safety and simplicity.&lt;/p&gt;

&lt;p&gt;For more details or to explore the codebase, check out the open-source project: &lt;a href="https://github.com/YeautyYE/ez-ffmpeg" rel="noopener noreferrer"&gt;ez-ffmpeg&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ffmpeg</category>
    </item>
    <item>
      <title>Quick and Easy Video Thumbnail Generation in Rust</title>
      <dc:creator>Yeauty YE</dc:creator>
      <pubDate>Mon, 24 Mar 2025 11:09:09 +0000</pubDate>
      <link>https://dev.to/yeauty/quick-and-easy-video-thumbnail-generation-in-rust-3d1c</link>
      <guid>https://dev.to/yeauty/quick-and-easy-video-thumbnail-generation-in-rust-3d1c</guid>
      <description>&lt;p&gt;Ever struggled with FFmpeg commands just to generate a simple video thumbnail? You’re not alone. As a Rust enthusiast, I’ve been there— wrestling with cryptic parameters and praying my command doesn’t crash. But there’s a better way: the &lt;code&gt;ez-ffmpeg&lt;/code&gt; library. With just a few lines of Rust code, you can create thumbnails effortlessly. Let’s dive in.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;The FFmpeg Struggle Is Real&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Video thumbnails are a common need—think preview images for a video site or cover art for a CMS. Traditionally, developers turn to FFmpeg, a powerhouse tool that can handle any multimedia task. The catch? Its command-line interface is a nightmare for beginners. Want a thumbnail? You’re stuck writing something like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 &lt;span class="nt"&gt;-vf&lt;/span&gt; &lt;span class="s2"&gt;"scale=160:-1"&lt;/span&gt; &lt;span class="nt"&gt;-frames&lt;/span&gt;:v 1 &lt;span class="nt"&gt;-q&lt;/span&gt;:v 2 thumbnail.jpg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Too many parameters, too many chances to mess up. Enter &lt;code&gt;ez-ffmpeg&lt;/code&gt;, a Rust library that wraps FFmpeg’s complexity into a clean, intuitive API. Plus, it leverages Rust’s safety features to keep your code bug-free.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Getting Started with &lt;code&gt;ez-ffmpeg&lt;/code&gt;&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here’s how to generate video thumbnails in Rust, step-by-step.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Install FFmpeg&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;First, you’ll need FFmpeg on your system. Here’s how to set it up:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  brew &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows&lt;/strong&gt; (using &lt;a href="https://vcpkg.io/" rel="noopener noreferrer"&gt;vcpkg&lt;/a&gt;):
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  vcpkg &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
  &lt;span class="c"&gt;# New to vcpkg? Set the VCPKG_ROOT environment variable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run &lt;code&gt;ffmpeg -version&lt;/code&gt; to confirm it’s working.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Set Up Your Rust Project&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In your Rust project, open &lt;code&gt;Cargo.toml&lt;/code&gt; and add:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;ez-ffmpeg&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"0.1"&lt;/span&gt;  &lt;span class="c"&gt;# Pin a version to avoid surprises&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;3. Generate a Single Thumbnail&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Let’s extract one thumbnail from a video—width 160 pixels, high quality, aspect ratio preserved. Here’s the code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Your video file&lt;/span&gt;
        &lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"scale='min(160,iw)':-1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Width 160, auto height&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"thumbnail.jpg"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
                &lt;span class="nf"&gt;.set_max_video_frames&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// One frame only&lt;/span&gt;
                &lt;span class="nf"&gt;.set_video_quality&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// High quality (2 is great, lower is better)&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it, and boom—&lt;code&gt;thumbnail.jpg&lt;/code&gt; appears in your directory. The &lt;code&gt;scale&lt;/code&gt; filter ensures the width is 160 pixels while keeping the aspect ratio, and &lt;code&gt;set_video_quality(2)&lt;/code&gt; delivers a crisp image.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;4. Generate Multiple Thumbnails&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Need a thumbnail every 10 seconds for a video preview? Here’s how:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Your video file&lt;/span&gt;
        &lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"select='not(mod(t,10))',scale='min(160,iw)':-1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// One frame every 10s, scaled&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
            &lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"thumbnail_%03d.jpg"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Sequential filenames&lt;/span&gt;
                &lt;span class="nf"&gt;.set_video_quality&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="c1"&gt;// High quality&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This spits out &lt;code&gt;thumbnail_001.jpg&lt;/code&gt;, &lt;code&gt;thumbnail_002.jpg&lt;/code&gt;, etc., capturing a frame every 10 seconds. The &lt;code&gt;select&lt;/code&gt; filter does the timing magic, and &lt;code&gt;%03d&lt;/code&gt; handles the numbering.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Beyond Thumbnails&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;&lt;code&gt;ez-ffmpeg&lt;/code&gt; isn’t a one-trick pony. You can:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Tweak frame rates using &lt;code&gt;set_frame_rate&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Output in formats like PNG or WebP.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Check out the &lt;a href="https://github.com/YeautyYE/ez-ffmpeg/tree/main/docs" rel="noopener noreferrer"&gt;official docs&lt;/a&gt; for the full scoop.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why You’ll Love It&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;For Rust developers, &lt;code&gt;ez-ffmpeg&lt;/code&gt; is a game-changer. It turns FFmpeg’s command-line chaos into simple, safe Rust code. Whether you’re grabbing one thumbnail or a dozen, it’s fast, reliable, and saves you from parameter hell. As someone who’s wasted hours debugging FFmpeg flags, I can’t recommend it enough.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Ready to Try It?&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Head over to the &lt;a href="https://github.com/YeautyYE/ez-ffmpeg" rel="noopener noreferrer"&gt;ez-ffmpeg GitHub repository&lt;/a&gt; to get started. Simplify your video processing today!&lt;/p&gt;

</description>
    </item>
    <item>
      <title>Master Audio Extraction in Three Minutes | Elegant Video-to-Audio Processing in Rust</title>
      <dc:creator>Yeauty YE</dc:creator>
      <pubDate>Sat, 22 Mar 2025 15:13:01 +0000</pubDate>
      <link>https://dev.to/yeauty/master-audio-extraction-in-three-minutes-elegant-video-to-audio-processing-in-rust-3k0e</link>
      <guid>https://dev.to/yeauty/master-audio-extraction-in-three-minutes-elegant-video-to-audio-processing-in-rust-3k0e</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;In multimedia development, &lt;strong&gt;extracting audio from video&lt;/strong&gt; is a common task. Whether you want to isolate background music for enjoyment, pull dialogue for speech analysis, or generate subtitles, audio extraction is a foundational skill in the field.&lt;/p&gt;

&lt;p&gt;Traditionally, you might use FFmpeg’s command-line tool to get the job done quickly. For example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 &lt;span class="nt"&gt;-vn&lt;/span&gt; &lt;span class="nt"&gt;-acodec&lt;/span&gt; copy output.aac
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;-vn&lt;/code&gt; disables the video stream, and &lt;code&gt;-acodec copy&lt;/code&gt; copies the audio stream directly—simple and effective. But for Rust developers, calling a command-line tool from code can feel clunky, especially when you need tight integration or precise control. Isn’t there a more elegant way? In this article, we’ll explore how to handle audio extraction in Rust—practical, beginner-friendly, and ready to use in just three minutes!&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Pain Points and Use Cases&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;When working with audio and video in a Rust project, developers often run into these challenges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Command-Line Calls Lack Flexibility&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Using &lt;code&gt;std::process::Command&lt;/code&gt; to run FFmpeg spawns an external process, eating up resources and forcing you to manually handle errors and outputs. A typo in the path or a missing argument? Good luck debugging that.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Steep Learning Curve with Complex Parameters&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
FFmpeg’s options are overwhelming. Basics like &lt;code&gt;-vn&lt;/code&gt; or &lt;code&gt;-acodec&lt;/code&gt; are manageable, but throw in sampling rates or time trimming, and the parameter soup can drive anyone nuts.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Poor Code Integration&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Stringing together command-line arguments in code looks messy, hurts readability, and makes maintenance a nightmare. It clashes with Rust’s focus on type safety and clean logic.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cross-Platform Headaches&lt;/strong&gt;&lt;br&gt;&lt;br&gt;
Windows, macOS, and Linux handle command-line tools differently. Path mismatches or environment quirks can break your app, making portability a constant struggle.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So, how can Rust developers escape these headaches and focus on building? The answer is yes—thanks to Rust’s ecosystem! Tools like &lt;code&gt;ez-ffmpeg&lt;/code&gt; wrap FFmpeg in a neat API, letting us extract audio elegantly. Let’s dive into some hands-on examples.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Getting Started: Extract Audio in Rust&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Imagine you have a video file, &lt;code&gt;test.mp4&lt;/code&gt;, and want to extract its audio into &lt;code&gt;output.aac&lt;/code&gt;. Here’s how to do it step-by-step:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Set Up Your Environment&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;First, ensure FFmpeg is installed on your system—it’s the backbone of audio-video processing. Installation varies by platform:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;macOS&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  brew &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Windows&lt;/strong&gt;:
&lt;/li&gt;
&lt;/ul&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;  &lt;span class="c"&gt;# Install via vcpkg&lt;/span&gt;
  vcpkg &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
  &lt;span class="c"&gt;# First-time vcpkg users: set the VCPKG_ROOT environment variable&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;2. Configure Your Rust Project&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Add the &lt;code&gt;ez-ffmpeg&lt;/code&gt; library to your Rust project. Edit your &lt;code&gt;Cargo.toml&lt;/code&gt;:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;ez-ffmpeg&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;3. Write the Code&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;main.rs&lt;/code&gt; file and add this code:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="c1"&gt;// Input video file&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.aac"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// Output audio file&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;       &lt;span class="c1"&gt;// Build the context&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;       &lt;span class="c1"&gt;// Start processing&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;       &lt;span class="c1"&gt;// Wait for completion&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run it, and boom—&lt;code&gt;output.aac&lt;/code&gt; is ready! Audio extracted, no fuss.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Code Breakdown and Insights&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;This snippet is small but powerful, tackling key pain points:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Chained API, Easy to Read&lt;/strong&gt;: &lt;code&gt;.input()&lt;/code&gt; and &lt;code&gt;.output()&lt;/code&gt; set the stage clearly—no command-line string hacking required.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Smart Defaults&lt;/strong&gt;: No need to specify &lt;code&gt;-vn&lt;/code&gt; or &lt;code&gt;-acodec&lt;/code&gt;; the library handles it based on context.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Rust-Style Error Handling&lt;/strong&gt;: &lt;code&gt;.unwrap()&lt;/code&gt; keeps it simple for now, but you can swap in &lt;code&gt;Result&lt;/code&gt; for production-grade robustness.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Quick Tip&lt;/strong&gt;: By default, this copies the audio stream (like &lt;code&gt;-acodec copy&lt;/code&gt;), making it fast and lossless. Want to transcode instead? The library adjusts based on the output file extension.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Level Up: Advanced Techniques&lt;/strong&gt;
&lt;/h2&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Convert to MP3&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Prefer MP3 over AAC? Just tweak the output filename:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.mp3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// Switch to MP3&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Insight&lt;/strong&gt;: The &lt;code&gt;.mp3&lt;/code&gt; extension triggers transcoding instead of copying. Make sure your FFmpeg supports the MP3 encoder (it usually does by default).&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Extract a Specific Time Range&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Need just a chunk of audio, say from 30 to 90 seconds? Here’s how:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.set_start_time_us&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;30_000_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;// Start at 30 seconds&lt;/span&gt;
            &lt;span class="nf"&gt;.set_recording_time_us&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;60_000_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Duration of 60 seconds&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.mp3"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Insight&lt;/strong&gt;: Times are in microseconds (1 second = 1,000,000 µs), offering more precision than FFmpeg’s &lt;code&gt;-ss&lt;/code&gt; and &lt;code&gt;-t&lt;/code&gt;. It’s also flexible for dynamic adjustments.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Customize Audio with Mono, Sample Rate, and Codec&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Sometimes you need full control—say, for speech analysis requiring mono audio at a specific sample rate with a lossless codec. Here’s an example setting the audio to single-channel, 16000 Hz, and &lt;code&gt;pcm_s16le&lt;/code&gt; (16-bit PCM):&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Output&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.wav"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.set_audio_channels&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c1"&gt;// Mono audio&lt;/span&gt;
            &lt;span class="nf"&gt;.set_audio_sample_rate&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;16000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// 16000 Hz sample rate&lt;/span&gt;
            &lt;span class="nf"&gt;.set_audio_codec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"pcm_s16le"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;   &lt;span class="c1"&gt;// 16-bit PCM codec&lt;/span&gt;
        &lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Insights&lt;/strong&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.set_audio_channels(1)&lt;/code&gt;&lt;/strong&gt;: Switches to mono, perfect for voice-focused tasks.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.set_audio_sample_rate(16000)&lt;/code&gt;&lt;/strong&gt;: Sets 16 kHz, a sweet spot for speech recognition—clear yet compact.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.set_audio_codec("pcm_s16le")&lt;/code&gt;&lt;/strong&gt;: Uses a lossless PCM format, ideal for analysis or editing; paired with &lt;code&gt;.wav&lt;/code&gt; for compatibility.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Why WAV?&lt;/strong&gt;: &lt;code&gt;pcm_s16le&lt;/code&gt; works best with WAV files, not MP3 or AAC, due to its uncompressed nature.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This setup is a game-changer for tasks like speech processing or high-fidelity audio work.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Wrap-Up&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;With Rust and tools like &lt;code&gt;ez-ffmpeg&lt;/code&gt;, audio extraction doesn’t have to mean wrestling with command-line hacks. You get:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Simplicity&lt;/strong&gt;: A few lines replace a forest of parameters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Maintainability&lt;/strong&gt;: Clean, readable code that fits right into your project.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Flexibility&lt;/strong&gt;: From basic extraction to custom audio tweaks, it’s all there.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you’re a newbie or a seasoned dev, this approach lets you jump into audio-video processing fast, keeping your focus on creativity—not configuration. Want to dig deeper? Check out projects like &lt;a href="https://github.com/YeautyYE/ez-ffmpeg" rel="noopener noreferrer"&gt;ez-ffmpeg&lt;/a&gt; for more features.&lt;/p&gt;

&lt;p&gt;Here’s to mastering audio extraction in Rust—give it a spin and see how easy it can be!&lt;/p&gt;

</description>
      <category>rust</category>
      <category>ffmpeg</category>
      <category>encode</category>
    </item>
    <item>
      <title>Master Video Resolution Adjustment in Rust with FFmpeg in 3 Minutes</title>
      <dc:creator>Yeauty YE</dc:creator>
      <pubDate>Wed, 19 Mar 2025 14:46:59 +0000</pubDate>
      <link>https://dev.to/yeauty/master-video-resolution-adjustment-in-rust-with-ffmpeg-in-3-minutes-3hfd</link>
      <guid>https://dev.to/yeauty/master-video-resolution-adjustment-in-rust-with-ffmpeg-in-3-minutes-3hfd</guid>
      <description>&lt;h2&gt;
  
  
  &lt;strong&gt;Introduction&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Adjusting video resolution is a routine task in video processing. Whether you're resizing a video for playback on different devices—like phones, tablets, or TVs—or reducing file size to save storage and bandwidth, resolution adjustment is a must-have skill. FFmpeg is a go-to tool for this, but its command-line interface can feel overwhelming with its endless options and tricky syntax. For Rust developers, integrating FFmpeg directly into a project can also be clunky and prone to errors. So, how can you simplify this process in Rust? In this article, I’ll show you a clean, efficient way to adjust video resolution with minimal hassle.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why It’s Tricky and How Rust Can Help&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Working with video resolution in Rust often comes with a few headaches:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Steep Learning Curve&lt;/strong&gt;: FFmpeg’s command-line options and filter syntax take time to master, especially for newcomers.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Error-Prone Commands&lt;/strong&gt;: Writing FFmpeg commands manually can lead to mistakes, particularly with complex filters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration Overhead&lt;/strong&gt;: Spawning external processes from Rust to run FFmpeg requires extra code for managing execution and handling errors.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;A better approach? Use a Rust library that wraps FFmpeg’s power into a simple, developer-friendly API. This lets you focus on your project’s logic instead of wrestling with FFmpeg’s quirks.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Quick Start: Resize a Video in Rust&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Let’s say you’re building a video-sharing app. A user uploads &lt;code&gt;test.mp4&lt;/code&gt;, and you need to resize it to a width of 1280 pixels while keeping the aspect ratio intact, saving it as &lt;code&gt;output.mp4&lt;/code&gt;. This is a common need for device compatibility or file optimization. Here’s how to do it in Rust:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;Step 1: Install FFmpeg&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;First, make sure FFmpeg is installed on your system. Here’s how to set it up:&lt;/p&gt;

&lt;h4&gt;
  
  
  &lt;strong&gt;macOS&lt;/strong&gt;:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h4&gt;
  
  
  &lt;strong&gt;Windows&lt;/strong&gt;:
&lt;/h4&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Using vcpkg&lt;/span&gt;
vcpkg &lt;span class="nb"&gt;install &lt;/span&gt;ffmpeg
&lt;span class="c"&gt;# Tip: Set the VCPKG_ROOT environment variable if you’re new to vcpkg&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 2: Add the Rust Dependency&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;In your &lt;code&gt;Cargo.toml&lt;/code&gt;, include this library dependency:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight toml"&gt;&lt;code&gt;&lt;span class="nn"&gt;[dependencies]&lt;/span&gt;
&lt;span class="py"&gt;ez-ffmpeg&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"*"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h3&gt;
  
  
  &lt;strong&gt;Step 3: Write the Code&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;Create a &lt;code&gt;main.rs&lt;/code&gt; file and add this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"test.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;          &lt;span class="c1"&gt;// Input video file&lt;/span&gt;
        &lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"scale=1280:-1"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// Resize to 1280px width, auto-height&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;       &lt;span class="c1"&gt;// Output file&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;           &lt;span class="c1"&gt;// Create the processing context&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;           &lt;span class="c1"&gt;// Kick off the process&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="nf"&gt;.unwrap&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;           &lt;span class="c1"&gt;// Wait for it to finish&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Run the code, and voilà—your resized &lt;code&gt;output.mp4&lt;/code&gt; is ready. Compared to raw FFmpeg commands, this is shorter, cleaner, and less likely to trip you up.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;How It Works&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Here’s a quick breakdown of the code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.input("test.mp4")&lt;/code&gt;&lt;/strong&gt;: Sets the source video.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.filter_desc("scale=1280:-1")&lt;/code&gt;&lt;/strong&gt;: Resizes the video to 1280 pixels wide, with &lt;code&gt;-1&lt;/code&gt; auto-calculating the height to preserve the aspect ratio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;&lt;code&gt;.output("output.mp4")&lt;/code&gt;&lt;/strong&gt;: Defines where the result goes.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Chained Methods&lt;/strong&gt;: &lt;code&gt;.build()&lt;/code&gt;, &lt;code&gt;.start()&lt;/code&gt;, and &lt;code&gt;.wait()&lt;/code&gt; handle the setup, execution, and completion in a neat flow.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;For reference, the equivalent FFmpeg command is &lt;code&gt;ffmpeg -i test.mp4 -vf scale=1280:-1 output.mp4&lt;/code&gt;. With Rust, you skip the manual command-building and get a more maintainable solution.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Real-World Examples&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Resolution tweaks come up in all sorts of projects. Here are a few scenarios and how to handle them:&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;1. Fixed Resolution (e.g., 640x480)&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;For a specific size, like fitting an older device:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"scale=640:480"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Heads-up: This might stretch or squash the video if the aspect ratio doesn’t match.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;2. Single-Dimension Resize with Aspect Ratio&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To set the height to 720 pixels and keep proportions:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"scale=-1:720"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The width adjusts automatically—no distortion.&lt;/p&gt;

&lt;h3&gt;
  
  
  &lt;strong&gt;3. Proportional Scaling&lt;/strong&gt;
&lt;/h3&gt;

&lt;p&gt;To shrink the video to half its original size:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"scale=iw*0.5:ih*0.5"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Here, &lt;code&gt;iw&lt;/code&gt; (input width) and &lt;code&gt;ih&lt;/code&gt; (input height) let you scale dynamically based on the source.&lt;/p&gt;

&lt;p&gt;These options make it easy to adapt videos for different devices, reduce file sizes, or generate multiple versions.&lt;/p&gt;




&lt;h2&gt;
  
  
  &lt;strong&gt;Why This Matters&lt;/strong&gt;
&lt;/h2&gt;

&lt;p&gt;Using FFmpeg directly in Rust projects can be a slog—learning its syntax, debugging commands, and managing processes take time. A Rust library like this flips the script:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Saves Time&lt;/strong&gt;: No more fiddling with arcane parameters.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Reduces Errors&lt;/strong&gt;: Chained methods beat hand-typed commands.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Stays Flexible&lt;/strong&gt;: Adjusts to your needs with minimal tweaks.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Whether you’re crafting a transcoding tool, prepping videos for cross-device playback, or trimming storage costs, this approach gets you there faster.&lt;/p&gt;

&lt;p&gt;🔗 &lt;strong&gt;Check It Out&lt;/strong&gt;: &lt;a href="https://github.com/YeautyYE/ez-ffmpeg" rel="noopener noreferrer"&gt;ez-ffmpeg on GitHub&lt;/a&gt;&lt;/p&gt;

</description>
    </item>
    <item>
      <title>[Boost]</title>
      <dc:creator>Yeauty YE</dc:creator>
      <pubDate>Tue, 18 Mar 2025 09:23:51 +0000</pubDate>
      <link>https://dev.to/yeauty/-341d</link>
      <guid>https://dev.to/yeauty/-341d</guid>
      <description>&lt;div class="ltag__link"&gt;
  &lt;a href="/yeauty" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__pic"&gt;
      &lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F2932171%2Fe3eedc22-29d9-4208-a808-b30b6d3116b7.png" alt="yeauty"&gt;
    &lt;/div&gt;
  &lt;/a&gt;
  &lt;a href="https://dev.to/yeauty/from-ffmpeg-command-line-to-rust-a-practical-guide-for-multiple-scenarios-1395" class="ltag__link__link"&gt;
    &lt;div class="ltag__link__content"&gt;
      &lt;h2&gt;From FFmpeg Command Line to Rust: A Practical Guide for Multiple Scenarios&lt;/h2&gt;
      &lt;h3&gt;Yeauty YE ・ Mar 17&lt;/h3&gt;
      &lt;div class="ltag__link__taglist"&gt;
      &lt;/div&gt;
    &lt;/div&gt;
  &lt;/a&gt;
&lt;/div&gt;


</description>
    </item>
    <item>
      <title>From FFmpeg Command Line to Rust: A Practical Guide for Multiple Scenarios</title>
      <dc:creator>Yeauty YE</dc:creator>
      <pubDate>Mon, 17 Mar 2025 16:02:33 +0000</pubDate>
      <link>https://dev.to/yeauty/from-ffmpeg-command-line-to-rust-a-practical-guide-for-multiple-scenarios-1395</link>
      <guid>https://dev.to/yeauty/from-ffmpeg-command-line-to-rust-a-practical-guide-for-multiple-scenarios-1395</guid>
      <description>&lt;p&gt;FFmpeg is a powerful multimedia processing tool widely used in video editing, format conversion, and more. However, using FFmpeg directly through its command-line interface (CLI) can present several challenges:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;High Complexity&lt;/strong&gt;: FFmpeg's CLI comes with numerous parameters that can be difficult for beginners to grasp. Debugging errors in configurations can be a daunting task.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Integration Challenges&lt;/strong&gt;: Calling FFmpeg's C API directly in modern programming languages like Rust requires careful memory management and security handling, potentially leading to memory leaks or illegal accesses.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;To address these issues, libraries like &lt;a href="https://github.com/YeautyYE/ez-ffmpeg" rel="noopener noreferrer"&gt;&lt;code&gt;ez-ffmpeg&lt;/code&gt;&lt;/a&gt; offer a more ergonomic and safer way to work with FFmpeg in Rust. Unlike official Rust community-provided libraries, &lt;code&gt;ez-ffmpeg&lt;/code&gt; is an independent project designed to simplify multimedia processing in Rust applications.&lt;/p&gt;

&lt;p&gt;Below are several common scenarios demonstrating how to convert FFmpeg CLI commands into Rust code:&lt;/p&gt;

&lt;h2&gt;
  
  
  1. Video Format Conversion
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;FFmpeg CLI:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 output.avi
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Equivalent Rust Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FfmpegScheduler&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.avi"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nn"&gt;FfmpegScheduler&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  2. Extracting Audio
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;FFmpeg CLI:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 &lt;span class="nt"&gt;-vn&lt;/span&gt; &lt;span class="nt"&gt;-acodec&lt;/span&gt; copy output.aac
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Equivalent Rust Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FfmpegScheduler&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.aac"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.no_video&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nn"&gt;FfmpegScheduler&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  3. Video Clipping
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;FFmpeg CLI:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 &lt;span class="nt"&gt;-ss&lt;/span&gt; 00:00:10 &lt;span class="nt"&gt;-t&lt;/span&gt; 00:00:05 &lt;span class="nt"&gt;-c&lt;/span&gt; copy output.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Equivalent Rust Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FfmpegScheduler&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nn"&gt;Input&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.set_start_time_us&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;10_000_000&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="nf"&gt;.set_recording_time_us&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;5_000_000&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nn"&gt;FfmpegScheduler&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  4. Converting Video to GIF
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;FFmpeg CLI:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-i&lt;/span&gt; input.mp4 &lt;span class="nt"&gt;-vf&lt;/span&gt; &lt;span class="s2"&gt;"fps=10,scale=320:-1:flags=lanczos"&lt;/span&gt; &lt;span class="nt"&gt;-c&lt;/span&gt;:v gif output.gif
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Equivalent Rust Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FfmpegScheduler&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.input&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"input.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.filter_desc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"fps=10,scale=320:-1:flags=lanczos"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.gif"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nn"&gt;FfmpegScheduler&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  5. Merging Multiple Videos
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;FFmpeg CLI:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;ffmpeg &lt;span class="nt"&gt;-f&lt;/span&gt; concat &lt;span class="nt"&gt;-safe&lt;/span&gt; 0 &lt;span class="nt"&gt;-i&lt;/span&gt; filelist.txt &lt;span class="nt"&gt;-c&lt;/span&gt; copy output.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;Equivalent Rust Code:&lt;/strong&gt;&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight rust"&gt;&lt;code&gt;&lt;span class="k"&gt;use&lt;/span&gt; &lt;span class="nn"&gt;ez_ffmpeg&lt;/span&gt;&lt;span class="p"&gt;::{&lt;/span&gt;&lt;span class="n"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;FfmpegScheduler&lt;/span&gt;&lt;span class="p"&gt;};&lt;/span&gt;

&lt;span class="k"&gt;fn&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="nb"&gt;Box&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="k"&gt;dyn&lt;/span&gt; &lt;span class="nn"&gt;std&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nn"&gt;error&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;inputs&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nd"&gt;vec!&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"file1.mp4"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"file2.mp4"&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;

    &lt;span class="k"&gt;let&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nn"&gt;FfmpegContext&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;builder&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
        &lt;span class="nf"&gt;.inputs&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;inputs&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.output&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"output.mp4"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.build&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="nn"&gt;FfmpegScheduler&lt;/span&gt;&lt;span class="p"&gt;::&lt;/span&gt;&lt;span class="nf"&gt;new&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="nf"&gt;.start&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;
        &lt;span class="nf"&gt;.wait&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Through these examples, you can see how &lt;a href="https://github.com/YeautyYE/ez-ffmpeg" rel="noopener noreferrer"&gt;&lt;code&gt;ez-ffmpeg&lt;/code&gt;&lt;/a&gt; provides a safer and more concise interface for working with FFmpeg in Rust. This approach enables developers to efficiently implement multimedia processing features while leveraging Rust's safety and performance benefits.&lt;/p&gt;

</description>
    </item>
  </channel>
</rss>
