<?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: Ronald Gosso</title>
    <description>The latest articles on DEV Community by Ronald Gosso (@ronaldgosso).</description>
    <link>https://dev.to/ronaldgosso</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.us-east-2.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F4167250%2F5a2f27e8-acb9-47c8-ae72-0136d9c47167.jpg</url>
      <title>DEV Community: Ronald Gosso</title>
      <link>https://dev.to/ronaldgosso</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/ronaldgosso"/>
    <language>en</language>
    <item>
      <title>My friend failed his OS exam by 4 marks and passed a cloud cert with 912 the same week</title>
      <dc:creator>Ronald Gosso</dc:creator>
      <pubDate>Tue, 20 Oct 2026 09:00:00 +0000</pubDate>
      <link>https://dev.to/ronaldgosso/my-friend-failed-his-os-exam-by-4-marks-and-passed-a-cloud-cert-with-912-the-same-week-2eo4</link>
      <guid>https://dev.to/ronaldgosso/my-friend-failed-his-os-exam-by-4-marks-and-passed-a-cloud-cert-with-912-the-same-week-2eo4</guid>
      <description>&lt;p&gt;My friend failed operating systems by 4 marks. Same week, he passed his first cloud certification with a score of 912.&lt;/p&gt;

&lt;p&gt;I keep thinking about that week. Not because of the gap between the two numbers, but because I was living in the same gap. I just hadn't admitted it yet.&lt;/p&gt;

&lt;h2&gt;
  
  
  Two worlds that refused to talk
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkt64ona69qfxjhdsk8hq.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fkt64ona69qfxjhdsk8hq.png" alt=" " width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;On one side you have the university. Lecture halls with 200 students, a projector, and a lecturer drawing a process state diagram on a whiteboard for the ninth time. Theory, proofs, exam papers, marks.&lt;/p&gt;

&lt;p&gt;On the other side you have the cloud. A terminal at 2 AM. A dashboard turning red. A teammate asking why the function that worked yesterday now times out. Nobody there asks you to define a semaphore. They ask you to make the red thing green.&lt;/p&gt;

&lt;p&gt;For a long time I assumed one of those worlds was a waste of my time. Some days I blamed the lectures. Other days I blamed the tutorials that taught me how to click through a console but never why anything behaved the way it did. I had a quiet theory that I only needed one of them, and I kept changing my mind about which.&lt;/p&gt;

&lt;p&gt;I was wrong, and the way I found out was slow and a little embarrassing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Deadlocks on paper, timeouts in production
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg4gm4rulvtq7w9bdvpp7.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fg4gm4rulvtq7w9bdvpp7.png" alt=" " width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the OS course, deadlock is a tidy little story. Two processes, two resources. Process A holds one and waits for the other. Process B holds the other and waits for the first. Neither moves. You draw a resource allocation graph, find the cycle, and get your marks.&lt;/p&gt;

&lt;p&gt;Then you meet a Lambda function that times out and the logs say nothing useful.&lt;/p&gt;

&lt;p&gt;Here is what it looked like in my case. The function opened a database connection, grabbed a lock on a row, and then called another service that was also waiting on that same row. Different code, different runtime, same shape as the diagram on the whiteboard. A cycle. Two things holding and waiting. The timeout was the platform's way of killing the stalemate after a fixed number of seconds.&lt;/p&gt;

&lt;p&gt;Once I saw it as a hold-and-wait problem, the fixes were already in my notes. Break the circular wait by always acquiring locks in the same order. Stop holding a resource while you wait on something slow. Add a timeout of your own so you fail early instead of hanging until the platform pulls the plug.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="c1"&gt;# Same idea as the textbook fix: one global order for locks
&lt;/span&gt;&lt;span class="k"&gt;def&lt;/span&gt; &lt;span class="nf"&gt;transfer&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="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt;
    &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;sorted&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="n"&gt;b&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="n"&gt;key&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="k"&gt;lambda&lt;/span&gt; &lt;span class="n"&gt;acct&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;acct&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nb"&gt;id&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
        &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;lock&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;first&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;debit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="n"&gt;second&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;credit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;amount&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I did not learn that from a cloud tutorial. I learned it from a lecture I had half ignored.&lt;/p&gt;

&lt;h2&gt;
  
  
  Normalization and the DynamoDB bill
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fljjqrm9klxwy1iqyjz63.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fljjqrm9klxwy1iqyjz63.png" alt=" " width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Normalization is the other chapter I used to treat as exam fodder. First normal form, second, third, the whole ladder. Remove repeated groups, remove partial dependencies, remove transitive ones. You split tables so each fact lives in exactly one place.&lt;/p&gt;

&lt;p&gt;It is a great habit for a relational database. It is a terrible habit to carry unchanged into DynamoDB.&lt;/p&gt;

&lt;p&gt;I did carry it over. I modeled my data the way I had been trained to, with small clean tables and relationships stitched together at read time. DynamoDB has no joins, so my application did the stitching. One screen in the app meant five or six separate reads, and a few queries that quietly turned into scans. Reads cost money. Scans on a growing table cost a lot of money. The bill told me, rather loudly, that my model was wrong for the tool.&lt;/p&gt;

&lt;p&gt;What fixed it was understanding why normalization exists in the first place. It exists to avoid update anomalies and wasted storage in a system where joins are cheap. In a key-value store where reads are the expensive part, the trade flips. You design around your access patterns, you duplicate data on purpose, and you accept that updates get harder because reads get cheaper.&lt;/p&gt;

&lt;p&gt;If I had only memorized the rules, I would have been stuck. Because I understood the reasoning behind them, I could see exactly where the reasoning stopped applying. That is the whole difference between knowing a rule and knowing a tradeoff.&lt;/p&gt;

&lt;h2&gt;
  
  
  Scheduling, and how Kubernetes picks a pod's home
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbu8j28kwsoyh5xg6zyru.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fbu8j28kwsoyh5xg6zyru.png" alt=" " width="800" height="336"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Every OS course spends weeks on CPU scheduling. First come first served, shortest job first, round robin, priority queues, starvation, aging. You compute average waiting times by hand until you hate Gantt charts.&lt;/p&gt;

&lt;p&gt;Then you read how the Kubernetes scheduler works and it feels strangely familiar.&lt;/p&gt;

&lt;p&gt;A new pod arrives and sits in a queue. The scheduler filters out nodes that cannot run it, for example nodes without enough CPU or memory left. Then it scores the survivors and picks the best one. Pods carry priorities. A high priority pod can preempt a lower one when the cluster is full. Resource requests and limits decide what a pod is promised and what it is allowed to burn.&lt;/p&gt;

&lt;p&gt;Swap the word process for pod and the word CPU for node, and half of it reads like my old lecture notes. Priority inversion, starvation, preemption. These were not abstract words anymore. They explained why a low priority batch job kept getting evicted, and why a pod with no resource requests behaved like a noisy neighbor.&lt;/p&gt;

&lt;p&gt;Nobody told me this would happen. I found out because a pod stayed Pending and I knew which questions to ask.&lt;/p&gt;

&lt;h2&gt;
  
  
  What the rebuild actually was
&lt;/h2&gt;

&lt;p&gt;I did not wake up one morning and decide to connect the two worlds. It happened in small collisions. A production problem would stall me, I would remember a diagram from a lecture, and the problem would crack open.&lt;/p&gt;

&lt;p&gt;Over time I started doing it on purpose. When I met a new cloud service, I asked what operating systems idea it was built on. Queues, caches, locks, schedulers, file systems, virtual memory. Almost every managed service is an old idea with a pricing page attached.&lt;/p&gt;

&lt;p&gt;That rebuild is the reason I can debug a distributed system today. Not because I memorized more services. Because I stopped treating each one as a separate magic trick.&lt;/p&gt;

&lt;h2&gt;
  
  
  Back to my friend
&lt;/h2&gt;

&lt;p&gt;I should be fair to him. A cloud certification and an operating systems exam test different things. One rewards breadth and a clear head under a clock. The other rewards depth and patience with ugly details. Failing one by 4 marks and acing the other says very little about how good an engineer he will be.&lt;/p&gt;

&lt;p&gt;But it did make me see my own situation more clearly. I felt split. Half my week belonged to coursework that felt disconnected from my job, and the other half belonged to a job that felt disconnected from my coursework.&lt;/p&gt;

&lt;p&gt;Living in both worlds at once feels like a handicap. It runs like a double lab nobody else gets to use. The lecture hall is where you learn why things work. The terminal is where you learn what happens when they don't. If you only have one, you are guessing at the other.&lt;/p&gt;

&lt;p&gt;So if you are a student who also ships things, stop apologizing for the overlap. Open your old notes the next time something breaks at 2 AM. There is a decent chance the answer is already in there, written in a boring diagram you drew while half asleep.&lt;/p&gt;

&lt;p&gt;What is the strangest place a textbook idea has shown up in your production work?&lt;/p&gt;

</description>
      <category>cloud</category>
      <category>devops</category>
      <category>career</category>
      <category>beginners</category>
    </item>
    <item>
      <title>I got tired of fighting ffmpeg for basic video trimming, so I built clipflow</title>
      <dc:creator>Ronald Gosso</dc:creator>
      <pubDate>Wed, 07 Oct 2026 03:06:10 +0000</pubDate>
      <link>https://dev.to/ronaldgosso/i-got-tired-of-fighting-ffmpeg-for-basic-video-trimming-so-i-built-clipflow-4eb4</link>
      <guid>https://dev.to/ronaldgosso/i-got-tired-of-fighting-ffmpeg-for-basic-video-trimming-so-i-built-clipflow-4eb4</guid>
      <description>&lt;p&gt;I got tired of fighting &lt;code&gt;ffmpeg&lt;/code&gt; for basic video trimming. So I built &lt;code&gt;clipflow&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;You know the drill. You just want to trim a 10-minute video. &lt;/p&gt;

&lt;p&gt;You open a terminal and type:&lt;br&gt;
&lt;code&gt;ffmpeg -i input.mp4 -ss 00:30 -to 02:15 -c copy output.mp4&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;Then you pray you got the flags right. &lt;/p&gt;

&lt;p&gt;But wait, you need frame-accurate cutting. So you scrap &lt;code&gt;-c copy&lt;/code&gt;. Now you are re-encoding a 4 GB file. Twenty minutes later, you are still staring at a progress bar.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7u5n5izznoc4a08zgnp4.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F7u5n5izznoc4a08zgnp4.png" alt="R.I.P. to the 400MB node_modules folder" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I hit this wall for the fifteenth time last month. Honestly, enough was enough. I decided to build a better way.&lt;/p&gt;
&lt;h3&gt;
  
  
  What &lt;code&gt;clipflow&lt;/code&gt; actually does
&lt;/h3&gt;

&lt;p&gt;&lt;code&gt;clipflow&lt;/code&gt; is a typed Python API and CLI for video clipping. &lt;/p&gt;

&lt;p&gt;It manages &lt;code&gt;ffmpeg&lt;/code&gt; for you. It auto-downloads the binary on first use, caches it locally, and falls back to your system &lt;code&gt;PATH&lt;/code&gt; if you already have it installed. &lt;/p&gt;

&lt;p&gt;No manual setup. No "install ffmpeg first" warnings.&lt;/p&gt;

&lt;p&gt;Here is the core idea. It builds and runs &lt;code&gt;ffmpeg&lt;/code&gt; commands directly as subprocess calls. &lt;/p&gt;

&lt;p&gt;No NumPy array conversions. No memory-heavy frame processing. Just clean, typed dataclasses going in and structured results coming out.&lt;/p&gt;
&lt;h3&gt;
  
  
  Three things I obsessed over
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;Lossless stream-copy by default.&lt;/strong&gt; Trimming a 10 GB file takes seconds with zero quality loss. Need frame-accurate cuts? Just flip a &lt;code&gt;compress&lt;/code&gt; flag and it re-encodes properly.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Highlights as a first-class concept.&lt;/strong&gt; Most Python video libraries treat highlights as an afterthought. In &lt;code&gt;clipflow&lt;/code&gt;, you mark a clip with &lt;code&gt;highlight=True&lt;/code&gt;. It automatically copies that slice to a &lt;code&gt;highlights/&lt;/code&gt; directory. That is it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Zero runtime dependencies.&lt;/strong&gt; The library uses only the Python standard library plus the &lt;code&gt;ffmpeg&lt;/code&gt; binary it manages. No bloated dependency tree to debug.&lt;/li&gt;
&lt;/ol&gt;
&lt;h3&gt;
  
  
  Quick taste
&lt;/h3&gt;

&lt;p&gt;Here is what the Python API looks like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;clipflow&lt;/span&gt;
&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;clipflow&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;ClipSpec&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;parse_range&lt;/span&gt;

&lt;span class="n"&gt;results&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;clipflow&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;trim&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;raw_footage.mp4&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="nc"&gt;ClipSpec&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="nf"&gt;parse_range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;05:00&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;06:30&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
        &lt;span class="n"&gt;highlight&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="bp"&gt;True&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;compress&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;COMPRESS_HIGH&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;aspect_ratio&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;AR_9_16&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;label&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;hero_moment&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
    &lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="n"&gt;output_dir&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;&lt;span class="s"&gt;out&lt;/span&gt;&lt;span class="sh"&gt;"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="nf"&gt;print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;results&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="n"&gt;highlight_path&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="c1"&gt;# out/highlights/hero_moment.mp4
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And the CLI is just as straightforward:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Lossless trim&lt;/span&gt;
clipflow trim lecture.mp4 01:00-02:30

&lt;span class="c"&gt;# Compress + crop + highlight&lt;/span&gt;
clipflow trim concert.mp4 05:00-06:30 &lt;span class="nt"&gt;--compress&lt;/span&gt; high &lt;span class="nt"&gt;--aspect&lt;/span&gt; 9:16 &lt;span class="nt"&gt;--highlight&lt;/span&gt;

&lt;span class="c"&gt;# Inspect metadata&lt;/span&gt;
clipflow inspect documentary.mp4
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0coocq37wmwgsqbf6bag.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2F0coocq37wmwgsqbf6bag.png" alt="Scenario A: 20 minutes and 4GB of re-encode. Scenario B: 2 seconds, lossless." width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Why not just use &lt;code&gt;moviepy&lt;/code&gt; or &lt;code&gt;ffmpeg-python&lt;/code&gt;?
&lt;/h3&gt;

&lt;p&gt;Good question. I asked myself the same thing.&lt;/p&gt;

&lt;p&gt;Most Python video libraries convert frames to NumPy arrays. That is slow. It is memory-heavy. And it is completely unnecessary for simple trimming.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;clipflow&lt;/code&gt; does not touch a single frame. It just constructs the &lt;code&gt;ffmpeg&lt;/code&gt; command and runs it as a subprocess. &lt;/p&gt;

&lt;p&gt;The entire subprocess layer is isolated in &lt;code&gt;clipflow/_ffmpeg.py&lt;/code&gt;. You can audit exactly what is being executed. No magic.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqa1p9lnna9o726zkrm9f.png" class="article-body-image-wrapper"&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.us-east-2.amazonaws.com%2Fuploads%2Farticles%2Fqa1p9lnna9o726zkrm9f.png" alt="" width="800" height="446"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Under the hood
&lt;/h3&gt;

&lt;ol&gt;
&lt;li&gt;Pure Python (requires ≥ 3.9). No Swift or Rust wrappers.&lt;/li&gt;
&lt;li&gt;Cross-platform support for macOS 14+, Windows, and Linux.&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ffmpeg&lt;/code&gt; auto-downloaded and cached per platform.&lt;/li&gt;
&lt;li&gt;82 tests with &amp;gt;90% coverage.&lt;/li&gt;
&lt;li&gt;Docker-ready for instant local development.&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  What is next
&lt;/h3&gt;

&lt;p&gt;I am currently working on batch processing improvements and a highlight-reel example script. &lt;/p&gt;

&lt;p&gt;The repo is open and MIT licensed. &lt;/p&gt;

&lt;p&gt;If you have ever spent more time fighting &lt;code&gt;ffmpeg&lt;/code&gt; than actually editing video, give it a shot. And if something breaks, open an issue. I read every single one.&lt;/p&gt;

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

&lt;ol&gt;
&lt;li&gt;GitHub: &lt;a href="//github.com/ronaldgosso/clipflow"&gt;github.com/ronaldgosso/clipflow&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;Docker Hub: &lt;a href="https://hub.docker.com/r/ronaldgosso/clipflow" rel="noopener noreferrer"&gt;ronaldgosso/clipflow&lt;/a&gt;
&lt;/li&gt;
&lt;li&gt;PyPI: &lt;code&gt;pip install clipflow&lt;/code&gt;
&lt;/li&gt;
&lt;/ol&gt;

</description>
      <category>python</category>
      <category>showdev</category>
      <category>opensource</category>
      <category>ffmpeg</category>
    </item>
  </channel>
</rss>
