<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet href="/rss.xsl" type="text/xsl"?><rss version="2.0" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>core</title><description>Random rants and fun tech things</description><link>https://blog.teamtuck.xyz</link><item><title>Blog Revamp</title><link>https://blog.teamtuck.xyz/posts/blog-revamp</link><guid isPermaLink="true">https://blog.teamtuck.xyz/posts/blog-revamp</guid><description>Yet another blog revamp</description><pubDate>Wed, 20 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I think over the last 4-5 years, I&apos;ve made a number of attempts at keeping a blog, writing a few posts a year, and just being happy with it in general.  Life gets busy, I may not have much to say, or whatever, but typically, it&apos;s the theming and overall look at the blog that I just don&apos;t like.  I&apos;ve even tried to write custom CSS and try various frameworks like Tailwind and Bulma, but I just can&apos;t seem to like what I come up with most of the time.  Even if I do come up with something, the whole blog system/setup just gets complicated more than what I want.&lt;/p&gt;
&lt;p&gt;This time, I&apos;m trying Astro and a pretty good looking theme that just happened to find.  Sure, it was a little involved getting Node and NPM set up just right, but it seems to be working.&lt;/p&gt;
&lt;p&gt;Let&apos;s see how long I can keep this going...&lt;/p&gt;
</content:encoded><author>sixstorm</author></item><item><title>LAN Radio for 2025</title><link>https://blog.teamtuck.xyz/posts/lan-radio</link><guid isPermaLink="true">https://blog.teamtuck.xyz/posts/lan-radio</guid><description>Music your way - on your LAN</description><pubDate>Thu, 21 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;I&apos;ve done my fair share of dabbling when it comes to serving up any video or audio that I have on my servers, using all kinds of server-side and client-side software.  But there is one piece of software that I&apos;ve never really understood or wrangled until recently:  IceCast.  IceCast is a server-side software that acts as a relay and &quot;broadcasts&quot; incoming audio streams out to the world.  The idea is that you create a source, i.e. an audio file or a playlist file, and send it to IceCast, so that you can listen to it with a client like VLC Media Player from anywhere on your LAN or in the world.  In fact, you can have many streams coming from a single IceCast server, as it may have many streams coming to it.&lt;/p&gt;
&lt;p&gt;[!WARNING] My server is running Ubuntu 24.04 LTS, YMMV if you are following along.&lt;/p&gt;
&lt;h1&gt;My Obscure Music Collection&lt;/h1&gt;
&lt;p&gt;I love music.  Plain and simple.  But over the years, I&apos;ve discovered that even a subscription to Spotify or Apple Music and having any song of my desire to listen to, there is still an obscure &quot;collection&quot; of music that I can&apos;t get anywhere except for YouTube.  This could be anything from live concerts and recordings, podcast clips, or even YouTube videos, in the form of audio only.  YouTube in 2025 is not the greatest platform due to the overkill amount of ads and the annoying &quot;Youtuber&quot; culture, but it does still serve a purpose of sourcing this type of media.  There is also the discussion of data preservation but that&apos;s another discussion for another time.&lt;/p&gt;
&lt;p&gt;But probably the biggest genre of music that I download from YouTube has to be ambient sounds and soundtracks.  Think spooky Halloween ambiance, rainy autumn days with thunder, dark ambient mixes, or jazz music by the fire in a coffee house.  Just fun, random stuff to have playing in the background (it gets quiet in the house during the day sometimes).&lt;/p&gt;
&lt;h1&gt;The Workflow&lt;/h1&gt;
&lt;p&gt;My current workflow is using 2 Docker instances of Pinchflat.  In case you don&apos;t know, Pinchflat is an app that allows you to provide a YouTube channel or playlist, and download those videos in many different formats (1080p, 720p, audio only, etc).  It will check these sources periodically for new content and notify you via AppRise for your platform of choice.&lt;/p&gt;
&lt;p&gt;Why do I use 2 instances instead of just 1?  I&apos;ve recently figured out that Jellyfin does not like to have 2 libraries pointed to the same folder, i.e. a parent folder for one library source and a child folder for another library source.  Pinchflat also does not support download locations to different folders, so I just run 2 instances:  1 for video and 1 for audio.  It&apos;s a crappy solution but it works.&lt;/p&gt;
&lt;p&gt;There are a lot of &quot;one off&quot; tracks that I find, so the best way to accomplish the goal is to create a &quot;Random Music&quot; playlist in YouTube, then add the playlist URL as a source in Pinchflat.  I can then add videos to this playlist as I come across them.&lt;/p&gt;
&lt;p&gt;Once Pinchflat has downloaded my media, it is all neatly stored and organized in my &quot;YTMusic&quot; folder on my server.&lt;/p&gt;
&lt;h1&gt;IceCast&lt;/h1&gt;
&lt;p&gt;This one is pretty simple.  I was trying to keep everything in Docker containers, but I found that it was simpler to just install the native packages.  Some IceCast Docker containers were modified and just didn&apos;t work well for what I wanted.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo apt install icecast2
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Before the installation begins, you will be prompted with a few questions, regarding the hostname and the password for both the admin web UI, mountpoints, and relay (remember this for later).  I set my host to &quot;localhost&quot; since I will be running this on my LAN only for now.  Once installed, you can revisit &apos;/etc/icecast2/icecast.xml&apos; for the configuration file.  Verify that you can get to your web UI by visiting &quot;http://localhost:8000/admin&quot;.  And that&apos;s it!  IceCast should accept anything incoming via port 8000 and with the credentials you set up during the installation process.&lt;/p&gt;
&lt;h1&gt;Creating a Source&lt;/h1&gt;
&lt;p&gt;This was the most frustrating part of the project for sure.  My goal was to use LiquidSoap to search through my music files, find files that have specific keywords in them (&quot;halloween&quot;, &quot;space&quot;, &quot;live&quot;, etc), and then send them to IceCast for broadcast.  However, I could not find a way with LiquidSoap to accomplish this; there seemed to be missing plugins and functionality.  The only way I could get it to work was to create playlist files via the &quot;find&quot; command, and use it like that, but I&apos;m not a fan of that solution.  I may revisit it in the future or even try a Docker container at some point.&lt;/p&gt;
&lt;p&gt;So I decided to take a step back and try something extremely simple and more direct:  FFMPEG.  FFMPEG has native ways to send audio directly to IceCast!&lt;/p&gt;
&lt;p&gt;Here is the command that I used to test everything out:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;ffmpeg -re -i INPUT.m4a -c:a libmp3lame -b:a 192k -vn -f mp3 icecast://source:SOURCE_PWD@localhost:8000/stream.mp3
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;This tells FFMPEG to encode the M4A audio file into a MP3 at 192K bitrate and setup a mountpoint in Icecast called &quot;stream.mp3&quot;.  I could then open VLC, open a network stream, and put in the address &quot;http://IP:8000/stream.mp3&quot; to listen to my specified audio file.&lt;/p&gt;
&lt;h1&gt;Python Enters the Chat&lt;/h1&gt;
&lt;p&gt;But what about searching files based on keywords?  What about any other actions besides sending a single audio file to the Icecast server?  Python to the rescue!&lt;/p&gt;
&lt;p&gt;I wrote a Python script, with the help of AI (I was lazy today, don&apos;t judge), to &quot;walk&quot; my folder of YouTube Music, find the files based on keywords, shuffle them, and stream them.  Once all files are done playing, it will do it all over again.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;import os
import subprocess
import time

def stream_audio_to_icecast(directory, keywords, icecast_url, source_password, mountpoint):
    &quot;&quot;&quot;
    Searches for audio files containing keywords in their filenames and streams them to Icecast.

    Args:
        directory (str): The directory to search for audio files.
        keywords (list): A list of keywords to search for in filenames.
        icecast_url (str): The Icecast server URL (e.g., &quot;hostname:port&quot;).
        source_password (str): The Icecast source password.
        mountpoint (str): The Icecast mountpoint (e.g., &quot;/stream.mp3&quot;).
    &quot;&quot;&quot;
    found_files = []
    for root, _, files in os.walk(directory):
        for file in files:
            if file.lower().endswith(&quot;.m4a&quot;) and any(keyword.lower() in file.lower() for keyword in keywords):
                found_files.append(os.path.join(root, file))

    if not found_files:
        print(f&quot;No M4A files found with keywords {keywords} in directory {directory}&quot;)
        return

    for m4a_file in found_files:
        print(f&quot;Streaming: {m4a_file}&quot;)
        command = [
            &quot;ffmpeg&quot;,
            &quot;-re&quot;,  # Read input at native frame rate, useful for live streaming.
            &quot;-i&quot;,
            mp3_file,
            &quot;-c:a&quot;,
            &quot;libmp3lame&quot;,
            &quot;-b:a&quot;,
            &quot;192k&quot;,  # Adjust bitrate as needed
            &quot;-vn&quot;,
            &quot;-f&quot;,
            &quot;mp3&quot;,
            f&quot;icecast://source:{source_password}@{icecast_url}{mountpoint}&quot;,
        ]
        try:
            subprocess.run(command, check=True)
            print(f&quot;Successfully streamed {m4a_file}&quot;)
        except subprocess.CalledProcessError as e:
            print(f&quot;Error streaming {m4a_file}: {e}&quot;)
        except FileNotFoundError:
            print(&quot;FFmpeg not found. Please ensure it&apos;s installed and in your PATH.&quot;)

if __name__ == &quot;__main__&quot;:
    # Customize these variables
    search_directory = &quot;/path/to/music&quot;  # Replace with the actual directory.
    search_keywords = [&quot;jazz&quot;, &quot;ambient&quot;, &quot;ambience&quot;, &quot;cyberpunk&quot;]  # Replace with keywords in filenames
    icecast_server_url = &quot;localhost:8000&quot;  # Replace with your Icecast server URL and port
    icecast_source_password = &quot;hackme&quot;  # Replace with your Icecast source password.
    icecast_mountpoint = &quot;/stream.mp3&quot;  # Replace with your Icecast mountpoint.

    while True:
        stream_audio_to_icecast(search_directory, search_keywords, icecast_server_url, icecast_source_password, icecast_mountpoint)
        time.sleep(5)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;After getting this script into action and testing it out manually, I thought it would be important to make sure that I could control it from SSH, so I created a simple SystemD service:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;[Unit]
Description=Icecast MP3 Streamer
After=network.target

[Service]
ExecStart=/usr/bin/python3 /path/to/stream.py
WorkingDirectory=/path/to
User=user  # Replace with the user that should run the script
Group=group    # Replace with the group that should run the script
Restart=on-failure
RestartSec=5s
StandardOutput=journal
StandardError=journal

[Install]
WantedBy=multi-user.target
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Reload the SystemD Daemon:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl daemon-reload
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Enable the service:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl enable icecast-streaming.service
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Start and verify the service:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;sudo systemctl start icecast-streaming.service
sudo systemctl status icecast-streaming.service
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And just like that, you have a working radio station that runs 24/7, based on your keywords!&lt;/p&gt;
&lt;h1&gt;Honorable Mention&lt;/h1&gt;
&lt;p&gt;If you want something that is more feature full but definitely more involved, I would recommend checking out &lt;a href=&quot;https://www.azuracast.com/&quot;&gt;Azuracast&lt;/a&gt;.  I&apos;ve ran this before via Docker and although it worked, getting multiple streams to work was a little bit of a pain.  I don&apos;t plan to include any jingles or stations IDs into my mix, so I really don&apos;t need the advanced tools.  However, you might.&lt;/p&gt;
&lt;p&gt;Also, depending on how much control you want, a simple IceCast + LiquidSoap setup might be for you.  I did get LiquidSoap working just pointing it to the parent music folder, but I couldn&apos;t filter based on keywords.&lt;/p&gt;
&lt;h1&gt;Future Plans&lt;/h1&gt;
&lt;p&gt;I have no idea how much I will use this, but now that I&apos;m home alone during the day a little more than usual (school season), I like to have background noise going on.  I would like to have a little bit of remote control and maybe even play things based on a schedule (play Halloween stuff between September 1st-November 1st, Jazz stuff around the holidays, etc).  And all of this can be done via Python, so I&apos;m pretty excited to get some traction on that project.&lt;/p&gt;
&lt;p&gt;Also, my son listens to his &quot;sounds&quot; at night while he sleeps, so this might be a good way to setup a simple radio station with his tunes and stream to his Raspberry Pi.&lt;/p&gt;
&lt;p&gt;Hopefully this might help someone who has been curious about creating their own simple radio station, or just how FFMPEG, IceCast or LiquidSoap works.&lt;/p&gt;
</content:encoded><author>sixstorm</author></item><item><title>LAN Radio with LiquidSoap!</title><link>https://blog.teamtuck.xyz/posts/lan-radio-liquidsoap</link><guid isPermaLink="true">https://blog.teamtuck.xyz/posts/lan-radio-liquidsoap</guid><description>LiquidSoap is alright</description><pubDate>Thu, 28 Aug 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;In my &lt;a href=&quot;https://blog.teamtuck.xyz/posts/lan-radio/&quot;&gt;last post&lt;/a&gt;, I explained how I&apos;m using IceCast and Python to create my own LAN radio station.  I&apos;ve been using it for the last week, listening on via VLC on my homemade speaker, and it&apos;s been really fun to just have some noise going on in the background throughout the day.&lt;/p&gt;
&lt;p&gt;But I&apos;ve also dabbled a little more with &lt;a href=&quot;https://www.liquidsoap.info&quot;&gt;LiquidSoap&lt;/a&gt; (LS) to try some other things.  LS may not be able to filter properly on filenames within a script (or at least I don&apos;t know how to do that yet), but you can still setup some easy LS scripts and harness its power pretty easily.&lt;/p&gt;
&lt;h1&gt;Playlist&lt;/h1&gt;
&lt;p&gt;If you want to search for keywords in filenames to play via LS, you will need to create a playlist file; I&apos;ll use a M3U file for this example.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;find /music -type f \( -iname &quot;*halloween*&quot; -o -iname &quot;*spooky*&quot; \) | shuf &amp;gt; /tmp/halloween_playlist.m3u
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this command, I&apos;m searching for keywords &quot;halloween&quot; and &quot;spooky&quot; in the /music directory, using &quot;shuf&quot; to shuffle the results, then outputting them to /tmp/halloween_playlist.m3u.  Once you have your playlist file, you can create a LS script to &quot;transmit&quot; them to IceCast:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;touch ~/radio.liq
chmod +x ~/radio.liq  # Make executable for direct calls
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Open the LIQ file with your favorite text editor and drop this in:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/liquidsoap
source = mksafe(playlist(&quot;/tmp/halloween_playlist.m3u&quot;, mode=&quot;randomize&quot;))

output.icecast(
        %mp3(bitrate=320, stereo=true),
        mount=&quot;stream&quot;,
        host=&quot;localhost&quot;,
        port=8000,
        password=&quot;hackme&quot;,
        description=&quot;Halloween LiquidSoap Stream&quot;,
        source)
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;In this script, we create a &quot;source&quot;, pointing to the M3U playlist file we created and setting the mode of playback to &quot;randomize&quot;.  Then, we define the output as IceCast, 320 bitrate in stereo, some other important properties, and we&apos;re done.  Finally, run the script directly and check IceCast to see that it&apos;s an active mountpoint.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;./radio.liq
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;On your client of choice, you can open the network stream &quot;http://&amp;lt;SERVER_IP&amp;gt;:8000/stream&quot; and listen to your tunes!&lt;/p&gt;
&lt;h1&gt;Folder&lt;/h1&gt;
&lt;p&gt;What if you want to just point LS at your music folder and listen to everything?  You can swap out the playlist filepath for a directory and LS will look in that directory recursively.&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;#!/usr/bin/liquidsoap
source = mksafe(playlist(&quot;/music&quot;, mode=&quot;randomize&quot;))

output.icecast(
        %mp3(bitrate=320, stereo=true),
        mount=&quot;stream&quot;,
        host=&quot;localhost&quot;,
        port=8000,
        password=&quot;hackme&quot;,
        description=&quot;All Music LiquidSoap Stream&quot;,
        source)
&lt;/code&gt;&lt;/pre&gt;
&lt;h1&gt;Side Notes&lt;/h1&gt;
&lt;p&gt;One thing to note is that by default, LS will add an automatic crossfade and play all available items indefinitely.&lt;/p&gt;
&lt;p&gt;Even though I don&apos;t have one of these LS scripts in a SystemD service yet, I&apos;ve enjoyed running them manually and just listening to my collection of music during my work day.  I hope to create a few services based on different scripts that I write, and then I can just use my client to select which stream I want to listen to.&lt;/p&gt;
&lt;p&gt;LS is a pretty powerful tool if you care to do more than just play random music.  For example, you can create a schedule to where LS will play specific playlists between certain times, or even throw in some jingles here and there using weights.  Heck, you can even setup and stream video, not just audio, due to the combination of LS and FFMPEG!  I haven&apos;t tried this yet, but it&apos;s on my list of things to test.&lt;/p&gt;
</content:encoded><author>sixstorm</author></item><item><title>Random Linux - 2025-11-12</title><link>https://blog.teamtuck.xyz/posts/randomlinux111225</link><guid isPermaLink="true">https://blog.teamtuck.xyz/posts/randomlinux111225</guid><description>Arch+Hyprland - Fun with an extra Mini PC</description><pubDate>Wed, 12 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;3 years ago, I was &quot;given&quot; a &lt;a href=&quot;https://www.servethehome.com/hp-elitedesk-800-g3-mini-ce-review-project-tinyminimicro/&quot;&gt;HP Elitedesk 800 G3&lt;/a&gt; from my previous employer since they were going to get rid of it.  One of the hardware guys explained to me that they would have to pull the SSD out and destroy it, but when I found one in there anyway, he just said &quot;Oops&quot;.  Since then, I have mainly used this as a secondary server, running Ubuntu Server and basically just being a Docker host, sandbox and Jellyfin transcoder (Intel QuickSync is nice).  It wasn&apos;t until I had to purchase all new hardware for my main server that this mini PC was &quot;decommissioned&quot; and taken out of the server room.&lt;/p&gt;
&lt;p&gt;So what is there to do with a spare PC?  Well ... anything!&lt;/p&gt;
&lt;p&gt;Here are a few things that I&apos;ve been testing this week on it.&lt;/p&gt;
&lt;h1&gt;Arch + Hyprland&lt;/h1&gt;
&lt;p&gt;For some reason, Omarchy has been popping up on my Youtube feed and I decided to watch a few videos about it.  I really enjoy the philosophy behind it (keyboard first and fast install/stand up time), but it&apos;s a developer&apos;s OS that doesn&apos;t fit my needs.  I&apos;ve always liked the idea behind fast and light operating systems that just get out of the way, something that is quick to install and get going from scratch.  But the real reason why I even bring this up is Hyprland.  I&apos;ve never used it, much less a window tiling manager (I&apos;m not the biggest fan of them), so I thought I would give it a try.&lt;/p&gt;
&lt;p&gt;I performed a basic Arch Linux install on the HP, used the Hyprland preset built into archinstall, and added a few applications on top like waybar, yay, brave, etc.  Hyprland is interesting to say the least and isn&apos;t that hard to use or customize, but it does not flow with my day to day work flow.  Being a Windows Administrator does not allow for a keyboard first approach; the mouse is a key tool for my work.  Sure, the mouse works, but doesn&apos;t it take away from a tiling window managers strengths?  I didn&apos;t try any games just to see how it would work.&lt;/p&gt;
&lt;p&gt;Needless to say, if I did more developer or Linux administration work, Hyprland would be an interesting tool to use.&lt;/p&gt;
&lt;h1&gt;Custom Arch ISO&lt;/h1&gt;
&lt;p&gt;Before I decided to move on from Hyprland, I tried my hand at creating a custom Arch ISO, prebuilt with my packages and customizations of choice.  The inspiration came from Dom&apos;s Blog (&lt;a href=&quot;https://blog.ctms.me/posts/2025-08-08-pi-zero-bug-out-server/&quot;&gt;Building a low-powered offline and offgrid bug-out media server&lt;/a&gt;), mimicking the scenario where you didn&apos;t have Internet, but you do have computer parts and a power source like a battery bank!  My spin on this is that I had a custom Arch ISO that I could either run live from a USB stick or install on any computer.  Either choice would give you a XFCE desktop for speed, apps like MPV, Firefox, and Neovim, and other files like movies, music, PDFs, eBooks, and maps of the local area.  I mean, who could survive a long term outage without some episodes of Friends?&lt;/p&gt;
&lt;p&gt;I didn&apos;t spend a whole lot of time researching this, so I (I know...) leaned on ChatGPT and Grok to help me out with a basic crash course.  Needless to say, their dataset is NOT up to date, so I had quite a few issues getting things like XFCE autologin and custom scripts to run properly on ISO creation.  Maybe I can put some more time into this and do more thorough testing in the future.  I just thought it would be cool to have some kind of a &quot;post-apocalyptic&quot; distro of Linux ready to go with everything ready for use.&lt;/p&gt;
&lt;p&gt;A few last things that I did not try (yet):&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;Kiwix and an offline copy of both the Arch Wiki and Wikipedia with images&lt;/li&gt;
&lt;li&gt;Wireless AP (I need hardware for this) so other devices could connect&lt;/li&gt;
&lt;/ul&gt;
&lt;h1&gt;What&apos;s Next&lt;/h1&gt;
&lt;p&gt;It&apos;s always fun to have a spare PC sitting around for when you have a crazy idea or two.  I actually just installed Linux Mint onto this HP Mini PC earlier this morning, just to test this distro out and try some other oddball ideas.&lt;/p&gt;
&lt;p&gt;This also sparked an idea based on a project that I&apos;ve been working on over the last two years, so maybe I&apos;ll write about that as well.&lt;/p&gt;
</content:encoded><author>sixstorm</author></item><item><title>New Steam Hardware for 2026</title><link>https://blog.teamtuck.xyz/posts/newsteamhardware</link><guid isPermaLink="true">https://blog.teamtuck.xyz/posts/newsteamhardware</guid><description>Steam continues to win</description><pubDate>Mon, 17 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;As I have been taking a small break from gaming and YouTube this week (personal story here), I missed out on the new &lt;a href=&quot;https://store.steampowered.com/sale/hardware&quot;&gt;Steam hardware announcement&lt;/a&gt; from last week.  If you haven&apos;t seen it, please check it out because it&apos;s an interesting one!&lt;/p&gt;
&lt;h1&gt;Steam Controller&lt;/h1&gt;
&lt;p&gt;I&apos;m not a huge controller fan, but for games like GTA, some arcade games, or racing titles, I prefer my XBOX Elite 2 controller (fun story, I bought this from Microsoft&apos;s campus a few years ago on a trip).  I do have an original Steam controller that I&apos;ve used a few times, but again, I just don&apos;t use a controller enough in KBM games to justify using the trackpads.  I&apos;m just keeping it as a part of fun &quot;history&quot;.&lt;/p&gt;
&lt;p&gt;However, this new Steam controller looks promising.  Trackpads are there if you need them, it looks like a comfortable, light weight design, including a magnetic charging &quot;puck&quot; (no extra purchase needed).  I will definitely keep this in mind if my XBOX controller were to ever die.&lt;/p&gt;
&lt;p&gt;My guess this will cost around $50 USD and be a hard piece of hardware to buy at first due to demand.&lt;/p&gt;
&lt;h1&gt;Steam Machine&lt;/h1&gt;
&lt;p&gt;We&apos;ve had mini-ITX PCs available for a long time, but nothing like what the Steam Machine offers.  This is a simple, &quot;console-like&quot; mini PC that is simple to use, simple to purchase with 2 configurations (512GB and 1TB), and rivals the identity of a XBOX or Playstation.  Probably the biggest features of this is not only playing PC games, but using any controller you want (XBOX, PS, Switch, Steam Controller), using it as a desktop PC, fantastic emulation out of the box (Switch, PS2, PS3, etc), or even using it as a home theater PC (if you can get streaming via Linux to work at full quality).&lt;/p&gt;
&lt;p&gt;The two things that I am curious about are the performance and the price.&lt;/p&gt;
&lt;p&gt;Valve claims that the Steam Machine can do 4K gaming at 60FPS using AMD&apos;s FSR technology.  This is obviously going to depends on what game that is being played, but I&apos;d say that this will handle indies and most AAA titles from 2021-ish and prior with no problem.  I&apos;ll be very interested to see how it plays with games like Red Dead Redemption 2, Cyberpunk 2077, and Doom The Dark Ages.  Yes, Doom TDA is a newer title with high hardware demands (ray tracing forced, boooo), but it was recently Steam Deck Verified with developer made presets.  It doesn&apos;t look pretty but it runs.&lt;/p&gt;
&lt;p&gt;My guess on the pricing is that the base model will start at $999 USD, as I doubt it will undercut current console pricing.  Valve will need to make the price as close as possible to make it a valid competitor.&lt;/p&gt;
&lt;h1&gt;Steam Frame&lt;/h1&gt;
&lt;p&gt;Ever since the &lt;a href=&quot;https://www.apple.com/apple-vision-pro/&quot;&gt;Apple Vision Pro&lt;/a&gt; was announced, the one feature that made me remotely interested in it was the fact that you could watch a movie, surf the web, or play a game on a virtual &quot;screen&quot; as big as you wanted.  Apple even demoed this to where you could be in a &lt;a href=&quot;https://support.apple.com/guide/apple-vision-pro/use-environments-tanb58c3cfaf/visionos&quot;&gt;&quot;virtual environment&quot;&lt;/a&gt;, watching your favorite content, even on the moon!  This is what intrigued me the most.  Imagine sitting down with a virtual headset and some noise-canceling headphones on to enjoy your favorite movie, show or video game in full immersion.  This is what I want!&lt;/p&gt;
&lt;p&gt;So Valve is making their attempt at doing some similar in that you can basically do the same thing:  play smaller, indie titles directly from the headset or stream games from your PC using a Wi-Fi adapter.  I&apos;m not sure if you can stream just any game or if there are some limitations to it.  I will definitely be interested to see what the reviews say and yes, the price point, as well.&lt;/p&gt;
&lt;p&gt;There is some voodoo magic with Proton and &lt;a href=&quot;https://github.com/FEX-Emu/FEX&amp;amp;ved=2ahUKEwjKy_2fxvmQAxWRyckDHWapLRcQFnoECAwQAQ&amp;amp;usg=AOvVaw1zqZQqh5YPSImThTK901Is&quot;&gt;Fex&lt;/a&gt;, translating x86_64 games over to ARM, that I&apos;m pretty excited about as well.&lt;/p&gt;
&lt;p&gt;One interesting feature of the Steam Frame is that the hardware will &quot;focus&quot; the graphical horsepower depending on where your eyes go.  This is called Foveated Streaming.  I wonder how this will work with framerates and performance.  For example, if I have a powerful PC and I stream a demanding game like Doom The Dark Ages to my Steam Frame, will my framerate improve because of where I&apos;m focusing my eyes?  Will it stay the same?&lt;/p&gt;
&lt;p&gt;My guess on the Steam Frame is going to be $1,500 USD.&lt;/p&gt;
&lt;h1&gt;Into the Future&lt;/h1&gt;
&lt;p&gt;As a lifelong PC gamer, I&apos;m super excited about this new hardware, not only because it&apos;s Valve taking the charge, but just the simplification of the whole process.  Gaming is not what it used to be and in my opinion, it&apos;s going downhill for the AAA games for various reasons.  Indies are just more interesting and don&apos;t require the best NVIDIA GPU with 10x FrameGen and DLSS just to run it at 60FPS.  I do not plan to build custom gaming PCs anymore as it&apos;s just not worth the time and money.  I&apos;d rather buy something like a Steam Machine and just play my games.  I can totally see me purchasing a Steam Machine or the next version of the Steam Deck to take with me when we start doing more traveling and camping in the next 4-5 years.&lt;/p&gt;
&lt;p&gt;Take the hardware that Valve is offering and continued support of the community, and you have some amazing possibilities coming over the next few years.  Very exciting times in the tech world where technology has become pretty dull and lifeless.&lt;/p&gt;
</content:encoded><author>sixstorm</author></item><item><title>Solostation Retrospective</title><link>https://blog.teamtuck.xyz/posts/solostation_retrospective</link><guid isPermaLink="true">https://blog.teamtuck.xyz/posts/solostation_retrospective</guid><description>Looking back on Solostation, my cable TV project</description><pubDate>Thu, 20 Nov 2025 00:00:00 GMT</pubDate><content:encoded>&lt;p&gt;Two years ago, I found a video floating around the web of probably the most amazing Raspberry Pi project that I&apos;ve ever seen.  This guy took a Pi 4B, an external 2TB hard drive, a screen from an old iPad 2, and an Apple iMac remote (Front Row anyone?), creating his own custom cable TV station.  This included 5-10 channels that had tons of content, commercials, station idents, and special local access programming that he curated himself.  Christmas commercials played when you got around Christmas time, movie marathons were fun surprises, and there were even Pay-Per-View channels!  It was truly a work of art that I wanted to see if I could recreate myself.&lt;/p&gt;
&lt;p&gt;So I set out by buying a Pi 4B, 2TB SSD, and a 15&quot; portable monitor.  Equipped with Python, I set out to try and make the exact same thing . . . or so I thought.  My goal was to create my own spin of this project and make it 100% offline (after the first run of course) so that it can run anywhere.  Here is a retrospect on this project &lt;em&gt;2 years&lt;/em&gt; in the making and where I stopped working on it.&lt;/p&gt;
&lt;h1&gt;Going beyond a beginner in Python&lt;/h1&gt;
&lt;p&gt;As an IT Administrator, I have done quite a bit with PowerShell and dabbled with Python enough to know some basic things.  But this project has taught me more about Python, SQL and JSON more than any other project I&apos;ve ever worked on.  Everything from getting very cozy with dictionaries, converting object types, and creating custom classes; I did a lot of researching, a lot of trail and error.&lt;/p&gt;
&lt;p&gt;One thing that I learned is about how time works in Python with the &apos;datetime&apos; module.  My goal with this project was to have content start at the top or bottom of the hour, depending on content length and type.  Sitcoms would play, say at 1PM, with commercial breaks, followed by the next item scheduled for 1:30PM.  But how do you handle the time and the schedule?  Enter timedeltas.  When dealing with time, you HAVE to keep everything lined up and in the same format.  Did you measure a block of time in minutes or seconds?  Which one makes more sense to use and work with?  It was a little bit of a chore to keep up with it all and make sure everything worked.  Tons of debug logs later and I finally mastered it ... I think?&lt;/p&gt;
&lt;p&gt;I also worked with TVDB&apos;s free API to pull down show, season and episode information, storing it in local JSON files so that I wouldn&apos;t have to make calls every time I ran the script.&lt;/p&gt;
&lt;h1&gt;Commercial Breaks&lt;/h1&gt;
&lt;p&gt;This is something that I really wanted to work but never could get just right.  The concept is that I would take my ripped content (from my physical DVD collection), have a SQL database with the episode information and when &lt;em&gt;chapter breaks&lt;/em&gt; would occur, down to the second.  The scheduler would choose an episode, get the episode information from the SQL database, and monitor during playback for when chapters would change, thus playing back a pre-selected list of commercials and going on to the next chapter of that episode.  Whew!  This sounds like it would work, although complicated, and it did ... to an extent.&lt;/p&gt;
&lt;p&gt;The problem is that media players, like MPV, can either playback content on the spot directly or in a playlist format.  You can&apos;t create a playlist that can take action when the chapter switches, so you have to create a &quot;monitor&quot; or &quot;watcher&quot; that watches for that chapter change and react accordingly.  MPV does have a built-in observer for chapter changes, but it&apos;s not reliable in my testing.  Also, some of my media doesn&apos;t even have chapters!&lt;/p&gt;
&lt;p&gt;I also found that this method of injecting commercials when chapters changed caused the time schedule to always be inaccurate.  Other issues resulted because of the time not being exact.&lt;/p&gt;
&lt;p&gt;I then pivoted to allowing an episode or movie to play, then play commercials until the next time block.  The issue with this method is that in order for this to work and there to be no &quot;dead air time&quot;, you have to have individual commercial files that fit every scenario and amount of time.  For example, if you have 8 seconds until the next block, you may or may not have a commercial file to fill in that gap.  How do you account for those 8 seconds if you don&apos;t have a commercial file?  See where I&apos;m going with this?  Heck, I even tried to see if there was a way to dynamically create video files to fill in these spots, but the Pi doesn&apos;t do this very well due to computing power.&lt;/p&gt;
&lt;h1&gt;I Want My MTV&lt;/h1&gt;
&lt;p&gt;One fun concept from the original video is that this guy recreated the MTV of the 80s and 90s, playing mainly music videos (yes, even with the song info in the bottom left), fun MTV shows like HeadBangers Ball and MTV News, and lots of Beavis and Butthead.  I started to do this by finding a YouTube playlist of music videos, downloading them with YT-DLP, processing each one into a SQL database, and then using the MPV on-screen text overlay for the first and last 5 seconds of the music video.  This actually worked and really wasn&apos;t that hard to implement!&lt;/p&gt;
&lt;h1&gt;Fail, Rebuild, Fail, Repeat&lt;/h1&gt;
&lt;p&gt;As I mentioned, I&apos;ve spent the last 2 years, on and off, trying new approaches to reach my goal.  I ran into many, many issues, solved quite a few of them, but there are just some that I could not resolve.&lt;/p&gt;
&lt;p&gt;Just getting commercials from YouTube and breaking them up into individual video files is such a process that I haven&apos;t had time for.  Trying a new concept or method to find that you broke 10 other things.  Trying to get seasonal commercials to play more often during the holidays.  Developing a &quot;weight&quot; system for your media, pushing the scheduler to choose specific things like playing Die Hard more often around Christmas.  All of these issues I just couldn&apos;t solve.&lt;/p&gt;
&lt;p&gt;Maybe the project was a little too much for me to take on.  Maybe I just haven&apos;t figured out the right way to put all of this together and make it work.&lt;/p&gt;
&lt;p&gt;Earlier this week, I took a little time to build a very simplified version of this project:  use MPV to build a playlist, consisting of a random amount of commercials, followed by either an episode or movie.  All you have to do is power on the Pi and enjoy, thanks to DietPi headless (no Desktop Environment) and .bashrc.  Nothing crazy, no SQL, no JSON, just straight Python.  And it only took me part of a day due to what I&apos;ve learned.  You can see &lt;a href=&quot;https://github.com/sixstorm/solostationv4&quot;&gt;&quot;Version 4&quot; of Solostation on my Github&lt;/a&gt; if you&apos;d like to see the code.  You can also see the mess of &quot;Version 3&quot; (the complicated version) if you check out my &lt;a href=&quot;https://github.com/sixstorm/&quot;&gt;repo&lt;/a&gt;.&lt;/p&gt;
&lt;h1&gt;So What Now?&lt;/h1&gt;
&lt;p&gt;There will come a time where I will take a fresh attempt at creating this project, but not today.  I didn&apos;t even get to design and build an enclosure!  And maybe that&apos;s something I do when the new year rolls around, we will just have to see.&lt;/p&gt;
</content:encoded><author>sixstorm</author></item></channel></rss>