More from Vadim Kravcenko
Question: Answer: The post What I learned building a $1K MRR SaaS in 6 weeks appeared first on Vadim Kravcenko.
Question: Answer: The post Iām sorry appeared first on Vadim Kravcenko.
Question: Hey Vadim, So, I've been coding for money for about 5 years now. I've jumped around a lot ā Java, Javascript, Python, NodeJS ā you name it. The job market's been great, making it super easy for me to switch between gigs. I've done both full-time and contract work across many different companies. I think I've reached the level of being senior as I take on more and more responsibility. At every place I've been at, they seemed to love me. I always got the comments that I'm the best dev they'd ever had. But, personally, I've always felt a bit off. I'm good at bringing the team together and breaking down problems. Yet, there's always someone who can code better than me. They can whip up solutions way faster than I can. I get things quickly, but my code always seemed a bit messier. Now here is where it starts being interesting. I decided to switch jobs again, as Rust is the new fun kid of the block, I decided to switch things up by teaching myself Rust. Landed a job at a big-name brand recently, many thousands of engineers, and I'm feeling way out of my league. The devs here are on another level, I feel like everyone here is smarter than me, even the juniors are soo good, coming up with stuff I wouldn't even dream of. It's gotten to the point where I'm doubting if I'm cut out for this, especially having the title senior but not really being senior amongst my teammates. Makes me think of calling it quits. So, here's what my question is: How can I tell if I'm a good developer? Were my previous companies just bad? Now, I feel like I'm just not measuring up. Looking for some guidance or any advice you've got. Answer: The post How can you tell if youāre a good developer? appeared first on Vadim Kravcenko.
Question: Answer: The post Why software projects fail appeared first on Vadim Kravcenko.
Back when I was coding in 2007, my stack was straightforward. I had a shared hosting provider that cost me [ā¦] The post Infrastructure: From Zero to Enterprise appeared first on Vadim Kravcenko.
More in programming
I listen to a lot of podcasts, and I like how they fit around other tasks. IĀ press play, lock my phone, and put it down. Iām free to wash the dishes, fold the laundry, or shop for groceries. Unfortunately, more and more information is only published as a video. Technical talks, conference sessions, video essays ā they donāt work in an audio-only podcast app. IĀ could convert these videos to MP3 files, but that breaks down the moment a video isnāt pure spoken word. If a speaker says, āLook at this slideā or holds up a diagram, an audio-only file leaves me stranded. I donāt want to give up the podcast player I like, nor stare at a screen for an hour ā but I do want the information in these videos. To solve this, Iām abusing my podcast playerās chapter support. This gives me the best of both worlds: I can listen to a video as audio-first, and glance at my lock screen if I need a moment of visual context. The idea: Chapters every few seconds MP3 files can have ID3 metadata, and ID3 metadata can include chapters. AĀ chapter covers a particular time range, and it can have an associated title, description, and cover art. My podcast app of choice is Overcast, which canāt play videos, but it does have robust chapter support. IĀ can jump between chapters, navigate a table of contents, and see per-chapter cover art. To get videos into Overcast, Iām creating MP3 files with a new chapter every few seconds, and the per-chapter cover art is a corresponding frame from the video. As I play the file, I get a slow, stop-motion-like rendition of the original video. If my phone is locked, I can glance at my lock screen and see the current frame in the Now Playing screen. Overcast is developed by Marco Arment, and I got this idea from Forecast, his app for adding chapters to podcasts. In particular, I was struck by its ability to create chapters that donāt display in the chapter list ā ideal if I donāt want a table of contents with hundreds of entries. As I was developing my script, I compared my output to the output from Forecast to ensure I was creating the chapters correctly. The code: FFmpeg and Mutagen There are three steps in this process: Convert a video file to an MP3 Extract images from the video at a fixed interval Insert the images as hidden chapters in the MP3 file Letās go through each in turn. 1. Convert a video file to an MP3 Converting a video file to an MP3 is a single FFmpeg command: ffmpeg -i video.mp4 audio.mp3 This is consistently the slowest step of the process, and I do wonder if I could use different settings or an alternative encoder to make it go faster ā but itās not slow enough to be worth further investigation. 2. Extract images from the video at a fixed interval Extracting images from a video needs a more complicated FFmpeg command: ffmpeg -i video.mp4 \ -vf 'fps=1/5,scale=iw*sar:ih,scale=min(iw\,945):min(ih\,945):force_original_aspect_ratio=decrease' \ thumbnail_%04d.jpg This extracts an image every 5Ā seconds, downscales any image larger than 945Ā pixels square (while preserving the original aspect ratio), and saves the results as sequentially numbered JPEG images (thumbnail_0001.png, thumbnail_0002.png, and so on). The key is the -vf flag, which defines two FFmpeg filters: The fps filter selects one frame every 5Ā seconds (fps=1/5). The first scale filter scales the width based on the sample aspect ratio (scale=iw*sar:ih). Without this filter, frames can be stretched and distorted. The second scale filter scales the input video, preserving the original aspect ratio (force_original_aspect_ratio=decrease), and ensuring the output images fit within 945Ć945px or the size of the input video, whichever is smaller. My limit is 945Ā pixels because thatās the largest size that cover art is shown on my iPhone. This filter still isnāt completely correct ā it sometimes creates images from portrait videos that are smaller than Iām expecting ā but itās good enough. These are only thumbnails for glancing at, and if I want to change it later, I can always do the image resizing outside FFmpeg. 3. Insert the images as hidden chapters in the MP3 file Inserting the chapters into the MP3 file is more complicated. Although FFmpeg has basic support for ID3 metadata, as far as I know, it canāt insert chapters with per-chapter artwork. Instead, Iām going to reach for Python and the Mutagen library. Hereās the code to add a chapter to an MP3 file: from mutagen.id3 import APIC, CHAP, ID3, PictureType audio = ID3("audio.mp3") with open("thumbnail_0001.jpg", "rb") as f: img_data = f.read() image_frame = APIC(mime="image/jpeg", type=PictureType.OTHER, data=img_data) chapter_frame = CHAP( element_id="chp1", start_time=0, end_time=5 * 1000, sub_frames=[image_frame] ) audio.add(chapter_frame) audio.save() This creates a single chapter that lasts the first 5Ā seconds (0 to 5000Ā milliseconds), and the per-chapter cover art is thumbnail_0001.jpg. If we ran this in a loop, we could add images for every 5Ā second slice of the original video. This code is inserting two frames into the ID3 metadata: The CHAP (chapter) frame contains the timing information, and it can have subframes for metadata like title, chapter art, or associated URL. The APIC (attached picture) subframe contains information about a picture, which can either be a blob of image data or a URL to an image on the web. Normally, youād also insert a CTOC frame which defines a table of contents, but I donāt want a TOC with hundreds of 5-second chapters, so Iām deliberately not doing this here. This is allowed by the ID3 spec ā youāre not required to insert a CTOC frame if youāre using chapters, and you can have chapters that arenāt listed in your table of contents. To work out which frames I needed, I used Forecast to create some chapters by hand, and I inspected their frames. In particular, loading an MP3 and calling Mutagenās pprint() method shows a human-readable list of frames, and then I could drill into the individual fields: from mutagen.id3 import ID3 audio = ID3("audio.mp3") print(audio.pprint()) I wrapped all this code in a project called glancecast, which allows you to convert a video file with a single command, with optional flags to set the frame length and chapter art size: $ python3 glancecast.py interesting_talk.mp4 interesting_talk.mp3 The process takes a minute or so to complete, most of which is spent transcoding the video file to MP3. The resulting MP3s are usually 40 to 50 MB in size, which is very reasonable. The outcome: How it looks in practice Hereās what one of these āglanceableā podcasts looks like in Overcast and on my lock screen: Maggie Appleton presented this talk over two years ago and itās been on my ātalks to watchā list ever since. Once I put it in Overcast? I listened to it in less than a day. Itās not a lot of extra information, but enough that I can quickly glance down and get the gist of what a speaker is saying. Both views update with a new frame every few seconds, or I can put my phone in my pocket and ignore the screen. Iāve used this approach for half a dozen videos so far, and Iām happy with the results. IĀ expect to keep using it, because I have a long queue of videos Iāve been meaning to watch. If youād like to try this, check out glancecast for the full code and instructions. [If the formatting of this post looks odd in your feed reader, visit the original article]
Andrew Baker, the current Group CIO at Capitec Bank wrote an interesting piece on AI and open source, and how these tools that generate code according to oneās specification may replace the general reliance on open source implementations done by contributors around the world. Iād really recommend reading it. I have great admiration and respectContinue reading "AI Isnāt Replacing OpenĀ Source"
A framework for thinking about when AI involvement is additive or a violation
Why we need richer, thicker interfaces and better boundary objects for collaborative planning with agents
A look at 10 foundational pillars that enable agents to operate more competently and more efficiently in any codebase.