<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>More Than Technical</title>
	<atom:link href="https://www.morethantechnical.com/feed/" rel="self" type="application/rss+xml" />
	<link>https://www.morethantechnical.com</link>
	<description>Code, content, and more.</description>
	<lastBuildDate>Mon, 17 Feb 2025 17:20:10 +0000</lastBuildDate>
	<language>en-US</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.8.1</generator>
	<item>
		<title>No More Software Left to Write</title>
		<link>https://www.morethantechnical.com/blog/2025/02/17/no-more-software-left-to-write/</link>
		
		<dc:creator><![CDATA[Roy]]></dc:creator>
		<pubDate>Mon, 17 Feb 2025 17:19:37 +0000</pubDate>
				<category><![CDATA[machine learning]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[school]]></category>
		<category><![CDATA[work]]></category>
		<guid isPermaLink="false">https://www.morethantechnical.com/?p=2359</guid>

					<description><![CDATA[Commoditized to a pulp.]]></description>
										<content:encoded><![CDATA[
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p><strong>TLDR:</strong> Traditional software engineering is becoming commoditized. Infrastructure, deployment, and development have become incredibly easy thanks to modern tools and platforms. While this means utility software (business applications) will likely be automated away, there&#8217;s still room for creativity and personal impact. Even though most software has already been written or will be handled by AI, developers should focus on writing software that matters to them or makes a difference to others, rather than waiting for even better tools.</p>
</blockquote>



<p>The world of software engineering and development is changing at a breakneck pace. For someone who&#8217;s been in SWE for nearly 40 years (since I was 6 years old) and professionally for nearly 25 years (since I started getting paid for SWE work), I am concerned, but still hopeful.</p>



<p>What do I mean by &#8220;no more software left to write&#8221;? It means a few things:</p>



<ul class="wp-block-list">
<li>Software infrastructure has become so widely developed that writing new applications today &#8212; by hand, we&#8217;ll get to AI later &#8212; is 100x easier, faster, secure and optimized than just 5 years ago, and this rate of development is constant, meaning that in 5 years it would be 100x faster / easier / better than today.</li>



<li>The amount of software written has risen dramatically. Just the sheer volume of applications and projects has increased, and within those &#8211; open-source projects that are easily copiable or integrable. It&#8217;s nearly impossible today to find an alcove of human pursuit that has been untouched by software or digitization.</li>



<li>Software (and software engineering) has become as much like LEGO as it has ever been, where engineers (builders) can piece together an application in minutes! With advanced features and production-ready backends with just lines of code.</li>



<li>Software deployment has become automated to immense degrees, where an app (web, mobile, desktop) can be packaged and served online (or dished out as download executable) with a single line of terminal. All backend services, all testing and integrations fully managed by someone else.</li>



<li>AI coding has made it so full applications can be &#8220;written&#8221; ad-hoc to the user&#8217;s needs almost instantaneously, making the need for bespoke engineering obsolete &#8211; apps can be generated on the fly for a single use! The age of disposable food containers has arrived in software engineering.</li>



<li>Hardware platforms are more generous than ever before! With memory, compute and disk capabilities that really make runtime optimization a thing of the past. You can brute force your way to software success and deal with consequences later, if at all it will become an issue.</li>
</ul>



<p>All this means is that it has never been a better time to be a software engineer. And it has never been a worse time to <em>start </em>as a software engineer. If you&#8217;re starting out today, take note of the rate of change in the field &#8211; it is exponential. Tools and paradigms used today will be obsolete or woefully outdated in just 2-3 years. Except for the deepest of technologies, engineering applications has been commoditized to a pulp.</p>



<span id="more-2359"></span>



<h2 class="wp-block-heading">What it means for Utility and Creativity</h2>



<p>I think the days of software engineering for utility are numbered. Meaning, to build utility software that solves a business need is going to go extinct, very soon. Just because most business problems already have some software covering it, or &#8211; it will be embarrassingly easy to write the software with minimal time and effort. So, utility, I believe will not drive many engineers of the future. Creativity and gratification however &#8211; will remain in demand. These are the things that makes us human &#8212; just like eating and sleeping &#8212; and they will not change much in the next 1,000,000 years.</p>



<p>See, creativity is nothing like utility. It&#8217;s not things done to solve problems. Sometimes it&#8217;s a mental exercise, sometimes it doesn&#8217;t have any material purpose, it might be art, or it could be done as therapy even. I think creativity in software engineering will stay a vibrant theme. People will write innovative software for creative pursuits (like media, arts, gaming etc.) or solving problems in a creative way (like porting Doom to an electric toothbrush).</p>



<p>But all in all, the major usage for software in our world will be taken care of by the arguments made in the beginning. Software to solve actual business problems (but also e.g. games for mass consumption) will eventually be automated away not leaving much for humans.</p>



<h2 class="wp-block-heading">A Big Push on Infrastructure</h2>



<p>A major part of the &#8220;no software left to write&#8221; paradigm is infrastructure, and not necessarily automation or AI. In just a few short years, the tooling for developers to create and deploy scalable software has exploded upwards. App development and deployment has been commoditized, meaning, it is now commodity &#8211; anyone can get it for a fair price. Contributing companies were Firebase, Vercel, Supabase, Netlify, AWS Amplify. They won&#8217;t write your frontend &#8211; but the infrastructure is dead simple: db, auth, host, analytics, server-side, APIs &#8211; you got it. And the price you pay for this peace of mind &#8212; no one got fired for putting data in Google cloud &#8212; is ridiculously low. For anything sub immense scale it&#8217;s basically free (except if you&#8217;re building a business &#8211; you should be happy to pay! That means you&#8217;ve reached scale). Most of these are a one-stop-shop end-to-end solution for apps, you don&#8217;t need anything else. Even if you&#8217;re not web based, with Electron to do some serious desktop damage and Qt + PyInstaller as an alternative &#8211; desktop is not taboo anymore (cf. projects like LM Studio as a case in point).</p>



<p>That&#8217;s infrastructure. On frontend though, things went absolutely wild. I can&#8217;t remember an era where developers could be designers and designers could be developers. With frontend tools like React (of course), Tailwind, Shadcn, Bootstrap, Material, the task of putting up some components on screen and make them look great &#8212; or at least palatable &#8212; became trivial. You want dark mode? (You know you do.) It&#8217;s built in. I remember a distant past where software/tech companies developed &#8220;design systems&#8221; and &#8220;component libraries&#8221; and hired a big design team. This is a thing of the past. I can now see tailwind-shadcn everywhere, and for good reason &#8211; it&#8217;s all you ever need! Just pick colors out of a premade palette generator and theme your way to app design glory.</p>



<p>Right, so infra is solved, frontend is done &#8211; how about backend and middleware? Surely &#8211; backend is hard! Well guess again because middleware and backend smooth as silk like Next, Express, Nuxt and others &#8211; you really don&#8217;t have to sweat anymore, just focus on building.</p>



<p>I think in today&#8217;s world, even if you&#8217;re working by hand &#8212; you luddite &#8212; the apps write themselves!</p>



<h2 class="wp-block-heading">A World Full of One Man Shows</h2>



<p>I think it was inevitable that the world of software tech would eventually come to this. As you probably know, software engineers are &#8212; in broad strokes &#8212; the reclusive kind, sort of introverts, like to work alone and get things done pretending they are slaying dragons. Well back in the day a single developer couldn&#8217;t get anything done at scale even if they were insanely good. It was because things simply took time to do. Provisioning server operating systems (let alone install them physically!), bringing up db services, pouring over API docs for obscure identity directory services for auth (remember LDAP?), and worrying about replication and redundancy and load balancing&#8230; I&#8217;m glad to see all that is now in the past.</p>



<p>Today, a single good-enough developer can actually slay dragons. It&#8217;s because they get their work done so quickly, they have all the time they want to play Baldur&#8217;s Gate. Seriously though, one-dev shops are popping up like mushrooms after the rain, where the rain is the crazy push on infra that allows them to translate needs into apps in mere minutes, hours or days. Little startup companies can churn through ideas and pivots at breakneck speeds and look for PMF without overly risking their financials. This is a very good thing.</p>



<p>At the same time, software has forever been a collaborative effort. Some people make the infrastructure and some make the applications. That&#8217;s how it always has been, and largely how it still works today. The fundamental shift though is that value has gone from infrastructure to the application layer. In the past if you laid down &#8220;copper&#8221; (think any medium for information transfer) and &#8220;metal&#8221; (servers) &#8211; you had a &#8220;forever business&#8221; because you could not be uprooted. But information infrastructure has commoditized, and value shifted to applications where you can charge the customer directly. Government declared internet an essential service just like water and electricity. The same is happening to software infrastructure today. How long would it be before cloud services will be declared an essential service?</p>



<h2 class="wp-block-heading">Quantity Over Quality</h2>



<p>I&#8217;ve written in the past that I believe the next push in AI agents would be &#8220;brute force&#8221;. A situation where you can have 1,000 weak competing agents on the same task, and all it takes is for one of them to succeed. Note this is different than &#8220;swarms&#8221; where each agent has a separate distinct job they must perform well on. What I suggest is that cheap agents with low probability of success will compete, but we will beat low probability with sheer numbers.</p>



<p>At the heart of &#8220;Quantity Over Quality&#8221; stands this principle: low probability can be beaten by repeated trials. The startups above with low probability of hitting PMF can now try 10-20 or even 50 separate ideas before running out of money. The AI coding agent[s] can try 100s of solutions for solving a bug &#8212; in parallel! &#8212; until something hits all the unit tests.</p>



<p>Think of software for doing the same thing in principle. We probably have in our world 100s of &#8220;versions&#8221; of Salesforce &#8212; primarily a CRM and ERP tool once geared towards sales but now has metastasized to every part of an organization. Everyone is trying to replicate the immense success. This is &#8220;brute force software&#8221; &#8211; low probability, multiple trials. And this experiment is repeated in pretty much every software you know! Like, WordPress (which I&#8217;m using for this blog), Windows, Google Docs, VS Code, Slack, Chrome, etc. each have 10s or 100s of viable alternatives.</p>



<h2 class="wp-block-heading">Software Worth Writing</h2>



<p>So what&#8217;s left for us lifetime software engineers? Everything has been done before 100s of times over, and the things not yet done will be made by swarms of swarms of competing AI agents. Is it even worth opening up the IDE today? Because, if we just wait a bit &#8211; software will be x1000 easier to write very soon, so why bother today? This is a principle called &#8220;The Waiting Calculation&#8221; or the &#8220;<a href="https://en.wikipedia.org/wiki/Wait/walk_dilemma">Wait/Walk Dilemma</a>&#8220;, where it&#8217;s better to wait for the bus and go faster than to walk slowly.</p>



<p>I however think it&#8217;s much better to be active today than to wait. By acting you influence the future and shape the technologies. It may seem like the efforts of one person may be negligible in face of a global movement &#8211; but that is untrue. We are all part of a tight fabric, and we all pull and push on the people around us. We have colleagues, students, mentors, family and friends, and strangers too that we may meet online. We influence them, and they influence us. Overall, we are all grabbing a tiny little part of the helm of the humanity ship.</p>



<p>Today you should be writing software worth writing. In other words, write for impact &#8211; personal or societal. Replicating a social network just to learn how it works? Great project! Definitely worth writing. A script for cropping images by right click on the file? Wonderful idea! Anything that makes an impact on your life or others is worth writing, even today and in the future.</p>



<p>So while there&#8217;s no more software left to write, you &#8212; personally &#8212; definitely have plenty of more software worth writing.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>What it Takes to Succeed, Today</title>
		<link>https://www.morethantechnical.com/blog/2025/01/30/what-it-takes-to-succeed-today/</link>
		
		<dc:creator><![CDATA[Roy]]></dc:creator>
		<pubDate>Thu, 30 Jan 2025 19:42:46 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://www.morethantechnical.com/?p=2356</guid>

					<description><![CDATA[TLDR: The tech industry is becoming a winner-takes-all arena. Traditional paths are dying, AI is eating entry-level jobs, and you have about 5-10 years to get rich or get replaced. Stop preparing, start taking. &#8220;In tomorrow&#8217;s tech world, you&#8217;re either the one building the AI, or the one being replaced by it.&#8221; Let&#8217;s cut straight [&#8230;]]]></description>
										<content:encoded><![CDATA[
<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>TLDR: The tech industry is becoming a winner-takes-all arena. Traditional paths are dying, AI is eating entry-level jobs, and you have about 5-10 years to get rich or get replaced. Stop preparing, start taking.</p>
</blockquote>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow">
<p>&#8220;In tomorrow&#8217;s tech world, you&#8217;re either the one building the AI, or the one being replaced by it.&#8221;</p>
</blockquote>



<p>Let&#8217;s cut straight to the chase: the odds are stacking up against junior folks trying to break into tech today:</p>



<ul class="wp-block-list">
<li>Mass layoffs have frozen hiring across the industry, with even tech giants slashing thousands of positions monthly</li>



<li>AI and automation are breathing down our necks, replacing entry-level positions at an alarming rate</li>



<li>Hiring managers have become numb to &#8220;average&#8221; achievements after seeing thousands of identical bootcamp projects</li>



<li>Global talent pools have exploded with remote work and immigration, turning local competitions into worldwide battles</li>
</ul>



<p>The tech landscape isn&#8217;t just harder – it&#8217;s transformed entirely. The bar for junior engineers and career switchers isn&#8217;t just higher; it&#8217;s in the stratosphere. We&#8217;re talking about a fundamental shift in what it means to be &#8220;qualified&#8221; for a tech role.</p>



<p>Is this a bad thing? On the grand scheme, probably not. It&#8217;s forcing people to be more driven, more motivated, more dedicated to succeed. The days of skating by on a basic CS degree are dead and buried. But let&#8217;s be real: not everyone with a CS degree is landing that $300K/year cash position at FAANG (e.g. Facebook, Google, Amazon, Microsoft, Apple, etc.). In fact, the vast majority have zero shot at such roles straight out of school. And I&#8217;m not talking about a small majority – we&#8217;re looking at 95%+ of graduates who won&#8217;t even get past the resume screen.</p>



<p>People ask me for advice on how to get ahead of these curves. Here&#8217;s the unvarnished truth, and fair warning – you&#8217;re going to dislike it.</p>



<span id="more-2356"></span>



<h2 class="wp-block-heading">The De-Sensitivity Crisis</h2>



<p>Hiring managers and recruiters are drowning in a sea of &#8220;qualified&#8221; candidates. Making an impression isn&#8217;t just harder – it&#8217;s nearly impossible without something extraordinary. The problem isn&#8217;t just volume; it&#8217;s that everyone looks the same on paper. Another TODO app? Delete. Another machine learning project that classifies cat pictures? Straight to the trash. Another blockchain wallet? Please.</p>



<p>But what does &#8220;making an impression&#8221; actually mean for an engineer? This distinction is crucial, and most candidates get it completely wrong.</p>



<p>To be impressive, you need something that&#8217;s <em>undeniably </em>yours. Not group work, not team achievements – something personal that you can claim 100% credit for. No &#8220;I was part of the team that&#8230;&#8221; or &#8220;I contributed to&#8230;&#8221; statements. Here&#8217;s what counts:</p>



<ul class="wp-block-list">
<li>Open-source projects with serious traction (we&#8217;re talking hundreds, preferably thousands of stars and million+ downloads). Your weekend project with 5 stars from your bootcamp buddies? Not even close.</li>



<li>First-author papers in top-tier venues (at least one for MS, four+ for PhD, plus 2-3 / 4-5 supporting papers equally). And no, your university&#8217;s research journal doesn&#8217;t count.</li>



<li>Patents or awards from major federal programs or national institutions (your name, front and center). The local hackathon prize won&#8217;t cut it anymore.</li>



<li>Massive social following (tens of thousands of followers minimum, millions of engagement marks). And we&#8217;re talking about real engagement, not bot farms or engagement pods.</li>



<li>Money. Numbers. If you can say you&#8217;ve personally been able to clock millions of $$$ in revenue to your company and be able to show it &#8211; that&#8217;s all it takes.</li>
</ul>



<p>Anything less? Hiring managers won&#8217;t even blink. They&#8217;ve seen it all.</p>



<h2 class="wp-block-heading">The Path to These Achievements</h2>



<p>Let&#8217;s be brutally honest: you need to borrow, hustle, and fight for every opportunity. And when I say fight, I mean it literally – you&#8217;re in a gladiator arena where only the most aggressive survive. Mostly because the other gladiators are faceless, nameless ghosts that just want to feast on your human brain.</p>



<h3 class="wp-block-heading">Publications</h3>



<p>Want papers? Muscle your way into top labs. Offer to work nights and weekends. Do the grunt work – data cleaning, figure creation, statistical analysis. Start as the fourth author and claw your way up. Be relentless. Take rejection as a challenge, not a stop sign. I&#8217;ve seen successful candidates camp outside professors&#8217; offices, volunteer for the worst tasks, and work 80-hour weeks just to get their name on a paper. That&#8217;s your competition.</p>



<h3 class="wp-block-heading">Projects</h3>



<p>Building something great isn&#8217;t enough – you need to be a marketing machine. Spend as much time promoting as coding. Give away value, but make it count. Target audiences beyond the US if needed. Learn SEO, social media algorithms, and growth hacking. Every star, every download, every GitHub fork is a battle you need to win.</p>



<p>And here&#8217;s the controversial take: don&#8217;t dilute your success with contributors. This is your spotlight – own it. I&#8217;ve seen too many promising projects die because their creators were too nice, too willing to share credit. In 2025&#8217;s tech landscape, being nice is a luxury you can&#8217;t afford.</p>



<h3 class="wp-block-heading">Awards</h3>



<p>Unless you&#8217;re that one-in-a-million genius (newsflash: you&#8217;re probably not, just like 99.99999% of us), you&#8217;re competing on pure grit. Even with talent, you&#8217;ll need insane work ethic. I&#8217;m talking about the kind of dedication that makes your friends think you&#8217;ve lost your mind.</p>



<p>Awards are lottery tickets, but you can read the odds. If your gut says you don&#8217;t have a shot, move on fast. Time is your most precious resource, and you can&#8217;t waste it on long-shot bets. I&#8217;ve seen candidates spend years chasing the wrong awards, only to end up with nothing to show for it.</p>



<h3 class="wp-block-heading">Social Following</h3>



<p>If you haven&#8217;t started building your platform 6-8 years ago, you&#8217;re already behind. Way behind. Today&#8217;s tech influencers didn&#8217;t just appear overnight – they&#8217;ve been grinding for years, building their presence post by post, tweet by tweet.</p>



<p>But here&#8217;s the silver lining: those other achievements (projects, awards, papers) can catapult your social presence. Just keep it organic – people smell fake engagement from miles away. And remember, in tech, your social media presence is becoming as important as your GitHub profile. Companies want engineers who can be advocates, who can attract talent, who can represent the brand.</p>



<h2 class="wp-block-heading">A Glimmer of Hope (For Now)</h2>



<p>These barriers seem impossible? They are. That&#8217;s the point. Breaking through them – that&#8217;s what makes it impressive.</p>



<p>But there&#8217;s still the traditional path: Start with a decent (not spectacular) internship, grind out 2-3 years learning big tech&#8217;s playbook (frameworks, tools, workplace politics), then make your move upward. This route probably has 6-10 years left before AI closes it for engineers, especially in software. But the window is closing fast, and the competition is getting fiercer by the day.</p>



<p>Consider this: In pre-ChatGPT 2020s, a decent post-grad internship at FAANG might have required a 3.5 GPA and some school project experience. Today? Companies are expecting interns to have contributed to open source, built full-stack applications, published work, and mastery of multiple tech stacks before they even start.</p>



<p>Your advantage? You&#8217;re reading this now. You&#8217;re aware. You&#8217;re planning. This window of opportunity won&#8217;t stay open forever. If you&#8217;re taking the traditional route, start yesterday. Actually, start last year.</p>



<h2 class="wp-block-heading">The Next Phase (10 Years Out)</h2>



<p>In five years, AI will be crushing engineering roles. Jobs will exist, but only for 10-100x engineers with deep AI milage. Everyone else? Automated into obsolescence. Today&#8217;s frameworks already provide so much boilerplate that even basic LLMs can piece together solutions. Tomorrow&#8217;s frameworks? They&#8217;ll make today&#8217;s automation look like stone tools.</p>



<p>Here&#8217;s how it plays out: Today, if an LLM agent tackles a complex programming task (reading 100,000 lines, writing 10,000 lines) at $1, with a 1% success rate, that&#8217;s $100 per solution. In five years? That same solution costs a penny. Organizations will unleash hundreds of thousands of agents, throwing thousands at each task. When 999 fail but one succeeds – at that cost – humans become optional.</p>



<p>Think about that for a minute. When the cost of failure approaches zero, brute force becomes a viable strategy. Why hire a human who might take a week to solve a problem when you can launch 10,000 AI attempts and get your solution in minutes?</p>



<p>And ten years out? Software development as we know it dies. Need software? An agent fashions it instantly, more like searching a vast directory than building from scratch. The entire concept of &#8220;software engineering&#8221; becomes as relevant as &#8220;horse-and-buggy maintenance.&#8221;</p>



<p>The signs are already here. Look at the tools released in just the last six months. They&#8217;re not just helping developers – they&#8217;re replacing them. Every new LLM release makes more junior dev tasks obsolete. The trend isn&#8217;t slowing; it&#8217;s accelerating.</p>



<h2 class="wp-block-heading">How to Prepare</h2>



<p>Don&#8217;t.</p>



<p>Instead, get rich as fast as you can. Look around – solo entrepreneurs are already building AI-powered empires. They see the writing on the wall: individualism (and tribalism) is back. Be self-reliant. Pay yourself first. Don&#8217;t share the spotlight. Be ruthless about your goals.</p>



<p>The era of the comfortable, steady tech career is <em>ending</em>. What&#8217;s replacing it? A winner-takes-all gladiator arena where only the most aggressive, most adaptable, and most ruthless survive. You&#8217;re either building the AI tools, or you&#8217;re being replaced by them.</p>



<p>Your time starts now. Every day you spend not building your empire is a day your competition is getting ahead. Every minute you waste trying to &#8220;prepare&#8221; for the future is a minute someone else is spending taking what could have been yours.</p>



<p>Good luck. You&#8217;re going to need it.</p>



<p>And if you think this sounds harsh or unfair? Welcome to tech in 2025. It only gets harder from here.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>How to Love Coding</title>
		<link>https://www.morethantechnical.com/blog/2024/09/20/how-to-love-coding/</link>
		
		<dc:creator><![CDATA[Roy]]></dc:creator>
		<pubDate>Fri, 20 Sep 2024 14:20:13 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://www.morethantechnical.com/?p=2334</guid>

					<description><![CDATA[Advice for Coders starting out I&#8217;ve been writing code for the past 36 years. That&#8217;s a lot of code. Started at 6 years old, writing BASIC on an Apple IIe that my dad brought home. Then graduated to PASCAL, Visual BASIC, MS-DOS Batch and then Borland C and Java, moved to C++, Objective-C some C# [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p><strong>Advice for Coders starting out</strong></p>



<p>I&#8217;ve been writing code for the past 36 years. That&#8217;s a lot of code. Started at 6 years old, writing BASIC on an Apple IIe that my dad brought home. Then graduated to PASCAL, Visual BASIC, MS-DOS Batch and then Borland C and Java, moved to C++, Objective-C some C# and JavaScript, Python obviously, recently TypeScript, all the while learning the secrets of Bash, ZSH and PowerShell and other more obscure languages like Go, Rust and even Elixir, LISP and Lua. I&#8217;m probably forgetting many languages and coding &#8220;situations&#8221; I went through like MSSQL/TSQL/PLSQL and HTML, CSS of their kind and several other task-specific code-ish things. This is just to explain and show to you, junior coder, that coding (for real) is a lifetime pursuit. Just like my journey, you will hear similar things from just about any other lifetime programmer that you know.</p>



<figure class="wp-block-audio"><audio controls src="https://www.morethantechnical.com/wp-content/uploads/2024/09/love-coding.mp3"></audio></figure>



<span id="more-2334"></span>



<p>See, coding is in my blood. I may claim that I had no choice but to become a coder, seeing as my dad, a control systems engineer by training and programmer by trade, has brought coding home to me, my older sister and younger brother at a very early age. My dad was programming AS-400 IBM mainframes in RPG to build the backend software for banks, insurance and logistics companies. As young kids we learned about algorithms, data structures, databases and user interface &#8211; in an unstructured way, an exploratory way, and as apprentices. Back in the 1980s software had very scarce mediums for sharing, so it often was shared in books! Big bulky book full of code. And my dad set us up to copy lines from to book into the computer to build a game or a graphical software. I was amazed and hooked from the very beginning. But that was a very special circumstance. Code and coding have transformed so much I sometimes can&#8217;t even recognize it, but for me it will always remain: a thrill of creation and exploration, a dialogue, a way to communicate thoughts.</p>



<p>In this article I would like to dispense some advice on writing code. But not in way of design patterns or efficiency. I&#8217;d like to tell you about the personal side of writing code, and what it can do emotionally, about what it means to be a &#8220;Coder&#8221;. At the same time, it is a very pragmatic guide, just as much as it is personal. As usual, take all of this with plenty a grain of salt.</p>



<h4 class="wp-block-heading">How to Love Crafting Code</h4>



<p>The above introduction goes to show that for me coding is a passion. In fact, I would say coding is my love. I love coding. I do it every day, for years and years and more years, and I hope to be coding for many decades more. When I&#8217;m not coding, I think about coding. I would do it every day given the chance. I also love very much the mental struggle and difficult puzzles that coding poses. It might seem unfair. Many tell me that coding comes easy to me but let me say that no code ever came easy to me. I heard a quote from Henry Rollins recently that goes roughly like: <em>&#8220;I&#8217;m not as talented or smart as others, so I just get up early and stay up late every day&#8221;</em>. This is basically it. Coding is hard, always, even to experienced coders. But it&#8217;s precisely because it is hard it is appealing to so many people.</p>



<p>A friend recently asked me how long it would take to code something. I answered: &#8220;There&#8217;s no such thing as &#8216;Coding time&#8217; per se, it&#8217;s just how long you sit in front of a keyboard banging your head against it until the thing is done.&#8221; This is the sad truth about coding, is that it&#8217;s simply hard and takes a long time to make a really nice thing. We will discuss AI coding shortly, but nothing would replace careful, measured steps, incremental advancement over a long period of time. Demos and one offs, simple one-file programs or scripts, new projects and boilerplates &#8211; all are not real examples of what a programmer would do on a daily basis. Coding a robust long-lasting module or package just takes time.</p>



<p>Coding is a craft. Just like woodworking or cooking. It relies heavily on past knowledge, drawing parallels from other projects, habits, rules of thumb with a dash of curiosity and trying something new. See, no code is truly similar to any other, it&#8217;s always a continuation of something. Remember the memes about programmers only needing 3 keys on their keyboard? Stack Overflow, Ctrl-C and Ctrl-V. This cannot be more wrong. Every empty file about to be filled with code is like a clear canvas, to which you take a big brush. First you work in broad strokes! Throwing big blotches of paint, just covering empty areas, making a scene, a background, for your finer work later on. After the canvas is full but really doesn&#8217;t look like anything, you take the smaller brushes, start filling in the little details, make smaller adjustments. Finally, you test your work. Take a few steps back, stare at it for a bit, raise an eyebrow. Find a bug here and there, just getting a feel of your creation, learning it, seeing it, connecting with it.</p>



<p>Coding is so much like painting, sketching, sculpting, or writing than you&#8217;d imagine. That&#8217;s why I believe that myself and others are so in love with coding. Not because we like code! In fact, if I&#8217;m being honest, I kind of dislike code. Code really is a way to describe your thoughts to the computer, it&#8217;s a medium that shouldn&#8217;t exist. But cod<strong><em>ing</em></strong> &#8211; oh boy, that is just wonderful. There is joy in coding. That&#8217;s why I fail to understand how come everyone is so eager to get rid of it. &#8220;No-code Platforms&#8221; or &#8220;AI will make all programmers obsolete&#8221;. That really is beside the point. People love coding because it&#8217;s a craft, an art, an expressive medium. This is the reason you will find folks in their 60s and even 70s still coding. It&#8217;s just fun!</p>



<h4 class="wp-block-heading">How to Love Coding for Work</h4>



<p>Ok coding is art and it&#8217;s a lot of fun, we get it. But doing it for 9-10 hours of the day for someone else? that&#8217;s recipe for &#8220;hobby burnout&#8221;. You will get sick of doing anything you love doing if you do it too much or for the wrong reasons. So, we must all find a way to still enjoy coding if it&#8217;s our job. Insofar as we like getting paid to support our lives and families.</p>



<p>Coding for work doesn&#8217;t have to be so bad though. As I stated above, I would be perfectly happy coding 10 hours a day. So, really the problem is in the motivation. If you&#8217;re working on a passion project, you&#8217;re probably highly motivated. If not for seeing it complete then probably for the skills you&#8217;re gaining, the community around it, or maybe it&#8217;s impact on others or even yourself. See &#8211; all the reasons are there! Treat your work coding time as a chance to enhance your skills, see the impact of your work on others, or find ways to communicate your work. Without you knowing, you&#8217;re already doing this. Every hour spent coding you&#8217;re getting better, more experienced. This however isn&#8217;t a recipe to avoid burnout. Burnout is likely inevitable. </p>



<p>There&#8217;s possibly nothing worse than being handed code that someone else wrote and being asked to &#8220;make it better&#8221; or add a dull feature or refactor it. This regularly happens at work, particularly for juniors. People would likely tell you how it&#8217;s actually a good thing: &#8220;Learn our codebase through your fingers&#8221; they will say. Frankly, I don&#8217;t buy that. As I said, I love coding, but I dislike code. In these situations, which you can&#8217;t always avoid, I suggest making the most of it. If you take the time to read and understand the code, take an equal amount of time to document it. Make diagrams etc. First, I think your supervisor would instantly have a whole new level of admiration for you (who doesn&#8217;t like documentation?), but second, this can factually be good for you. Any ancillary output beside code, for a programmer, is really a rare sight. Programmers like the coding part see, they usually don&#8217;t like the extras. If you&#8217;re an &#8220;extra&#8221; kind of coder &#8211; that increases your value and makes you a candidate for promotion.</p>



<p>To recap, I&#8217;m not suggesting coding for work is going to always (or even sometimes) be as fun and exhilarating as working on your own passion projects. But if you focus on your personal goals &#8211; it can just bearable enough to keep you satisfied for a long while. Look for the opportunity to get better and go farther.</p>



<h4 class="wp-block-heading">How to Love AI Coding</h4>



<p>AI coding is a game changer. Personally, I really enjoy it. Many times, I go &#8220;oh my this totally just read my mind&#8221; and have moments of awe. There are things AI coding or a copilot does absolutely amazingly well. There are also things it does terribly wrong. But for better or worse this is the future. I have no doubt. If you&#8217;re not using AI to program in 2024, I&#8217;m sorry friend you&#8217;re in the wrong field of work.</p>



<p>One thing to get out of the way right away is that using AI assistants for coding really doesn&#8217;t take much of anything out of the joy of coding. If anything, I love how the AI does the boring stuff for me, and I can stay in the flow longer. It&#8217;s still a paintbrush, but a bigger one that has tiny little paintbrushes on it, so you still make broad strokes, but they also fill in the tiny details at the same time.</p>



<p>The key I found for being successful with AI coding is to deliver your intent. If you&#8217;re writing a new function and want that filled in &#8211; start with a descriptive comment, if the AI still doesn&#8217;t make a good suggestion, start writing the signature of the function using meaningful names. For example,</p>



<pre class="wp-block-code"><code>// This function takes in two numbers and returns the largest
// common denominator.
int largest_common_denominator(</code></pre>



<p>This really should be enough for any AI assistant to complete the rest. Most likely the AI would not even let you finish the comment before it gives a suggestion. Another thing is to get to the point as soon as possible with the least verbiage, for example:</p>



<pre class="wp-block-code"><code>// Calculate the largest common denominator from</code></pre>



<p>At this point the AI will probably already give you a valid suggestion.</p>



<p>One more thing about AI coding. There&#8217;s a trending word out there that programmers would be out of a job because of AI coding getting too good. While that might be true someday, this must not deter you from learning how to enjoy coding today. Coding is more than making computers do things, it&#8217;s a mental exercise, a puzzle, a craft, an artistic medium of expression. Do it because you love it, or I suggest, in interest of time, you go do something else. There are plenty of professions that AI will not touch any time soon if that&#8217;s what you&#8217;re worried about. Folks that use AI to write all their software for them and simply copy-and-paste verbatim &#8211; are not getting any joy from it. For them, I&#8217;m actually very glad that AI can spare their time and misery in writing code. AI coding is much better for a person that enjoys coding, than it is for someone who doesn&#8217;t.</p>



<hr class="wp-block-separator has-alpha-channel-opacity"/>



<p>Some departing words. Coding is a lot of different things for different people. It&#8217;s an art, a craft, a job, a necessary evil, a struggle, a means of providing, a collaboration, a community, a joyful thing. Every coder will tell you another story. But at the basis of all you will find that insofar as coding is an intermediary between machines and humans, it&#8217;s always about humans. If machines knew how to program themselves to do exactly what we humans need without any interface &#8211; then coding won&#8217;t exist. Some people believe in that future. I don&#8217;t.</p>



<p>Love coding, and it will love you back.</p>
]]></content:encoded>
					
		
		<enclosure url="https://www.morethantechnical.com/wp-content/uploads/2024/09/love-coding.mp3" length="10596186" type="audio/mpeg" />

			</item>
		<item>
		<title>How to be an Employee</title>
		<link>https://www.morethantechnical.com/blog/2024/05/20/how-to-be-an-employee/</link>
		
		<dc:creator><![CDATA[Roy]]></dc:creator>
		<pubDate>Mon, 20 May 2024 14:18:49 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://www.morethantechnical.com/?p=2325</guid>

					<description><![CDATA[Advice for People Joining the Workforce Working in the service of something bigger than yourself is a pillar of humanity. It enabled all riches and privileges we have in our world. It is how people have built society for eons. There&#8217;s no doubt today that being employed keeps you balanced, satiated and healthy (in a [&#8230;]]]></description>
										<content:encoded><![CDATA[
<h5 class="wp-block-heading">Advice for People Joining the Workforce</h5>



<p>Working in the service of something bigger than yourself is a pillar of humanity. It enabled all riches and privileges we have in our world. It is how people have built society for eons. There&#8217;s no doubt today that being employed keeps you balanced, satiated and healthy (in a way). It&#8217;s the best tool to support yourself and others. But at the same time, it takes away many of your freedoms. Before we dive in, let&#8217;s set a few things straight.</p>



<figure class="wp-block-audio"><audio controls src="https://www.morethantechnical.com/wp-content/uploads/2024/05/how-to-be-an-employee.mp3"></audio></figure>



<p>At the core of employment stands a simple principle: <em>An employer is hiring you for value you bring to the business which is less than the compensation they pay you</em>. Get it? At the core of employment, the principle is that <em>someone is getting bigger value from your work than what they pay you</em>. No business ever, if it&#8217;s a well-functioning business driven by real metrics, will pay you more than the value you bring &#8211; otherwise they will either hire someone else for less or not hire at all. If you ever own a small business, you will learn this simple principle very quickly. No <em>business</em> is charity.</p>



<span id="more-2325"></span>



<p>The next principle is that <em>as an employee you are first &#8211; a function</em>. You&#8217;re not a person first, you&#8217;re not the sum of your goals and aspirations, you&#8217;re not your knowledge and expertise. As an employee, you are filling a role, driving value in a specific vector. If you are more than that in an organization, well you&#8217;re no longer and employee and more of an owner. All employers will try to convince your otherwise, but at the core &#8211; they first need you to perform a role, a task.</p>



<p>Finally, as an employee you are part of a whole. You&#8217;re not an individual maximizing your own gain. When you sign up you promise to maximize the gains of the organization. There is comfort in knowing that everyone around you is exactly the same &#8211; they are pulling the cart just like you.</p>



<p>Understand, the above principles are not bad or malicious. They are in fact wonderful and unlocked the greatest innovation and prosperity for all of humanity. Because of these gaps in gains, everyone is in effect donating a portion of their efforts to a greater good. It is often misappropriated, but on the grand scheme of things &#8211; it is perfectly great.</p>



<p>Being an employee will teach you a whole lot. About your business domain, about people (peers, customers) and how they think and operate, about impossible decisions, about things done at immense scale, about yourself as you stack up vs. others, and about life itself. The key in making the most from employment is to capture these teachings.</p>



<p>Here is some advice I have for you as you&#8217;re joining the workforce.</p>



<h3 class="wp-block-heading">How to be a Bad Employee</h3>



<p>Don&#8217;t be a bad employee. If you&#8217;ve joined a place of work, put in the time and effort to be successful. When I say &#8220;bad employee&#8221; I mean &#8211; understand the principles above, repeat them to yourself every day and on all occasions. And then, think for yourself. What kind of engagements are you looking to have in your personal life? What are your personal goals and metrics of success? Just put yourself first.</p>



<p>To me, being a bad employee is leveling the playing field. Employers will take endlessly but only pay you up the value equilibrium point &#8211; the point where you are paid as much money as your employer values your work. As such, you&#8217;re in a rigged system. You will never (unless by trickery or felony) be able to get paid more than you&#8217;re valued. Again, this is not all bad and most people in the world are better off on one side of this equation.</p>



<p>My advice for being &#8220;bad&#8221; is to make sure you are always on the right side of the equilibrium, not by cheating and slacking off, but by making the pie bigger. You can always, always! generate more value for <em>yourself</em> than your employer values you. Sure, you can take a second job (moonlighting, &#8220;side hustle&#8221;), but you&#8217;re at risk of double-dipping on the time from your main job, which would be borderline morally wrong. Many people do it, more than you&#8217;d think, and they glorify it. What I advise is to look for values in a different place than your time. Here&#8217;s the principle:</p>



<p class="has-larger-font-size">1+1=3.</p>



<p>Keep that in mind. 1+1=3 is your goal for employment. Always generate more value from one single thing that you do, really squeeze it out. Prepared a report to your supervisor? Also prepare a documentation of how you made the report, or how you would automate it. Wrote a piece of code? Also note down and share (!!) how you did it and what should be done next. Made a presentation for a meeting? Deliver the same presentation again in a different setting. Had a meeting with someone high ranking in the company? Write about your impressions from the meeting and your personal take on things. You were promoted to a leading role? Write a guide for all of things you learned, share it religiously, make sure people know why you were selected, and they will have a lasting impression of you that will last your career! There&#8217;s a big group meeting? Ask your boss for a chance to present work you have already done.</p>



<p>Be a bad employee. Generate more value <em>for yourself</em> than your employer needs or hired you for. Paradoxically, this is the best way to advance up the chain at work! Truly, a remarkable thing. If you maximize your personal gain at work by generating more value like discussed above, and the organization will value you more. When you think about it, it makes all the sense, since the organization is hiring you based on how you are valued in the market. Make yourself be worth more. Always grow your skillset, preferably &#8211; laterally, and always grow your network inside and out of your workplace.</p>



<h3 class="wp-block-heading">How to be a Good Employee</h3>



<p>As a junior employee, my advice for the first few years is to just keep your eyes and ears open when you join a new place. <em>Look for inefficiency</em>. Organizations, and particularly management, are obsessed with inefficiency. Because of laws of diminishing returns, all orgs that get bigger become inefficient and efficiency is a battle at any workplace.</p>



<p>Attended a meeting and you were bored for half the time? That&#8217;s inefficiency that you should share and publicize. The next meeting should be half the time, and if you&#8217;re lucky &#8211; you will never attend it at all! Had to make presentation from a bunch of data on various systems and that took you forever? Perfect inefficiency &#8211; let the people in charge of data systems know. You have to take 3 authentication steps or keycard scans to get to your desk? That&#8217;s eating up your efficiency for performing your tasks.</p>



<p>The key here is to verbalize. Never suffer alone. Either commiserate or communicate, preferably to your supervisor but group meetings are great too. Every workplace has tons of points for improvement, and is looking for them, but most people around you either don&#8217;t care or don&#8217;t mind because they are &#8220;getting paid for their time either way&#8221;. Don&#8217;t be like that, be a good employee. Speak up. But don&#8217;t be overbearing or make it all about complaining. Do it from a place of caring. Your goal is to improve conditions for everyone, not just yourself.</p>



<p>The are many ways you can be a good employee, and many guides for it. But the core of all of these things is singular: Generate as much value to the organization as possible. Either you lift other employees up, or optimize operations (save the org money), or through working more efficiently yourself, or by finding new value so far undetected (make the org more money).</p>



<h3 class="wp-block-heading">How not to be an Employee</h3>



<p>For once in your career, my advice is to try very hard not to be an employee and strike off on your own. This is the ultimate test of your skills and stamina as a professional. Being independent is hardest professional move, and definitely not for everyone. But I guarantee that at one point in your career you will feel that you must give it a shot. I&#8217;m going to exclude starting a company and focus on self-employment, since by starting a company, you are in fact an employee again.</p>



<p>Self-employment is the toughest thing. Do not attempt it before you have a lot of prestige and credentials in your domain. Finding customers, and holding them, is mostly a matter of marketing your skills and value you can bring. If that hasn&#8217;t been substantiated &#8211; you&#8217;re at risk. Remember, someone will only pay you up to the value that you can provide, and since you will now be charging a premium on your services &#8211; that value needs to be equally bigger. Getting to a position where self-employment makes financial sense usually takes years. At first you could only charge roughly as much as you can in your 9-5 job, after taxes you&#8217;d be taking home ~50% of the salary you used to make. It&#8217;s only when you can comfortably charge x2-x3 your salary that the math works out. Look for calculators online.</p>



<p>Luckily, since you&#8217;ve been such a bad employee and you&#8217;ve looked out for yourself from the beginning &#8211; you are well on your way to establish yourself as a leading figure in your field. That is your currency. Treat the outside perception of persona as equity, almost money in the bank. It&#8217;s an asset to you that you must guard and nourish. It is critical for success as a non-employee. So how do you generate this currency?</p>



<p>Personally, I&#8217;ve always liked academia. At first it seemed like a wonderful lifestyle; in reality it is just like any other business. But one thing is set apart: People are recognized for their individual contributions. You publish papers with your personal name on them, you receive awards with your name on them, you start labs and call them after yourself. Yes, it&#8217;s a very ego-centric domain. But, for that reason exactly it is great for self-employment. Your success is measured by how significant your name in your field is, like how many citations your papers get and other mostly similar metrics. While employed at a company &#8211; the exact opposite happens. No one knows what you did exactly and what was your contribution! To make matters worse, most if not all of your projects are group efforts where you had a small role, even as the lead. Try selling that to your customers! &#8220;Oh yes I&#8217;ve worked on this huge successful project you must have heard of, but I only did some part of it and the rest was taken care of by another group of dozens of people.&#8221; That&#8217;s not a convincing demonstration of your amazing skills.</p>



<p>To be a non-employee you must first <em>work for yourself while you&#8217;re working for others</em>. Building a name for yourself is just about as hard as being self-employed. It&#8217;s a matter of getting out there and being visible. Both internally in your company (remember, your colleagues are your professional network forever), and obviously outside of your company. This is work. Constant, ungratifying work, at first. But establishing a following outside of your company is crucial for your success. In some ways, treat establishing a name for yourself more important than your skills. This is done via social networks, in-person social events (e.g. meetups), conferences, article writing, blogging &amp; podcasting, maybe writing a book even. But the most important factor of all of this is consistency. Do this consistently over a long enough period of time and your chances of failure are slim.</p>



<p>Some parting words. There is so much more to being a successful employee or a self-employed person than what I&#8217;ve covered here. Countless books have been written. This here is my own reflection on a couple of matters I thought were interesting. But you must write your own philosophies which you will invent through decades of work. Go forth and participate in the largest open human experiment called Employment. Come back to share your experiences.</p>
]]></content:encoded>
					
		
		<enclosure url="https://www.morethantechnical.com/wp-content/uploads/2024/05/how-to-be-an-employee.mp3" length="11418311" type="audio/mpeg" />

			</item>
		<item>
		<title>How to Succeed</title>
		<link>https://www.morethantechnical.com/blog/2024/05/15/how-to-succeed/</link>
		
		<dc:creator><![CDATA[Roy]]></dc:creator>
		<pubDate>Wed, 15 May 2024 20:03:00 +0000</pubDate>
				<category><![CDATA[Uncategorized]]></category>
		<guid isPermaLink="false">https://www.morethantechnical.com/?p=2317</guid>

					<description><![CDATA[Advice for young graduates Lots of bright young folks ask me &#8220;How do I get a good job?&#8221;, &#8220;How do I achieve success in this domain?&#8221;, &#8220;What should I do next?&#8221;, usually in the applied computer science or machine learning field. So, I thought I&#8217;d dispense some advice for all future advice seekers, and I [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p><strong>Advice for young graduates</strong></p>



<p>Lots of bright young folks ask me &#8220;How do I get a good job?&#8221;, &#8220;How do I achieve success in this domain?&#8221;, &#8220;What should I do next?&#8221;, usually in the applied computer science or machine learning field. So, I thought I&#8217;d dispense some advice for all future advice seekers, and I may refer some people here, so I don&#8217;t have to repeat myself all that much. Although, feel free to come up and ask a question.</p>



<figure class="wp-block-audio"><audio controls src="https://www.morethantechnical.com/wp-content/uploads/2024/05/How-to-Succeed.mp3"></audio></figure>



<p>Graduating, from anywhere, is daunting. Going from a well understood environment where your achievements are precisely measured, into the world where, frankly, no one cares. You have to make up your own metrics, measure yourself up to them, set goals for yourself and have a roadmap and a timeline. There&#8217;s no &#8220;graduation&#8221; from life. You may think it&#8217;s retirement, but that would not only be wrong (since there&#8217;s life after retirement) it is also immensely subjective and domain specific. So, what metric would you choose? Money in the bank? Sq. ft of your home? Number of dependents? Assets? Papers published? Books read? Miles traveled? BMI? Social subscribers? See? It&#8217;s impossible to pick. It is foolish to pick. Don&#8217;t pick. Not right now at least.</p>



<span id="more-2317"></span>



<p>Your goals after graduation should be to establish yourself as a professional and an individual. Yes, you should focus on yourself. Maximize gains for your-self. Take <em>all </em>the credits, don&#8217;t be shy. Exercise all your rights and privileges. Soak up as much of the accolades. But at the same time appreciate, acknowledge and celebrate the work of others. Never punch down or sideways, <em>only </em>lift people. Make sure that you pack your knapsack very tightly with people you work with, projects concluded, products delivered, etc. These are your fuel reserves for the rest of your career and life &#8211; so bulk up!</p>



<p>OK, that sounds good but how to actually do that? this &#8220;bulking up&#8221;, you may ask. The answer is very short and clear:</p>



<p class="has-larger-font-size">Build.</p>



<p>Just &#8211; build. Build a product. Build a community. Build a following. Build a reputation. Build relationships. Build a home. Build a family. Build your confidence. Build a nest egg. Build an expertise. Build a hobby. Build. Build. Build.</p>



<p>Treat your first few years after graduating from your post-secondary education as a building period. Everything you do, even if it&#8217;s playing video games and going out, should be part of some&#8230; thing that you are building. If you&#8217;re a social type &#8211; you are building a social network. If you&#8217;re an engineer &#8211; you are building a product that delivers value to someone else. Be in a constant state of building, in many different vectors all the time.</p>



<p>Building is like investing. The consequences of your efforts will only be clear to you after a long time. And just like investing &#8211; building compounds. You can never go wrong with being focused on building. If you continue to invest in a project or direction &#8211; you will see success eventually. Investing in the S&amp;P 500 for example has <strong>guaranteed</strong> positive gains if your time horizon is &gt;10 years. It is exactly the same for building, if you stay consistent in your contributions you will keep up with the market and build something with lasting value. Some people refer to the 10,000 hours rule for becoming an expert. Building works the same way.</p>



<p>Now your next question may be: <strong>What </strong>should I build? Again, I have a very short and clear answer:</p>



<p class="has-larger-font-size">Anything.</p>



<p>See the thing is it doesn&#8217;t really matter what you build right now. As long as you are focused on building you are doing the right thing. You may have a tendency to a certain area or an interest domain, but truth is &#8211; you&#8217;re at the very early beginning of your journey that will have a definitely unexpected end point, so it doesn&#8217;t really matter which direction you start walking. As long as you are walking. Walking is the focus.</p>



<p>Just focusing on building will teach you a lot. Anywhere and anything you start making will teach you: whether you like it, whether there&#8217;s a market for it, whether the domain community is nice, whether it&#8217;s something that can compound, whether it has a holistic effect on other things you may build. So many things to learn!</p>



<h4 class="wp-block-heading">How to Build</h4>



<p>This is geared towards students of the engineering disciplines, but it does transfer very well to everything else. I want to give some direct concrete advice on what to work on and how to do it, in case you don&#8217;t have a lot of ideas right now. By the way, not having ideas &#8211; is a blessing. I wish, one day, to not have new ideas on things to work on, it&#8217;s a curse, believe me. But in any case, even if you do have ideas and plenty of them, here are a few things to consider.</p>



<p>Working on an open-source project. Open source is a divine gift given to humanity. It drives the entire world. It creates so much incredible innovation. It is timeless too, and has existed since the beginning of history. It has the power to make you very successful. My advice would be to start a new open-source project and not join an existing one. See above &#8211; you should take ALL the credit to yourself at this point, don&#8217;t share. But the product of your hard work &#8211; give that away for free, again &#8211; right now, don&#8217;t ask for anything in return. Participate in humanity&#8217;s greatest experiment: Benevolence. Work hard, help people through your work, ask for nothing, and success will arrive, it is <em>only</em> a matter of time.</p>



<p>The next question is &#8211; what project should you build? Great question! First, I suggest you refer back to your goals. Let&#8217;s say your goal is to get hired by a big corporation (a great choice! a big company will teach you everything you need to know about business!). Then my suggestion is that you take one of their products and clone it open source, don&#8217;t be shy, don&#8217;t fear retribution, I guarantee you they absolutely don&#8217;t care (their value is in a completely different place! find out where&#8230;). Just the thought and implementation exercises on how to build it will show you: 1. It is not as easy as you thought, 2. all the snags along the way, 3. all the decisions along the way, 4. how to improve it and go beyond &#8211; in short: Everything this company wants you to know as a candidate! You&#8217;re already prepared for the toughest interviews.</p>



<p>The other advice on what to build is more personal. If your family is lucky to have a family business &#8211; build something for that business. The key is to get information on your customer&#8217;s needs. When the customer is your dad, well that makes it a little easier (usually, not all dads are the same) to get that insider information. But if you don&#8217;t have that &#8211; you can reflect on your own life and &#8220;build for yourself&#8221;. I&#8217;m not suggesting you make yet another time management system. Instead, find gaps in your knowledge and fill them. If you&#8217;ve always wanted to learn to code in Lisp &#8211; do that now! Again, the direction is not super important, the persistence is! Find something you can do over a long period of time, like 1-2 years. Knowledge and education are excellent. If you&#8217;re missing a class on a certain topic &#8211; create it. Same as if you&#8217;re missing a tool to e.g. sort your photo album folder based on how many dogs are in the photo &#8211; make that tool. Just start making something useful(-ish?) and put it out there.</p>



<p>Another aspect of building and contributing is <em>how to get noticed</em>. This is important, you want visibility else no one will recognize your hard work. And again, see above &#8211; you want ALL the credit at this point. When building open source, use GitHub. Make it as easy as possible for people to access your work. If you have a knack for it &#8211; go on YouTube and make some videos. Those assets are compounding investment vehicles too. Go on Twitter, be religious about talking about your work. Remember: this is open source and therefore belongs to the world &#8211; better make the world aware it got this gift of your work.</p>



<p>This brings me to the last part about community. Every product, every company, every successful business, every service you see and know &#8211; is about People. It&#8217;s not about finance or things, it&#8217;s about what the products do to change the lives of People. People are the key. So, when you go about your build make sure you have a community of people in mind. When you want to tell people about it, you likely would want to find where they congregate, maybe on a subreddit, maybe a Discord server, or a mailing list (if they&#8217;re OGs). Get in there, mingle, and when you&#8217;ve got the hang of it &#8211; make a community of your own! Opening a Discord server is $0. There&#8217;s a similar cost level to starting a mailing list or newsletter. But whatever method you choose, it has got to be open, it must be inclusive, it must be not about yourself but about the community. Become a servant of your community, NOT it&#8217;s leader. Be the fuel, be the fire that burns under the cauldron. Facilitate, and participate. Trust me, this will pay off x1000 times by the time you realize it.</p>



<h4 class="wp-block-heading">How to Fail</h4>



<p>You might have heard about &#8220;Fail fast, fail early, fail often&#8221; and &#8220;Learning how to fail well&#8221;. I think most of it is BS told to you by people who have already reached success. It is true that at this point in your life you have extremely high risk-tolerance, and pretty much nothing you would do now would damage your long-term success, short of a felony. So, while it <em>is </em>time to experiment, be ready to accept immense measures of failure. Like, so much failure that you&#8217;d re-think your entire life.</p>



<p>Here&#8217;s how you will for sure fail: You will write something so cool and not a single person would read it or comment about it. You will build a free product that people pay $1000s for the alternative and not one single person will use. You will build a community, and no one will join or won&#8217;t say anything. You will make a video, and no one will watch. All this will happen to you, again you have my guarantee.</p>



<p>But guess what. This is absolutely perfect. It&#8217;s exactly what should happen. The burning pain you feel in your chest? that will become your battle scar. The feeling of loss of purpose and rethinking everything? that will become your rocket fuel. The crippling impostor syndrome when everyone around you is 10x more awesome than you? That will become an impregnable Kevlar armor. You will look back at this and you will smile and thank the universe for these opportunities to fail. You will not get many more of these beautiful moments of failure again…</p>



<p>The most important thing in failing is the learning that comes from it. That is not a cliche. But it is by far the easiest to learn from failure when it&#8217;s about something that you build, by yourself, for your personal success. If you slip up or straight up just be negligent in employment &#8211; prepare to accept the consequences. But when you fail working on your own thing, it&#8217;s far easier to know how to improve for next time. And see, the only thing you need to do, even if you don&#8217;t do anything to improve, is just to keep on building. Stay consistent.</p>



<h4 class="wp-block-heading">How to Stop</h4>



<p>Finally, I want to share a bit of advice on knowing how and when to give up. So far in this article I&#8217;ve been pretty adamant on &#8220;just keep building and never stop&#8221;. That&#8217;s a good philosophy. But you should also take care of learning when and how to stop building. It is very easy to get sucked into a whirlpool of never-ending work, and holding the above philosophy you may not have many exit points. To this I want to dedicate a few sentences.</p>



<p>First, always in life and work, always hedge your bets. Always have something to average with. Meaning, if you build &#8211; build several things at once. If you&#8217;re working at a job &#8211; have several streams of work. The only way the numbers are in your favor is if you&#8217;re averaging either over time or over space. Remember the S&amp;P 500, you have 10 years to average over. In building &#8211; make sure you have multiple horses in the race. When one fails, others will step in to continue the race. This is the easiest way to &#8220;Stop&#8221;. Just divert your resources to better ventures and let the failing project die. Simple.</p>



<p>But what if things are not simple? and your project is &#8220;kind of&#8221; working but you&#8217;re not sure? This is time to look at the bigger picture. If you have a family to support that is the easiest, focus on their needs (ahead of your own) and adjust course. But if it&#8217;s just you, which is most times the case, go back to your goals: Is this project going to get me hired at this place? Is it going to teach me? Does it have a community I want to be a part of? Is it genuinely doing good? Really, don&#8217;t be bothered with silly terms like &#8220;disruption&#8221;, &#8220;displacement&#8221;, &#8220;growth&#8221;, &#8220;scale&#8221;, &#8220;market fit&#8221;, these are absolutely irrelevant at this stage. Your goal in this period is to build. If building the project doesn&#8217;t also at the same time build your reputation &#8211; it&#8217;s a sign. Everything you do should be 1+1=3. If it&#8217;s closer to 2 &#8211; it&#8217;s a sign. Learn to read signs.</p>



<p>So, how do you know when and where to stop? You will know. It will be when you achieve your goals.</p>



<p>A few parting words to end this article. Always be in motion. Always be building. Motion creates a flywheel effect that works for you when you sleep. Realize nothing will be served to you ever. You will have to build nice things to have them. Alway be learning, always be teaching. Share your knowledge for free at every opportunity. Make your opinions vocal, make them in person preferably. You are ready.</p>
]]></content:encoded>
					
		
		<enclosure url="https://www.morethantechnical.com/wp-content/uploads/2024/05/How-to-Succeed.mp3" length="13663548" type="audio/mpeg" />

			</item>
		<item>
		<title>URL/API Source OBS Plugin: Fetch Live Data in your Stream</title>
		<link>https://www.morethantechnical.com/blog/2023/08/10/url-api-source-obs-plugin/</link>
		
		<dc:creator><![CDATA[Roy]]></dc:creator>
		<pubDate>Thu, 10 Aug 2023 14:07:38 +0000</pubDate>
				<category><![CDATA[cmake]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[gui]]></category>
		<category><![CDATA[qt]]></category>
		<category><![CDATA[Stream]]></category>
		<category><![CDATA[video]]></category>
		<guid isPermaLink="false">https://www.morethantechnical.com/?p=2280</guid>

					<description><![CDATA[Walk through the source code for the URL API source plugin for OBS, built in C++, which allows users to fetch information from a URL and parse the output, which can then be rendered on screen.]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="URL/API Source OBS Code Walkthrough" width="580" height="326" src="https://www.youtube.com/embed/TiluUg1LxcQ?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<p>If you&#8217;re a fan of OBS (Open Broadcaster Software), you may already be familiar with its vast library of plugins that enhance its functionality and provide added features. One such plugin that I recently developed is the <a href="https://obsproject.com/forum/resources/url-api-source-fetch-live-data-and-display-it-on-screen.1756/" target="_blank" rel="noreferrer noopener">URL API source plugin</a>. This plugin allows you to fetch information from a URL and display it in your OBS stream. In this blog post, we will take a closer look at the <a href="https://github.com/royshil/obs-urlsource" target="_blank" rel="noreferrer noopener">source code for this plugin</a> and understand how it works.</p>



<span id="more-2280"></span>



<p>To begin with, let&#8217;s quickly recap what the URL API source plugin does. When set up as a new source in OBS, it has a few properties, including the URL from which it fetches information, the parsing of the output, styling using HTML tags and CSS, and a timer. The plugin is built in C++ and consists of various functions that handle tasks like making HTTP requests, parsing the response, and rendering the text on screen.</p>



<figure class="wp-block-image size-large"><img fetchpriority="high" decoding="async" width="1024" height="961" src="https://www.morethantechnical.com/wp-content/uploads/2023/08/Screenshot-2023-08-10-at-4.50.38-PM-1024x961.png" alt="" class="wp-image-2281" srcset="https://www.morethantechnical.com/wp-content/uploads/2023/08/Screenshot-2023-08-10-at-4.50.38-PM-1024x961.png 1024w, https://www.morethantechnical.com/wp-content/uploads/2023/08/Screenshot-2023-08-10-at-4.50.38-PM-300x282.png 300w, https://www.morethantechnical.com/wp-content/uploads/2023/08/Screenshot-2023-08-10-at-4.50.38-PM-768x721.png 768w, https://www.morethantechnical.com/wp-content/uploads/2023/08/Screenshot-2023-08-10-at-4.50.38-PM-1536x1442.png 1536w, https://www.morethantechnical.com/wp-content/uploads/2023/08/Screenshot-2023-08-10-at-4.50.38-PM-1200x1126.png 1200w, https://www.morethantechnical.com/wp-content/uploads/2023/08/Screenshot-2023-08-10-at-4.50.38-PM.png 1664w" sizes="(max-width: 1024px) 100vw, 1024px" /></figure>



<p>The core functionality of the URL API source plugin lies in a thread that runs continuously in a loop, separate from the rendering thread and the rest of OBS. This thread periodically sends the HTTP request, parses the output, and sends it back to OBS for rendering on screen. By running the requests on a timer, the plugin ensures that the rendering pipeline remains lean, as it doesn&#8217;t have to handle the requests frame by frame.</p>



<p>The thread function:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
void curl_loop(struct url_source_data *usd)
{
  struct obs_source_frame frame = {};

  while (true) {
    {
      std::lock_guard&lt;std::mutex&gt; lock(*(usd-&gt;curl_mutex.get()));
      if (!usd-&gt;curl_thread_run) {
        break;
      }
    }

    // Send the request
    struct request_data_handler_response response =
      request_data_handler(&amp;(usd-&gt;request_data));
    if (response.status_code != 200) {
      obs_log(LOG_INFO, &quot;Failed to send request&quot;);
    } else {
      uint32_t width = 0;
      uint32_t height = 0;
      uint8_t *renderBuffer = nullptr;

      // prepare the text from the template
      std::string text = usd-&gt;output_text_template;
      // if the template is empty use the response body
      if (text.empty()) {
        text = response.body_parsed;
      } else {
        // attempt to replace {output} with the response body
        text = std::regex_replace(text, std::regex(&quot;\\{output\\}&quot;), response.body_parsed);
      }
      // render the text
      render_text_with_qtextdocument(text, width, height, &amp;renderBuffer, usd-&gt;css_props);
      // Update the frame
      frame.data&#x5B;0] = renderBuffer;
      frame.linesize&#x5B;0] = width * 4;
      frame.width = width;
      frame.height = height;
      frame.format = VIDEO_FORMAT_BGRA;

      // Send the frame
      obs_source_output_video(usd-&gt;source, &amp;frame);

      // Free the render buffer
      bfree(renderBuffer);
    }

    const int64_t sleep_time_ms = (int64_t)(usd-&gt;update_timer_ms);
    {
      std::unique_lock&lt;std::mutex&gt; lock(*(usd-&gt;curl_mutex.get()));
      // Sleep for n ns as per the update timer for the remaining time
      usd-&gt;curl_thread_cv-&gt;wait_for(lock, std::chrono::milliseconds(sleep_time_ms));
    }
  }
  obs_log(LOG_INFO, &quot;Stopping URL Source thread&quot;);
}

</pre></div>


<p>One interesting feature of the plugin is the use of a condition variable (<code>curl_thread_cv</code> above) for the thread&#8217;s sleep function. This allows the thread to be interrupted if the source is hidden or destroyed, preventing OBS from hanging until the thread completes its sleep cycle</p>



<p>The plugin supports various options for parsing the output, including JSON, XML, and regular expressions. For JSON parsing, the developer has implemented the <a href="https://github.com/nlohmann/json" target="_blank" rel="noreferrer noopener">Nlohmann JSON</a> parser and JSON pointer for extracting specific information from the response. Similarly, XML parsing is handled using the <a href="https://github.com/zeux/pugixml" target="_blank" rel="noreferrer noopener">PugiXML</a> library and XPath for extraction. And for regular expression parsing, the plugin utilizes <code>std::regex</code> library.</p>



<p>Once the request has been completed successfully, the plugin renders the fetched information on screen using the Qt library&#8217;s QtTextDocument. This allows for typesetting or layout of the text using HTML or markdown. By creating a template with the desired styling and replacing the text content with the fetched information, the plugin achieves a user-friendly rendering of the data.</p>



<p>The text rendering function:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
void render_text_with_qtextdocument(const std::string &amp;text, uint32_t &amp;width, uint32_t &amp;height,
				    uint8_t **data, const std::string &amp;css_props)
{
  // apply response in template
  QString html = QString(template_text).replace(&quot;{text}&quot;, QString::fromStdString(text)).replace(&quot;{css_props}&quot;, QString::fromStdString(css_props));
  QTextDocument textDocument;
  textDocument.setHtml(html);
  textDocument.setTextWidth(640);

  QPixmap pixmap(textDocument.size().toSize());
  pixmap.fill(Qt::transparent);
  QPainter painter;
  painter.begin(&amp;pixmap);
  painter.setCompositionMode(QPainter::CompositionMode_Source);

  // render text
  textDocument.drawContents(&amp;painter);

	  painter.setCompositionMode(QPainter::CompositionMode_DestinationIn);
  painter.end();

  // save pixmap to buffer
  QImage image = pixmap.toImage();
  // crop to the idealWidth of the text
  image = image.copy(0, 0, (int)textDocument.idealWidth(), image.height());
  // get width and height
  width = image.width();
  height = image.height();
  // allocate output buffer (RGBA), user must free
  *data = (uint8_t *)bzalloc(width * height * 4);
  // copy image data to output buffer
  memcpy(*data, image.bits(), width * height * 4);
}

</pre></div>


<p>Overall, the URL API source plugin for OBS is a simple yet powerful tool for fetching and displaying dynamic content in your OBS stream. The elegance of its implementation lies in the careful handling of HTTP requests, parsing of various data formats, and the efficient integration with OBS&#8217;s rendering pipeline.</p>



<p>If you&#8217;re interested in diving deeper into the code and exploring the additional features of the plugin, I highly recommend taking a look at the <a href="https://github.com/royshil/obs-urlsource" target="_blank" rel="noreferrer noopener">source code</a> yourself. The developer has put in significant effort to ensure the plugin&#8217;s functionality and ease of use. By studying the code, you can gain insights into the inner workings of the plugin and potentially even contribute to its development.</p>



<p>In conclusion, the URL API source plugin for OBS is a valuable addition to any streaming setup, providing a seamless way to fetch and display external information in your live streams. Its well-structured source code, efficient threading, and support for various data formats make it a versatile tool for streamers. So, give it a try and see how it enhances your streaming experience.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>CleanStream OBS Plugin: Remove Filler Words with Whisper CPP</title>
		<link>https://www.morethantechnical.com/blog/2023/06/18/cleanstream-obs-plugin-remove-filler-words-with-whisper-cpp/</link>
		
		<dc:creator><![CDATA[Roy]]></dc:creator>
		<pubDate>Sun, 18 Jun 2023 06:45:49 +0000</pubDate>
				<category><![CDATA[code]]></category>
		<category><![CDATA[machine learning]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Stream]]></category>
		<category><![CDATA[video]]></category>
		<guid isPermaLink="false">https://www.morethantechnical.com/?p=2262</guid>

					<description><![CDATA[CleanStream OBS Plugin is a powerful tool that helps clean live audio streams from unwanted words, filler words, and profanities. Created in C++, this plugin can improve the quality of live streams while saving time and effort in post-processing. In this blog post, we will take a detailed walk-through of the code for my CleanStream [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>CleanStream OBS Plugin is a powerful tool that helps clean live audio streams from unwanted words, filler words, and profanities. Created in C++, this plugin can improve the quality of live streams while saving time and effort in post-processing. In this blog post, we will take a detailed walk-through of the code for my <a rel="noreferrer noopener" href="https://github.com/royshil/obs-cleanstream" target="_blank">CleanStream OBS plugin</a>, explaining how it is built and its core functionalities.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe title="CleanStream OBS plugin code walkthrough" width="580" height="326" src="https://www.youtube.com/embed/HdSI3sUKwsY?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<span id="more-2262"></span>



<p>To begin with, this plugin is an audio filter, which means that it works by filtering the audio entered through one function in the main plugin file. </p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
struct obs_source_info my_audio_filter_info = {
  .id = &quot;cleanstream_audio_filter&quot;,
  .type = OBS_SOURCE_TYPE_FILTER,
  .output_flags = OBS_SOURCE_AUDIO,
  .get_name = cleanstream_name,
  .create = cleanstream_create,
  .destroy = cleanstream_destroy,
  .get_defaults = cleanstream_defaults,
  .get_properties = cleanstream_properties,
  .update = cleanstream_update,
  .filter_audio = cleanstream_filter_audio,
}
</pre></div>


<p>The <code>cleanstream_filter_audio</code> function is responsible for getting audio frames, processing them, and returning the resultant audio data to OBS. The entire magic of this plugin happens within this one function.</p>



<p>The CleanStream OBS plugin is built on top of Whisper C++, a project by <a rel="noreferrer noopener" href="https://github.com/ggerganov/whisper.cpp" target="_blank">ggerganov</a> that allows building the <a rel="noreferrer noopener" href="https://github.com/openai/whisper" target="_blank">OpenAI Whisper</a> speech recognition model from the ground up in C++, without any dependencies. To use Whisper.cpp in CleanStream, we just need two source files, two header files. Whisper C++ runs the neural network for Whisper, which is quite slow, in a different thread to continuously run in the background. This threading requires some buffering, so we use a circular buffer (utility provided by OBS) to store the incoming audio data, and a separate thread for continuous background processing. Mind I am using two buffers &#8211; one for the raw audio data and one for &#8220;info&#8221; which denotes how many audio frames are in the data buffer and what&#8217;s the timestamp.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
// push back current audio data to input circlebuf
for (size_t c = 0; c &lt; gf-&gt;channels; c++) {
  circlebuf_push_back(&amp;gf-&gt;input_buffers&#x5B;c], audio-&gt;data&#x5B;c], audio-&gt;frames * sizeof(float));
}
// push audio packet info (timestamp/frame count) to info circlebuf
struct cleanstream_audio_info info = {0};
info.frames = audio-&gt;frames;       // number of frames in this packet
info.timestamp = audio-&gt;timestamp; // timestamp of this packet
circlebuf_push_back(&amp;gf-&gt;info_buffer, &amp;info, sizeof(info));
</pre></div>


<p>The processing thread uses a loop called &#8216;Whisper Loop,&#8217; which continuously runs to clean out the audio from any unwanted words or profanities. It gets the shared data for the plugin and checks if the Whisper context is initialized and if there is any data to process or not. If there is data to process, the thread performs some processing, such as resampling and voice activation using a VAD (Voice Activation Detection) algorithm that looks at the energy in all the windows. </p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
float energy_all = 0.0f;

for (uint64_t i = 0; i &lt; n_samples; i++) {
  energy_all += fabsf(pcmf32&#x5B;i]);
}

energy_all /= n_samples;

if (energy_all &lt; vad_thold) {
  return false;
}
</pre></div>


<p>This creates an overlap between different samples coming in, and to set the overlap region dynamically, we check the timing of the Whisper inference function. If Whisper was fast enough we increase the overlap, otherwise we decrease it. It eventually settles on the right value for the overlap.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
do_log(gf-&gt;log_level, &quot;audio processing of %u ms new data took %d ms&quot;, new_frames_from_infos_ms,
        (int)duration);

if (duration &gt; new_frames_from_infos_ms) {
  // try to decrease overlap down to minimum of 100 ms
  gf-&gt;overlap_ms = std::max((uint64_t)gf-&gt;overlap_ms - 10, (uint64_t)100);
  gf-&gt;overlap_frames = gf-&gt;overlap_ms * gf-&gt;sample_rate / 1000;
} else if (!skipped_inference) {
  // try to increase overlap up to 75% of the segment
  gf-&gt;overlap_ms =
    std::min((uint64_t)gf-&gt;overlap_ms + 10, (uint64_t)(new_frames_from_infos_ms * 0.75f));
  gf-&gt;overlap_frames = gf-&gt;overlap_ms * gf-&gt;sample_rate / 1000;
}
</pre></div>


<p>Speaking of the Whisper inference function, it is a fundamental part of this plugin, which transcribes the audio and removes any unwanted sounds. We use a few interesting things from Whisper CPP to decode the transcription into text, such as get segment text, which is limited to just one segment, and t0 t1, which gives the timings. We also sum up the probability for all the tokens that came up from the Whisper inference function to give us the general sentence probability.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
const int n_segment = 0;
const char *text = whisper_full_get_segment_text(gf-&gt;whisper_context, n_segment);
const int64_t t0 = whisper_full_get_segment_t0(gf-&gt;whisper_context, n_segment);
const int64_t t1 = whisper_full_get_segment_t1(gf-&gt;whisper_context, n_segment);

float sentence_p = 0.0f;
const int n_tokens = whisper_full_n_tokens(gf-&gt;whisper_context, n_segment);
for (int j = 0; j &lt; n_tokens; ++j) {
  sentence_p += whisper_full_get_token_p(gf-&gt;whisper_context, n_segment, j);
}
sentence_p /= (float)n_tokens;
</pre></div>


<p>Finally, we detect the fillers and profanities through user-defined detect and reject regular expressions. This detection allows us to process the audio and return it using circular buffers and multi-threading to ensure that everything runs smoothly.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
std::regex filler_regex(gf-&gt;detect_regex);
if (std::regex_search(text_lower, filler_regex, std::regex_constants::match_any)) {
  return DETECTION_RESULT_FILLER;
}
std::regex beep_regex(gf-&gt;beep_regex);
if (std::regex_search(text_lower, beep_regex, std::regex_constants::match_any)) {
  return DETECTION_RESULT_BEEP;
}
</pre></div>


<p>Modifying the audio to include beep or silence:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
info(&quot;beep segment, adding a beep %lu -&gt; %u&quot;, first_boundary, num_new_frames_from_infos);
if (gf-&gt;do_silence) { // User can enable/disable modification
  for (size_t c = 0; c &lt; gf-&gt;channels; c++) {
    for (size_t i = first_boundary; i &lt; num_new_frames_from_infos; i++) {
      // add a beep at A4 (440Hz)
      gf-&gt;copy_buffers&#x5B;c]&#x5B;i] = 0.5f * sinf(2.0f * M_PI * 440.0f * (float)i / gf-&gt;sample_rate);
    }
  }
}
</pre></div>


<p>In conclusion, the CleanStream OBS plugin offers a powerful tool that filters live audio streams from any unwanted sounds. By providing a detailed code walkthrough of the CleanStream OBS plugin, I hope to have given you a better understanding of how it works and what makes it so powerful. This is a big plugin, so covering everything in this post is impossible. So I highly recommend that you check out the <a href="https://github.com/royshil/obs-cleanstream" target="_blank" rel="noreferrer noopener">CleanStream OBS plugin on GitHub</a> and try it out yourself to experience its powerful capabilities. It&#8217;s an excellent tool that can save time and provide high-quality audio for live streams.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Tutorial: M-Audio Oxygen Pro Mini with Ableton</title>
		<link>https://www.morethantechnical.com/blog/2023/05/23/tutorial-m-audio-oxygen-pro-mini-with-ableton/</link>
		
		<dc:creator><![CDATA[Roy]]></dc:creator>
		<pubDate>Tue, 23 May 2023 20:01:59 +0000</pubDate>
				<category><![CDATA[Music]]></category>
		<category><![CDATA[Software]]></category>
		<category><![CDATA[tips]]></category>
		<category><![CDATA[video]]></category>
		<guid isPermaLink="false">https://www.morethantechnical.com/?p=2250</guid>

					<description><![CDATA[Have you recently purchased the M Audio Oxygen Pro mini and want to figure out how to use it with Ableton Live Lite 11? If so, you&#8217;re not alone! In this blog post, we will go over some of the essential functions and tips that I have learned while working with this keyboard. One of [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Have you recently purchased the M Audio Oxygen Pro mini and want to figure out how to use it with Ableton Live Lite 11? If so, you&#8217;re not alone! In this blog post, we will go over some of the essential functions and tips that I have learned while working with this keyboard.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="M-AUDIO Oxygen Pro Mini Ableton functions [Tutorial, Live]" width="580" height="326" src="https://www.youtube.com/embed/1W7wDMG5M58?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<span id="more-2250"></span>



<p>One of the primary things to keep in mind is to connect the keyboard before starting Ableton. Once connected, you will see a red bar above the clips that you have pre-recorded or are going to record. This bar is a selector that helps you play or record the clips. You can scroll up and down with the red selector, and the channels that are armed and ready to play will be yellow. </p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="993" height="1024" src="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-5-993x1024.png" alt="" class="wp-image-2251" srcset="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-5-993x1024.png 993w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-5-291x300.png 291w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-5-768x792.png 768w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-5-1200x1238.png 1200w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-5.png 1332w" sizes="auto, (max-width: 993px) 100vw, 993px" /></figure>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="573" src="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-6-1024x573.png" alt="" class="wp-image-2252" srcset="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-6-1024x573.png 1024w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-6-300x168.png 300w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-6-768x430.png 768w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-6-1200x672.png 1200w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-6.png 1218w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The arming of these channels is done through the four buttons under the sliders, which also control the output volume of each channel.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="566" src="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-7-1024x566.png" alt="" class="wp-image-2253" srcset="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-7-1024x566.png 1024w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-7-300x166.png 300w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-7-768x425.png 768w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-7-1200x663.png 1200w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-7.png 1212w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The pads on the keyboard also have different functions. The white pads stop the playing when a channel has nothing, and the black channels are armed and ready to record. The play and record buttons work as expected.</p>



<p>If you want to play all channels together, you can use the Pad Bank button. This button plays all the channels in that row. And to clear the clips that are playing, press the Pat Bank button again. If you want to play the second row of clips, scroll down with the knob, select the second row, and start playing.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="564" src="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-8-1024x564.png" alt="" class="wp-image-2254" srcset="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-8-1024x564.png 1024w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-8-300x165.png 300w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-8-768x423.png 768w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-8-1200x661.png 1200w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-8.png 1220w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<figure class="wp-block-image size-full"><img loading="lazy" decoding="async" width="874" height="924" src="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-9.png" alt="" class="wp-image-2255" srcset="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-9.png 874w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-9-284x300.png 284w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-9-768x812.png 768w" sizes="auto, (max-width: 874px) 100vw, 874px" /></figure>



<p>The knobs on the keyboard can control channel parameters or sends, depending on how you set them up. Just select the channel you want to control, and start using the knobs to adjust the parameters. Since there are 4 knob you will only be able to control 4 parameters of the instrument, or the 4 channels selected by the red selector.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="567" src="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-10-1024x567.png" alt="" class="wp-image-2256" srcset="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-10-1024x567.png 1024w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-10-300x166.png 300w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-10-768x425.png 768w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-10-1200x664.png 1200w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-10.png 1214w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>


<div class="wp-block-image">
<figure class="aligncenter size-full"><img loading="lazy" decoding="async" width="378" height="328" src="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-11.png" alt="" class="wp-image-2257" srcset="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-11.png 378w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-11-300x260.png 300w" sizes="auto, (max-width: 378px) 100vw, 378px" /></figure></div>


<p>The back and forward buttons or the bank left and bank right keys move the selector square, allowing you to select different channels. </p>



<p>Remember that the keyboard has a global mode function too. Turning it off will allow you to use the ARP or the latch mode. These functions are useful for live looping and recording as they give you shortcuts to control Ableton from your keyboard, saving you time and effort.</p>



<p>In conclusion, the M Audio Oxygen Pro mini is a pretty capable keyboard that can do a lot of things, but not all of them are well documented. With these tips and functions, you can get started with your Ableton Live Lite 11, and start making music the way you want to.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>Building an OBS Background Removal Plugin: A Walkthrough</title>
		<link>https://www.morethantechnical.com/blog/2023/05/20/building-an-obs-background-removal-plugin-a-walkthrough/</link>
		
		<dc:creator><![CDATA[Roy]]></dc:creator>
		<pubDate>Sat, 20 May 2023 19:47:28 +0000</pubDate>
				<category><![CDATA[code]]></category>
		<category><![CDATA[graphics]]></category>
		<category><![CDATA[machine learning]]></category>
		<category><![CDATA[opencv]]></category>
		<category><![CDATA[opengl]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[video]]></category>
		<category><![CDATA[vision]]></category>
		<guid isPermaLink="false">https://www.morethantechnical.com/?p=2242</guid>

					<description><![CDATA[In this blog post, we will take a closer look at the development of the OBS Background Removal Plugin, discussing its key components, functionalities, and the process behind building it. The plugin was created to address the need for virtual green screen and background removal capabilities in OBS (Open Broadcaster Software), a popular live streaming [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>In this blog post, we will take a closer look at the development of the OBS Background Removal Plugin, discussing its key components, functionalities, and the process behind building it. The plugin was created to address the need for virtual green screen and background removal capabilities in OBS (Open Broadcaster Software), a popular live streaming and recording software. With over 500,000 downloads and ongoing contributions from various developers, the OBS Background Removal Plugin has gained significant traction in the streaming community. Whether you&#8217;re interested in understanding how this plugin works or considering building a similar plugin yourself, this walkthrough will provide valuable insights.</p>



<span id="more-2242"></span>



<p>Please refer to the GitHub repo for the full code: <a href="https://github.com/royshil/obs-backgroundremoval" target="_blank" rel="noreferrer noopener">https://github.com/royshil/obs-backgroundremoval</a> as I cannot put all code here, just the &#8220;interesting parts&#8221;.</p>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="OBS Background Removal Plugin w ONNX Runtime Neural Networks [Code Walkthrough | C++]" width="580" height="326" src="https://www.youtube.com/embed/iFQtcJg0Wsk?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div><figcaption class="wp-element-caption">Code Walkthrough</figcaption></figure>



<h2 class="wp-block-heading">Plugin Architecture</h2>



<p>The OBS Background Removal Plugin is written in C++ and follows the plugin template provided by the OBS project. The main entry point for the plugin is the &#8220;plugin-main.cpp&#8221; file, which registers the plugin&#8217;s functions with OBS. The <a href="https://github.com/obsproject/obs-plugintemplate" target="_blank" rel="noreferrer noopener">template provided by OBS</a> serves as a foundation for building plugins, offering essential workflows for building and publishing the plugin across multiple operating systems.</p>



<p>The <code>plugin-main.cpp</code> file only gives the module a name and registers the plugin, for example:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
MODULE_EXPORT const char *obs_module_description(void)
{
  return obs_module_text(&quot;PortraitBackgroundFilterPlugin&quot;);
}

extern struct obs_source_info background_removal_filter_info;

bool obs_module_load(void)
{
  obs_register_source(&amp;background_removal_filter_info);
  blog(LOG_INFO, &quot;plugin loaded successfully (version %s)&quot;, PLUGIN_VERSION);
  return true;
}
</pre></div>


<p>This is the struct that registers the functions of the plugin with OBS:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
struct obs_source_info background_removal_filter_info = {
  .id = &quot;background_removal&quot;,
  .type = OBS_SOURCE_TYPE_FILTER,
  .output_flags = OBS_SOURCE_VIDEO,
  .get_name = filter_getname,
  .create = filter_create,
  .destroy = filter_destroy,
  .get_defaults = filter_defaults,
  .get_properties = filter_properties,
  .update = filter_update,
  .activate = filter_activate,
  .deactivate = filter_deactivate,
  .video_tick = filter_video_tick,
  .video_render = filter_video_render,
};
</pre></div>


<h2 class="wp-block-heading">Video Rendering and Effects</h2>



<p>The core functionality of the plugin resides in the &#8220;background-filter.cpp&#8221; file. Within this file, the &#8220;video-render&#8221; function is responsible for rendering the video and utilizing the GPU for efficiency. The plugin leverages OBS&#8217;s effects system, and the video rendering process involves blending the input RGB image with the background mask using a custom effect written in HLSL (High-Level Shader Language). This blending effectively removes the background while preserving the foreground.</p>



<p>This is part of the code for the rendering:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
  gs_eparam_t *alphamask = gs_effect_get_param_by_name(tf-&gt;effect, &quot;alphamask&quot;);
  gs_eparam_t *blurSize = gs_effect_get_param_by_name(tf-&gt;effect, &quot;blurSize&quot;);
  gs_eparam_t *xTexelSize = gs_effect_get_param_by_name(tf-&gt;effect, &quot;xTexelSize&quot;);
  gs_eparam_t *yTexelSize = gs_effect_get_param_by_name(tf-&gt;effect, &quot;yTexelSize&quot;);
  gs_eparam_t *blurredBackground = gs_effect_get_param_by_name(tf-&gt;effect, &quot;blurredBackground&quot;);

  gs_effect_set_texture(alphamask, alphaTexture);
  gs_effect_set_int(blurSize, (int)tf-&gt;blurBackground);
  gs_effect_set_float(xTexelSize, 1.0f / width);
  gs_effect_set_float(yTexelSize, 1.0f / height);
  if (tf-&gt;blurBackground &gt; 0.0) {
    gs_effect_set_texture(blurredBackground, blurredTexture);
  }

  obs_source_process_filter_tech_end(tf-&gt;source, tf-&gt;effect, 0, 0, &quot;DrawWithBlur&quot;);

  gs_blend_state_pop();

  gs_texture_destroy(alphaTexture);
  gs_texture_destroy(blurredTexture);

</pre></div>


<p>The HLSL effect is very simple. It only multiplies the RGB values by the alpha values from the background mask:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
float4 PSAlphaMaskRGBAWithoutBlur(VertDataOut v_in) : TARGET
{
	float4 inputRGBA = image.Sample(textureSampler, v_in.uv);
	inputRGBA.rgb = max(float3(0.0, 0.0, 0.0), inputRGBA.rgb / inputRGBA.a);

	float4 outputRGBA;
	float a = (1.0 - alphamask.Sample(textureSampler, v_in.uv).r) * inputRGBA.a;
	outputRGBA.rgb = inputRGBA.rgb * a;
	outputRGBA.a = a;
	return outputRGBA;
}
</pre></div>


<h2 class="wp-block-heading">Neural Network Inference</h2>



<p>To perform background removal, the plugin employs a neural network for image processing. The &#8220;video tick&#8221; function retrieves the RGB(A) input color image, which is then processed through the neural network in the &#8220;run filter model inference&#8221; function. This process involves converting the image to RGB, resizing it to the network&#8217;s input size, applying any necessary preprocessing, running the inference, and converting the output to the expected format.</p>



<h2 class="wp-block-heading">Abstracted Model Class</h2>



<p>The plugin incorporates various neural network models for different background removal scenarios. These models are abstracted using a parent class called &#8220;model,&#8221; which handles shared functionalities such as file path retrieval, input/output names, and buffer allocation. Each specific model subclass implements model-specific preprocessing and postprocessing logic, catering to the requirements of different neural network architectures.</p>



<p>The <code>Model.h</code> file holds the abstract Model class:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
class Model {
  private:
  /* data */
  public:
  Model(/* args */){};
  virtual ~Model(){};

  const char *name;

#if _WIN32
  const std::wstring
#else
  const std::string
#endif
  getModelFilepath(const std::string &amp;amp;modelSelection)
  {
    //...
  }

  virtual void populateInputOutputNames(const std::unique_ptr&amp;lt;Ort::Session&gt; &amp;amp;session,
                                        std::vector&amp;lt;Ort::AllocatedStringPtr&gt; &amp;amp;inputNames,
                                        std::vector&amp;lt;Ort::AllocatedStringPtr&gt; &amp;amp;outputNames)
  {
    //...
  }

  virtual bool populateInputOutputShapes(const std::unique_ptr&amp;lt;Ort::Session&gt; &amp;amp;session,
                                         std::vector&amp;lt;std::vector&amp;lt;int64_t&gt;&gt; &amp;amp;inputDims,
                                         std::vector&amp;lt;std::vector&amp;lt;int64_t&gt;&gt; &amp;amp;outputDims)
  {
    //...
  }

  virtual void allocateTensorBuffers(const std::vector&amp;lt;std::vector&amp;lt;int64_t&gt;&gt; &amp;amp;inputDims,
                                     const std::vector&amp;lt;std::vector&amp;lt;int64_t&gt;&gt; &amp;amp;outputDims,
                                     std::vector&amp;lt;std::vector&amp;lt;float&gt;&gt; &amp;amp;outputTensorValues,
                                     std::vector&amp;lt;std::vector&amp;lt;float&gt;&gt; &amp;amp;inputTensorValues,
                                     std::vector&amp;lt;Ort::Value&gt; &amp;amp;inputTensor,
                                     std::vector&amp;lt;Ort::Value&gt; &amp;amp;outputTensor)
  {
    
    //...
  }

  virtual void getNetworkInputSize(const std::vector&amp;lt;std::vector&amp;lt;int64_t&gt;&gt; &amp;amp;inputDims,
                                   uint32_t &amp;amp;inputWidth, uint32_t &amp;amp;inputHeight)
  {
    // BHWC
    inputWidth = (int)inputDims&#x5B;0]&#x5B;2];
    inputHeight = (int)inputDims&#x5B;0]&#x5B;1];
  }

  virtual void prepareInputToNetwork(cv::Mat &amp;amp;resizedImage, cv::Mat &amp;amp;preprocessedImage)
  {
    preprocessedImage = resizedImage / 255.0;
  }

  virtual void postprocessOutput(cv::Mat &amp;amp;output)
  {
    output = output * 255.0; // Convert to 0-255 range
  }

  virtual void loadInputToTensor(const cv::Mat &amp;amp;preprocessedImage, uint32_t inputWidth,
                                 uint32_t inputHeight,
                                 std::vector&amp;lt;std::vector&amp;lt;float&gt;&gt; &amp;amp;inputTensorValues)
  {
    //...
  }

  virtual cv::Mat getNetworkOutput(const std::vector&amp;lt;std::vector&amp;lt;int64_t&gt;&gt; &amp;amp;outputDims,
                                   std::vector&amp;lt;std::vector&amp;lt;float&gt;&gt; &amp;amp;outputTensorValues)
  {
    //...
  }

  virtual void assignOutputToInput(std::vector&amp;lt;std::vector&amp;lt;float&gt;&gt; &amp;amp;,
                                   std::vector&amp;lt;std::vector&amp;lt;float&gt;&gt; &amp;amp;)
  {
  }

  virtual void runNetworkInference(const std::unique_ptr&amp;lt;Ort::Session&gt; &amp;amp;session,
                                   const std::vector&amp;lt;Ort::AllocatedStringPtr&gt; &amp;amp;inputNames,
                                   const std::vector&amp;lt;Ort::AllocatedStringPtr&gt; &amp;amp;outputNames,
                                   const std::vector&amp;lt;Ort::Value&gt; &amp;amp;inputTensor,
                                   std::vector&amp;lt;Ort::Value&gt; &amp;amp;outputTensor)
  {
   //...
  }
};
</pre></div>


<p>This class assumes <code>BHWC</code> data format, but some models are <code>BCHW</code>. To handle that we have the <code>ModelBCHW</code> class which overrides some of the functions that have to do with loading and unloading the tensors from the inference session.</p>



<h2 class="wp-block-heading">Plugin Properties and Customization</h2>



<p>The plugin offers a range of properties and customization options to enhance the user&#8217;s control over the background removal process. These properties include threshold adjustments, preprocessing / postprocessing operations (e.g., smoothing, feathering), GPU options, model selection, and more. By leveraging the plugin&#8217;s properties, users can fine-tune the background removal based on their specific streaming or recording needs.</p>



<p>Defining properties on the plugin <code>static obs_properties_t *filter_properties(void *data)</code> function will create UI elements:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="911" src="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-4-1024x911.png" alt="" class="wp-image-2243" srcset="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-4-1024x911.png 1024w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-4-300x267.png 300w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-4-768x684.png 768w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-4-1536x1367.png 1536w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-4-1200x1068.png 1200w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-4.png 1946w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>All of the functions have access to a data pointer that holds important data that we need for processing the video:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: cpp; title: ; notranslate">
struct background_removal_filter : public filter_data {
  float threshold = 0.5f;
  cv::Scalar backgroundColor{0, 0, 0, 0};
  float contourFilter = 0.05f;
  float smoothContour = 0.5f;
  float feather = 0.0f;

  cv::Mat backgroundMask;
  int maskEveryXFrames = 1;
  int maskEveryXFramesCount = 0;
  int64_t blurBackground = 0;

  gs_effect_t *effect;
  gs_effect_t *kawaseBlurEffect;
};
</pre></div>


<p>This for example is part of the function that gets the UI properties and stores them in the data struct:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
static void filter_update(void *data, obs_data_t *settings)
{
  struct background_removal_filter *tf = reinterpret_cast&amp;lt;background_removal_filter *&gt;(data);
  tf-&gt;threshold = (float)obs_data_get_double(settings, &quot;threshold&quot;);

  tf-&gt;contourFilter = (float)obs_data_get_double(settings, &quot;contour_filter&quot;);
  tf-&gt;smoothContour = (float)obs_data_get_double(settings, &quot;smooth_contour&quot;);
  tf-&gt;feather = (float)obs_data_get_double(settings, &quot;feather&quot;);
  tf-&gt;maskEveryXFrames = (int)obs_data_get_int(settings, &quot;mask_every_x_frames&quot;);
  tf-&gt;maskEveryXFramesCount = (int)(0);
  tf-&gt;blurBackground = obs_data_get_int(settings, &quot;blur_background&quot;);
//...
</pre></div>


<h2 class="wp-block-heading">Conclusion</h2>



<p>The OBS Background Removal Plugin has emerged as a valuable tool for content creators seeking virtual green screen capabilities and seamless background removal in OBS. Through a well-structured architecture, efficient GPU utilization, and integration with neural network models, the plugin delivers high-quality results in real-time. By exploring the code walkthrough provided above, developers can gain insights into building similar plugins and harness the power of OBS&#8217;s plugin system.</p>



<p>As the plugin continues to evolve and improve, its widespread adoption within the streaming community highlights the value it brings to content creators. If you&#8217;re interested in delving deeper into OBS plugin development or learning more about the OBS Background Removal Plugin, refer to the official OBS plugin documentation for comprehensive resources and guidance.</p>
]]></content:encoded>
					
		
		
			</item>
		<item>
		<title>AWS Lambda NodeJS Telegram Bot with Typescript, Serverless and DynamoDB</title>
		<link>https://www.morethantechnical.com/blog/2023/05/18/aws-lambda-nodejs-telegram-bot-with-typescript-serverless-and-dynamodb/</link>
		
		<dc:creator><![CDATA[Roy]]></dc:creator>
		<pubDate>Thu, 18 May 2023 04:40:02 +0000</pubDate>
				<category><![CDATA[cloud]]></category>
		<category><![CDATA[code]]></category>
		<category><![CDATA[javascript]]></category>
		<category><![CDATA[programming]]></category>
		<category><![CDATA[Web]]></category>
		<guid isPermaLink="false">https://www.morethantechnical.com/?p=2227</guid>

					<description><![CDATA[Sharing a bit of experience building a telegram bot with Serverless, AWS Lambda and TypeScript. In this tutorial, we will explore how to build a simple Telegram bot using serverless with TypeScript and AWS Lambda. We&#8217;ll leverage the power of AWS services such as API Gateway and DynamoDB to create a highly scalable and efficient [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>Sharing a bit of experience building a telegram bot with Serverless, AWS Lambda and TypeScript.</p>



<p>In this tutorial, we will explore how to build a simple Telegram bot using <code>serverless</code> with TypeScript and AWS Lambda. We&#8217;ll leverage the power of AWS services such as API Gateway and DynamoDB to create a highly scalable and efficient bot. While there are various tutorials available online, this guide aims to provide a more comprehensive and detailed approach. So, let&#8217;s dive in!</p>



<span id="more-2227"></span>



<figure class="wp-block-embed is-type-video is-provider-youtube wp-block-embed-youtube wp-embed-aspect-16-9 wp-has-aspect-ratio"><div class="wp-block-embed__wrapper">
<iframe loading="lazy" title="Telegram Bot Typescript Serverless AWS Lambda DynamoDB [Code Walkthrough]" width="580" height="326" src="https://www.youtube.com/embed/MtWUKFcljKg?feature=oembed" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen></iframe>
</div></figure>



<h2 class="wp-block-heading">Setting Up the Server</h2>



<p>To begin, we define a CloudFormation template using <code>serverless</code> that includes a single function serving as the entry point for our Telegram bot. This function, called &#8220;webhook,&#8221; resides in the index module and is responsible for handling incoming messages. TypeScript allows us to benefit from type safety, providing clear understanding of the event types passed from the API Gateway proxy into the Lambda function. Although TypeScript code may appear more verbose, it proves advantageous in the long run.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: yaml; title: ; notranslate">
functions:
  webhook:
    handler: index.webhook
    events:
      - http:
          path: webhook
          method: post
</pre></div>


<p>This is the function entry in <code>index.ts</code></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
export const webhook = async (
  event: APIGatewayProxyEvent
): Promise&lt;APIGatewayProxyResult&gt; =&gt; {
  const bodyParsed = JSON.parse(event.body!);
  console.log(&quot;bodyParsed&quot;, bodyParsed);
  // ...
}
</pre></div>


<h2 class="wp-block-heading">Configuring DynamoDB</h2>



<p>In addition to the server setup, we create a DynamoDB table to store our bot&#8217;s data. This table includes essential parameters and an index to facilitate efficient querying and content modification. While the complete list of attributes is not mentioned here, we focus on indexing for our specific use case of handling to-do items within the bot.</p>



<p>This is how the config looks in <code>serverless.yaml</code></p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: yaml; title: ; notranslate">
resources:
  Resources:
    ExampleDynamoDbTable:
      Type: 'AWS::DynamoDB::Table'
      DeletionPolicy: Retain
      Properties:
        AttributeDefinitions:
          -
            AttributeName: id
            AttributeType: S
          -
            AttributeName: chatId
            AttributeType: S
        KeySchema:
          -
            AttributeName: chatId
            KeyType: HASH
          -
            AttributeName: id
            KeyType: RANGE
        GlobalSecondaryIndexes:
          -
            IndexName: chatId-index
            KeySchema:
              -
                AttributeName: chatId
                KeyType: HASH
            Projection:
              ProjectionType: ALL
        BillingMode: PAY_PER_REQUEST
        TableName: ${self:provider.environment.DYNAMODB_TABLE}
</pre></div>


<p>The, for example in the TS side we can make operations on the DynamoDB table:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
// Find all todos for this chatId
const r = await dynamoDb
    .query({
          ...params,
          KeyConditionExpression: &quot;chatId = :chatId&quot;,
          ExpressionAttributeValues: {
            &quot;:chatId&quot;: chatId.toString(),
          },
        })
        .promise();
if (r.Items == undefined || r.Items!.length == 0) {
    await bot.sendMessage(chatId, `0️⃣ No TODOs found`);
    globalResolve(&quot;ok&quot;);
    return;
}
let message = &quot;&quot;;
for (const todo of r.Items!) {
    message += `➖ ${todo.what}\n`;
}
await bot.sendMessage(chatId, `📝 Current TODOs:\n${message}`);

</pre></div>


<h2 class="wp-block-heading">Handling Telegram Messages</h2>



<p>The entry point for our bot is the Lambda function responsible for processing incoming messages. To achieve this, we parse the message and chat ID from the message&#8217;s body. Leveraging the powerful &#8220;node-telegram-bot-api&#8221; package, we process the parsed message and send it to the bot for further handling. However, since we are using a Lambda function from AWS, we need to parse the message from Telegram and utilize the &#8220;processUpdate&#8221; function provided by the &#8220;node-telegram-bot-api&#8221; package. This sets off a chain of events that execute the bot&#8217;s commands.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
const bot = new TelegramBot(token);

let globalResolve: (value: any) =&gt; void = () =&gt; {};

export const webhook = async (
  event: APIGatewayProxyEvent
): Promise&lt;APIGatewayProxyResult&gt; =&gt; {
  const bodyParsed = JSON.parse(event.body!);
  console.log(&quot;bodyParsed&quot;, bodyParsed);
  await new Promise((resolve, reject) =&gt; {
    globalResolve = resolve;
    bot.processUpdate(bodyParsed);
    // set timeout to 3 seconds to resolve the promise in case the bot doesn't respond
    setTimeout(() =&gt; {
      // make sure to resolve the promise in case of timeout as well
      // do not reject the promise, otherwise the lambda will be marked as failed
      resolve(&quot;global timeout&quot;);
    }, 3000);
  });

  // respond to Telegram that the webhook has been received.
  // if this is not sent, telegram will try to resend the webhook over and over again.
  return {
    statusCode: 200,
    body: JSON.stringify({ message: &quot;function executed successfully&quot; }),
  };
};
</pre></div>


<p>Notice that I&#8217;m using a global promise to hang until all the bot&#8217;s work is done. This is because Lambda will not wait for any async operations. The TelegramBot is an event queue so things happen out of sync. The bot handlers will resolve the promise and then the lambda will complete with a 200 status.</p>



<h2 class="wp-block-heading">Implementing Bot Commands</h2>



<p>We introduce various bot commands such as listing to-do items, adding new items, and removing existing ones. By following standard boilerplate code, we enable the bot to perform these actions. The complete code for these commands and additional functionalities can be found on GitHub for reference.</p>



<p>For example the <code>/add</code> command:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: plain; title: ; notranslate">
bot.onText(
  /\/add (.+)/,
  async (msg: TelegramBot.Message, match: RegExpExecArray | null) =&gt; {
    const chatId = msg.chat.id;
    const what = match!&#x5B;1];
    const id = randomUUID();
    try {
      await dynamoDb
        .put({
          ...params,
          Item: {
            id,
            chatId: chatId.toString(),
            what,
          },
        })
        .promise();
      await bot.sendMessage(chatId, `✅ Added TODO: ${what}`);
    } catch (error) {
      console.error(error);
      await bot.sendMessage(chatId, `❌ Error adding TODO: ${what} (${error})`);
    }
    globalResolve(&quot;ok&quot;);
  }
);
</pre></div>


<p>Note that I&#8217;m calling the global resolve to signal the finish of the bot&#8217;s work for this message and clear the Lambda run.</p>



<h2 class="wp-block-heading">Deploying the Bot</h2>



<p>With the server and bot code ready, we need to deploy the solution. Using the serverless framework, we run the deploy command, which sets up the infrastructure on AWS, including the Lambda function and API Gateway. After deployment, we obtain the HTTPS endpoint URL, which we need to configure as the webhook for our Telegram bot. This connection enables Telegram to send messages to our deployed bot.</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: bash; title: ; notranslate">
$ ./node_modules/.bin/serverless deploy
</pre></div>


<p>You can also watch your AWS account for the Lambda&#8217;s existence, as well as DynamoDB and the API Gateway.</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="582" src="https://www.morethantechnical.com/wp-content/uploads/2023/05/Screenshot-2023-05-17-at-11.30.39-AM-1024x582.png" alt="" class="wp-image-2234" srcset="https://www.morethantechnical.com/wp-content/uploads/2023/05/Screenshot-2023-05-17-at-11.30.39-AM-1024x582.png 1024w, https://www.morethantechnical.com/wp-content/uploads/2023/05/Screenshot-2023-05-17-at-11.30.39-AM-300x170.png 300w, https://www.morethantechnical.com/wp-content/uploads/2023/05/Screenshot-2023-05-17-at-11.30.39-AM-768x436.png 768w, https://www.morethantechnical.com/wp-content/uploads/2023/05/Screenshot-2023-05-17-at-11.30.39-AM-1200x682.png 1200w, https://www.morethantechnical.com/wp-content/uploads/2023/05/Screenshot-2023-05-17-at-11.30.39-AM.png 1440w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>You&#8217;re going to have to register your webhook with Telegram by running the following command:</p>


<div class="wp-block-syntaxhighlighter-code "><pre class="brush: jscript; title: ; notranslate">
curl --request POST --url &quot;https://api.telegram.org/bot&lt;BOT_TOKEN&gt;/setWebhook&quot; --header 'content-type: application/json' --data '{&quot;url&quot;: &quot;&lt;URL&gt;&quot;}'
</pre></div>


<p>Use the URL that you received from <code>serverless deploy</code> for the POST endpoint. At that point the bot lambda should start receiving messages from Telegram.</p>



<p>Here&#8217;s proof:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="940" src="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-1-1024x940.png" alt="" class="wp-image-2236" srcset="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-1-1024x940.png 1024w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-1-300x276.png 300w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-1-768x705.png 768w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-1-1536x1411.png 1536w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-1-1200x1102.png 1200w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-1-1980x1818.png 1980w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-1.png 1984w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Monitoring and Debugging</h2>



<p>To monitor and debug our bot, we utilize various tools provided by AWS. CloudWatch allows us to view logs generated by our Lambda function, helping us identify any issues and understand the flow of data. Additionally, DynamoDB provides a handy interface to verify the stored data and perform tests on the bot&#8217;s functionality. Utilizing console logs and try-catch blocks for error handling and logging ensures a smooth debugging experience.</p>



<p>Cloudwatch: (all <code>console.log</code>s from your code will appear as lines there)</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="506" src="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-2-1024x506.png" alt="" class="wp-image-2237" srcset="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-2-1024x506.png 1024w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-2-300x148.png 300w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-2-768x379.png 768w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-2-1536x758.png 1536w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-2-2048x1011.png 2048w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-2-1200x593.png 1200w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-2-1980x978.png 1980w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<p>The Lambda itself will also show the invocations:</p>



<figure class="wp-block-image size-large"><img loading="lazy" decoding="async" width="1024" height="386" src="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-3-1024x386.png" alt="" class="wp-image-2238" srcset="https://www.morethantechnical.com/wp-content/uploads/2023/05/image-3-1024x386.png 1024w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-3-300x113.png 300w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-3-768x289.png 768w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-3-1536x578.png 1536w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-3-2048x771.png 2048w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-3-1200x452.png 1200w, https://www.morethantechnical.com/wp-content/uploads/2023/05/image-3-1980x746.png 1980w" sizes="auto, (max-width: 1024px) 100vw, 1024px" /></figure>



<h2 class="wp-block-heading">Conclusion</h2>



<p>By following this tutorial, you&#8217;ve learned how to build a serverless Telegram bot using TypeScript and AWS Lambda. Leveraging AWS services like API Gateway and DynamoDB, we&#8217;ve created a scalable and efficient bot infrastructure. TypeScript&#8217;s type safety provides clarity in handling events, while the &#8220;node-telegram-bot-api&#8221; package simplifies interaction with Telegram&#8217;s API. With the power of AWS and the ease of TypeScript, you can create sophisticated bots tailored to your requirements. The complete code and instructions for this project are available on GitHub, allowing you to start building your own bot right away. Happy bot building!</p>



<p><br></p>
]]></content:encoded>
					
		
		
			</item>
	</channel>
</rss>
