Channels DVR <-> Dispatcharr Tools

I threw together a quick little GUI based Python tool to take channels loaded into Dispatcharr and map them to Gracenote ID's using the Channels DVR IP (aka your own server). It will auto match as much as possible and then warn you of what it couldn't match and what requires a second look. It's just one python file and uses tkinter for the GUI. I'm not accepting PR's or issues on this but wanted to share for the community as it was very useful for me. Hope this helps someone else.

4 Likes

Looks like a version of this.

Its nice to have more tools for that tho. Very useful for underground providers

1 Like

I saw that but didn't want an entire docker. I figured a single python file is more lightweight.

1 Like

I think docker should be an option as you can isolate the dependecies needed for this tool from another tool on hand but yeah this is useful either way

This seems like something we should add to OliveTin. There used to be lots of little tools like this floating around on the forum, which was a big part of why I put OliveTin together.

6 Likes

Hey, just wanted to update everyone. So I kind of updated this repository. It's more than just a Gracenote matcher. It's a bundle of tools I designed all around Python.

So in addition to the main Dispatcharr Gracenote manager for Channels, I made one for another tool called M3U-Editor. It's a very similar tool to Dispatcharr. It just is a different option. It functions a little differently. Basically it does the same thing, it just has some different features. It does require a little bit more complexity. You do have to generate an API key, and the tool asks you to export a plugin and import it into M3U-Editor, as M3U-Editor cannot insert Gracenote data over its API. So what happens is you install the plugin and approve it and activate it. Once you are ready to load up your IDs, you click a button in my little tool. It copies them to your clipboard. You go back into M3U-Editor to the plugin, and there is an action to paste them in, and it just enters them into every channel.

Additionally, I wrote a tool specifically for Dispatcharr. That's what I'm using primarily to look at every single feed you've selected and try to match it to identical feeds on other groups that can serve as fallback feeds. If one goes down, it'll fall back to the next one in the list, and it just makes it really easy to add those in bulk and confirm you have everything correct. This is not really specific to Channels in particular, but it's just useful to have, and I included it in the repo. It's really the same design as the other two tools and the same UX, although I will admit it's a little clunky right now. It could use a little bit of polish. I will have to get to that at some point. It's just not a priority for me right now. But in terms of function, it's more function than form.

Next, I wrote an extraordinarily long and custom stream profile for Dispatcharr. This is a custom profile that uses their custom mode. It runs in Python and is just copied and pasted inline. It is extraordinarily long and complex and took a lot of time and effort to get in the place it is right now, although it does require more validation for long-term stability, and I'm still validating it, so I consider it a work in progress that might take a few more revisions to get completely right. Although it seems to be pretty good right now, and things seem to be working quite well. But it will take some time to be sure that it's okay.

The idea behind this is, since Channels isn't really meant for IPTV, and sure, we've talked a number of times, IPTV does require some buffering and starting behind the live edge in order to maintain a consistent stream and not stutter all the time and buffer and freeze. This absorbs a lot of that through various means and helps pace the stream a little bit more evenly. Catch is, it does require an HLS feed coming from your provider. Obviously, we're not going to discuss specific providers here as that goes against forum rules. But the idea is you want to just figure out how to get an HLS stream out of your provider. My provider, I was provided with a feed that ended in the words &output=ts I changed that to &output=m3u8 and that fed me an HLS feed which works with this profile. A regular transport stream will not. However, at the same time, what you're feeding into Channels should be a standard MPEGTS stream. So what you're pulling into Dispatcharr is going to be an HLS feed. What comes out of Dispatcharr into Channels is just MPEGTS. All of the proxying and buffering and all that is handled at the first level inside of Dispatcharr and should not have to make it to Channels, because Channels is given a pretty hefty buffer to begin with.

Finally, I did one more nice thing that just helped me out a little bit, and I thought I'd share it. This is mainly for Dispatcher, but it could work with other tools. I don't really know. It's just a simple regex to remove anything that prefixes the name of a channel. A lot of providers seem to throw prefixes before channel names that end with a "|" such as US| all I did was just write a regex to remove that and leave the raw channel name to make it super easy to alphabetize channels within our channel collection and have them in order, to make them easier to find, especially if you have a large list.

That's basically what I've done so far, and the main work in progress is just making sure that stream profile is working well. The other thing I really kind of have to do at some point my backup streaming matcher is a little more user-friendly and a little less janky. But I will get to that at some point. Right now, it's working quite well for me and got the job done, and it's really a one-off sort of thing.

This is all in the repository that I linked above, and I hope this helps some people that are using some of these services that we will not discuss the names of. We can just discuss how to better utilize them within the platform, of course, as long as that is allowed.

I would be happy for these to be included in Olivetin. Of course, if that helps the community out, particularly the backup feed matcher and the Gracenote matcher. I think those are very useful tools, and I think Dispatcharr is a good tool to standardize on for this sort of thing because it's just been around for a long time and is quite stable.

2 Likes

Just wanted to update another time. I have reworked the UI for all three Python tools to make them as user-friendly as possible, clean up any weird glitches where things were cut off, as well as try to make the workflow a little bit more seamless.

It's not a rewrite of the whole logic. It's just some UI polish that should make it a little bit easier to use all three tools.

Lastly, I have implemented a new profile specifically for Channels and Dispatcharr. I removed the old profile I wrote, as it was more generic. The reason this is specific to Channels is it handles tuner sharing really well. So if you were to open up a stream from an IPTV provider and then open up another stream from the same channel on a second device, it handles the buffering really well, without dropping frames or buffering pauses. It just handles the caching a lot better. It's really just a custom wrapper for Dispatcharr at this point. It's kind of doing its own thing around the original tune that Dispatcharr sends out. I found it to work super well with Channels. It just requires an HLS feed. Now I'm currently testing a TS-supported profile where you can use it with a provider that only supports MPEG TS. Now, I won't be testing that myself or watching it because I'm happy with my HLS profile. However, I am running automated testing against it, including automated testing through Channels to catch any issues. I can't guarantee that it'll be perfect because TS is not as reliable as HLS when it comes to this sort of thing in terms of catching up with segments and such. But I'm doing the best I can, just as a fallback option for those who could possibly use it. It will have the same tuner sharing logic as well. I just won't be watching it with my own eyes. But my agent will be running automated tests against it and testing it on my Channels server and capturing any logging, and it will just be going for about a couple of hours to confirm that it is as stable as it can be without a human looking at it.

Once that TS profile is validated, I'll just post a little update on this comment that it is live on GitHub.

This sounds great, thanks for sharing your work on it. I'll be giving it a go when I find some time in the next week or so. Really appreciate it!

1 Like

Hi. 2 questions? Could you make it auto switch to HLS from the provider within the profile itself (vs having to switch to U/N account with URL change)?

And could it provide stream rez/stats to Dispatcharr? I tried it but didn't see all the stats.

Thanks.

I don't know what you're talking about. So first off, you set the provider up as HLS and then output MPEG-TS to Channels. I'm toying with a possible profile that will ingest TS from a provider and then still output MPEG-TS to Channels. I just don't know if it's going to work, and am currently having my agent spend several hours testing it, fixing things, and then retesting it, which will probably take the rest of the day, if not until tomorrow. Even when that's ready, I'm not even testing it myself. I'm just going off what the agent does because I'm happy with my setup, and I'm making this for me and sharing it just in case anyone finds it useful. I really don't care if people don't.

Secondly, I am not doing anything with Dispatcharr. I just wrote a couple of tools to make it easier to set up Gracenote data and make backup channels.

I'm also sharing this, not the benefit of others. I'm not looking to make any changes or provide any support at all whatsoever to anyone. This is just come as it is, use it or don't. Hopefully, it helps some people. If it doesn't help anyone, then don't use it. I just don't have the time to support people with it. But if people find it useful, great. If people don't find it useful, great.

GitHub issues and pull requests are disabled. Anyone who needs to make any changes can fork and maintain their own fork. It's very clearly written Python with a lot of comments and just not really that complex. But it's there, open source, everything is pretty self-contained to individual files and pretty maintainable for a fork if needed. Each tool is about 3,000 lines of code, so it's pretty maintainable to fork. It's MIT licensed, and the repo clearly states that it's not open to contributions.

This is just due to my own ability to support things and my own time constraints and life challenges. I don't have the ability to answer questions, maintain anything, or assist people. I wrote a clear README on how to set this up, and if that's not helpful, then I'm sorry.

I spent quite a bit of time building two Dispatcharr stream profiles for Channels. One is for HLS and one is for MPEG-TS.

HLS profile (recommended): HLS stream profile

MPEG-TS profile (fallback): MPEG-TS stream profile

The basic idea is the buffer lives in Dispatcharr instead of in your players. The HLS profile grabs the provider's whole playlist window, about 60 seconds, and keeps it as a reserve. It feeds Channels at exactly real time, paced off the video timestamps, kind of like an HDMI encoder would. When the provider is late or stalls, the reserve keeps video flowing and your TV never notices. When the provider catches up, the reserve refills. You end up around 60 seconds behind live, which is normal for HLS.

It's built around tuner sharing in Channels. Channels shares one connection between every device on the same channel, and normally a device that joins late starts with nothing buffered. The profile asks Channels how many devices are watching, and every time one joins it sends an extra 5 second head start out of the reserve so the new device doesn't start empty. It never takes that back when someone leaves, and it slowly rebuilds the reserve later at about 1% slower than real time, which you can't see or hear. It finds the channel in Channels on its own from your Dispatcharr M3U source, so there's nothing to set up. Leave tuner sharing on.

Recordings are handled too. Since the profile runs a bit behind live, a recording would normally lose the last minute. The profile extends any recording Channels is making through it by its own delay plus 45 seconds for the provider's own delay, on top of whatever padding you already set. So if you pad a show 30 minutes for football, you keep your 30 minutes. It only touches recordings coming from that source and channel, and it only adds it once even if Dispatcharr restarts.

Failover is built in if your channels have backup streams. I made switching a last resort on purpose, because every backup feed is at a different point in the show and switching means jumping forward or back. So it rides out stalls, refused connections and slow feeds on the same feed, and only switches if the feed is actually dead and the cushion is about to run out, is serving the provider's offline placeholder, gets stuck, or has been way too slow for 5 minutes. If a feed starts sending segments with the audio and video way out of step, it holds them back and tries a backup. It checks a backup actually works before switching to it and won't keep hopping between dead feeds.

Use Xtream Codes if your provider has it, not an M3U link. The channel list loads way faster and a lot more reliably, and both profiles handle it properly. Dispatcharr stores Xtream streams as .ts and has no HLS option, but the HLS profile rewrites those addresses to .m3u8 on its own, so you get HLS.

HLS vs TS: use HLS if your provider has it. It has a bigger cushion (about 60 seconds vs about 20), it can re-fetch video it missed, and a reconnect picks up right where it left off. The TS profile is for providers that only do MPEG-TS. It does the same job but only has the burst the provider sends on connect as its reserve, so a long outage loses video for good. Both send MPEG-TS to Channels, so keep your Channels source on MPEG-TS.

No re-encoding, CPU use is basically nothing. Setup is in the README. This took about a day or so straight of work and a lot of effort, so I'm really proud of it, and I hope people enjoy it. It makes it really seamless to integrate IPTV with Channels and, in my opinion, makes Channels act more like a native IPTV player.

1 Like

Very nice work, @mackid1993!

I don't use Dispatcharr but with all this work that you have done with buffers and all, I'm really interested to try it. Especially if it can reduce the amounts of interrupted recordings. Will it help with that?

Very cool. Thanks for doing this and sharing it with us.

So what it can do is hold a pretty big buffer to hopefully ride out any interruptions or slowdowns, et cetera. If something really does kind of stall, it can keep the player alive for a little bit to prevent a complete connection drop. If something really does go bananas, I have that tool there to actually make it really easy to find secondary streams of channels and load in backup channels. Falling over to those is the last resort because it will make the video wonky for a second, especially if the backup channel's at a different point in the video. Obviously, what it can't do is, obviously these providers are not quite above board. So if something is totally broken, like a feed is just like done and it's borked, there's not much I can do to fix that because that's on the provider's end. So mainly what it's doing is just holding a nice buffer and trying to keep a stream as stable as possible. I've had things run overnight now rather than dropping after 30 minutes, which is really great. So obviously, if you have a good provider and it's reliable and it's working well, it should be reliable and work well with this. If you don't have a good provider and it's not working well, that's just the provider. The other thing is sometimes channels have weird outages, which is possible, and obviously there's not much that can be done about an actual outage to keep a DVR recording alive. It's just going to freeze or try to fall over to a secondary feed, which might cause a hiccup, or a tertiary feed, which also might cause a hiccup.

The main thing I did really that I think is useful is, because it's running 60 seconds at least behind live, every recording made through this profile will have extra padding added to it over Channels' API. So you start a recording for an hour, it's going to run for an hour and 2 minutes or so, and you'll see it in Channels that the recording runs for an extra 2 minutes, for example. The other piece to that is, if you have a recording that already has padding, like a football game that you set to add an extra 30 minutes to because it runs with overtime, it's going to add 32 minutes to it because the stream is running behind the live feed by a certain amount of time, depending on the situation and how it rides everything out. So that's to prevent a video from being cut off at the end of a recording because it's running behind the guide, essentially, but not really. Channels doesn't know it's running behind the guide, but in reality it is, because Dispatcharr is holding extra buffer in its own cache to hand off to a Channels client if things begin to run dry, to keep things running smoothly until the provider picks back up.

I should also mention, since this is more of a personal pet project just for my own benefit that I'm sharing, I'm not doing any proper versioning besides GitHub commits. I did make a change to both profiles this morning. I just ran an adversarial audit against everything, and it found one bug in each profile that were pretty much identical. It's just a buffering issue that should help stream stability.

So if anyone happened to try this overnight since I posted, just grab the newest off GitHub. It's just copy-paste. But you should see a few more seconds of cache in the Channels client, and that should help things out a little bit.

1 Like

Now that Dispatcharr will use HLS (October release) is this still needed? This is my setup. I have switched away from Channels because I kept getting stream stopping with Dispatcharr connection. I’m trying again now that it has HLS output.

The answer is yes.
So I'm updating this hours later. Dispatcharr does not have HLS at all.
There's a huge misconception of what this release does. It will not natively pull HLS in from your provider and pass it through its proxy. All this release does is give Dispatcharr the ability to, instead of sending MPEG-TS to your player, send HLS to your player, which does not really help us at all. It kind of makes things much worse.

What my code does is take the regular TS that is coming from your provider, that is the only thing that Dispatcharr understands, for some stupid reason, rewrite it to HLS, which is much more reliable since most providers support that out of the gate anyway, and then send a stable TS stream to Channels, which works way better than HLS because of all of the reasons I stated in the readme. So you can put in your Xstream credentials just get regular TS channels like you normally would with Dispatcharr. Use my HLS profile. It will rewrite those channels to HLS on its own every time you tune. You pick the MPEG-TS option instead of the HLS option, like I explained. Give that to Channels. Channels will get MPEG-TS directly from Dispatcharr on your network. Play MPEG-TS from Dispatcharr, and Dispatcharr is getting HLS from your provider. Everything is nicely buffered inside of Dispatcharr. Channels gets a little bit of buffer for itself, and things are super reliable. And if things slow down, the code releases more video to Channels, so the stream stays stable.

As a last resort, if things get really super-duper messed up, a failover channel is then used to keep the stream alive as a very last resort if it buffers way too long. I preferred just letting it buffer a little bit and come back at the same time and just kind of re-pull those chunks again, rather than falling over to another feed that might be at a totally different point in whatever you're watching. So that's why failover is our last resort to everything. Falling over to another channel is not particularly smooth. It's smoother just to kind of ride it out or just let it buffer for a second and pick back up.

It's one of those things where you ultimately get what you pay for, and ultimately a legitimate pay TV provider is going to provide better quality and more stability. Personally, for me, this has been a fun little project and is just more of a backup to DirecTV and my LinkPi encoders and AH4C. I have simply been watching this more lately because I've been trying to get it working really well for myself, and I also wanted to share my efforts with the community just as a courtesy.

I also want to note here: always use the proxy with this tool and Dispatcharr. It will not work if you're passing a direct stream with the option to do so. That will bypass my code completely. The other advantage of using Dispatchrr as a proxy is you can bind Gluetun to Dispatcharr, which will make it super easy to implement a VPN just for the IPTV feeds you're pulling in, rather than the entire server you're running on. And it doesn't even affect your Channels instance at all. It just affects what Dispatcharr is reading. And with Gluetun, it's really nice. You can set an exception for your home subnet, so it'll still see your home network just fine. I kind of prefer this using a VPN provider and a static IP purchased from them to keep things clean. It's not that expensive if you use a good one, such as Windscribe, for example. I think we can discuss that here safely. There's nothing illegal about using a VPN for anything. I like Windscribe for this because they're inexpensive and very privacy supporting. What I recommend doing is taking the hostname provided to you by your provider and doing a traceroute to it and figuring out where it terminates, and then picking a location close to that. For example, if your provider terminates in Amsterdam, pick a VPN in Amsterdam. So it takes a clean route to Amsterdam from wherever you are and terminates a few milliseconds away.

Just notating here that previously this post stated I was able to modify the profile to quickly rank the channels that were selected as backups by quality and then choose the best one. Unfortunately, that did not work so well, so I'm reverting back to what did work. I did notice when something falls over and the frame rate's different, there are a lot of dropped frames and some AV sync issues, but from what I can tell, it's just cosmetic. It's not visible to the naked eye, so I'm just going to leave it as is. It seems to work just fine for me.

For example, I was watching a channel that was 30 hertz, and it went up to 60 hertz, and although it was dropping frames, it played just fine and looked just fine, and I think it was just the player getting confused, basically. As far as I can tell, it seemed to just work just fine, honestly. I could not see anything out of the ordinary.

I also just thought I'd share, really quickly, my Docker Compose file. This covers both Dispatcharr as well as adding Gluetun to it. Please consult the Gluetun documentation for all the different environment variables that might be needed for your particular VPN provider. But I thought this might be helpful for anyone looking to integrate a VPN with Dispatcharr as well. Please ignore my unraid-centric paths. You may change those as needed. I also use a purchased static IP with my provider, so I have the variable for that set. These are just example variables for Gluetun. You might want to go on their documentation website, wherever that may be located, and determine what variables are needed for your particular provider and configuration.

services:
  gluetun:
    image: qmcgaw/gluetun:latest
    container_name: GluetunVPN
    cap_add:
      - NET_ADMIN
    devices:
      - /dev/net/tun:/dev/net/tun
    environment:
      - TZ=America/New_York
      - VPN_SERVICE_PROVIDER=custom
      - VPN_TYPE=wireguard
      - WIREGUARD_ENDPOINT_IP=${WG_ENDPOINT_IP}
      - WIREGUARD_ENDPOINT_PORT=${WG_ENDPOINT_PORT}
      - WIREGUARD_PUBLIC_KEY=${WG_PUBLIC_KEY}
      - WIREGUARD_PRIVATE_KEY=${WG_PRIVATE_KEY}
      - WIREGUARD_PRESHARED_KEY=${WG_PRESHARED_KEY}
      - WIREGUARD_ADDRESSES=${WG_ADDRESSES}
      - WIREGUARD_ALLOWED_IPS=0.0.0.0/0
      - WIREGUARD_MTU=1320
      - DNS_ADDRESS=${WG_DNS}
      - FIREWALL_OUTBOUND_SUBNETS=192.168.1.0/24
    ports:
      - "9191:9191"
    volumes:
      - /mnt/user/appdata/gluetun:/gluetun
    restart: unless-stopped

  dispatcharr:
    image: ghcr.io/dispatcharr/dispatcharr:latest
    container_name: Dispatcharr
    network_mode: "service:gluetun"
    depends_on:
      gluetun:
        condition: service_healthy
        restart: true
    environment:
      - TZ=America/New_York
      - PUID=99
      - DISPATCHARR_ENV=aio
      - DISPATCHARR_LOG_LEVEL=info
      - REDIS_HOST=localhost
      - CELERY_BROKER_URL=redis://localhost:6379/0
    volumes:
      - /mnt/user/appdata/dispatcharr/data:/data
    restart: unless-stopped
WG_ENDPOINT_IP=
WG_ENDPOINT_PORT=
WG_ADDRESSES=
WG_DNS=
WG_PUBLIC_KEY=
WG_PRESHARED_KEY=
WG_PRIVATE_KEY=PK

Transcoding Support

I added optional transcoding to both profiles. It's off by default. At the top of each profile there's a short explanation and one setting to fill in with the preset you want (for example 1080p60 or 720p30).

The main benefit is stability when a stream has to fail over to another feed. Every feed comes out in the same format, so a backup with a different frame rate shouldn't make your player drop frames or drift the audio. I haven't seen a failover with it yet, but that's the idea.

If you use it, I'd recommend passing a GPU through to the Dispatcharr container. The README has instructions for Docker Compose, plain Docker and Unraid, for both Intel/AMD and NVIDIA.

It also rebuilds the stream's reserve in Dispatcharr after a provider problem, like a slowdown or an outage, uses it up. While it refills, playback runs slightly slower with the pitch unchanged: up to 3% on still scenes, as little as 0.5% during fast motion like sports. It adjusts gradually in small steps based on what's on screen, and goes back to normal speed once the reserve is full again. That stays below what most people can notice, while the buffer rebuilds and the stream stays stable.

This only works with transcoding on. Without it, the profile just passes the provider's video and audio through and can't slow them down cleanly, so the reserve only comes back if you retune.


A follow-up to last night's post about transcoding support.
The variable slowdown had a bug, so I replaced it. Last night I described a refill that slowed playback by 0.5% to 3% depending on motion, changing speed live inside FFmpeg. During a long refill that pushed the audio badly out of sync, about 10 seconds by the end. FFmpeg's pitch-preserving audio filter loses a tiny slice of audio every time its speed changes, and the variable version changed speed constantly, so the losses added up.
How it works now:

A fixed 3% slowdown. Pitch stays the same, and audio and video stay in sync.

The encoder restarts twice per refill, once when the slowdown starts and once when it ends. Each new encoder runs at its speed from the first frame, so nothing changes mid-stream and nothing can drift.

Each restart waits for the next keyframe (up to 10 seconds) and picks up the timeline where the old encoder stopped, so the switch doesn't show on screen. This works with any provider, including ones whose HLS segments don't start on keyframes.

A refill only starts after the reserve has stayed below half for 30 seconds, so a provider that stalls briefly and then catches up doesn't set one off.
Why 3% is fine: 50 Hz countries have played 24 fps films at 25 fps, about 4% fast, for decades, and almost nobody noticed. The README has the details and the research behind it.
Live test. I ran it on Comedy Central, the worst channel I have, which was stalling about every 2 minutes this afternoon.

Over more than an hour: two refills and a provider channel restart, and partway through I moved from my Apple TV to my MacBook.

What Channels reported: 0% buffering and 0% dropped frames on every check, every 30 seconds the whole time.

What I saw: I watched both refills start and end, and the picture and audio sync stayed clean.

Hardware: it ran on Intel Quick Sync (VAAPI), and the GPU encoder restarts were quick enough not to show.
Readable source. The profiles aren't one-line blobs anymore. The full readable Python lives in stream_profiles/ in the repo, and a GitHub Action minifies it into the copy-paste blocks in the README on every change, so installing is still just a paste. I also went through the README against the code and corrected everything that had drifted out of date.
If you set up last night's version, copy the new HLS and MPEG-TS blocks from the README over the old ones and keep your TRANSCODE setting. The refill only runs with transcoding on.


Just another little quick update I wanted to share. So, I made some changes to the way the profiles are executed. This is intended for reliability, although it's a little bit more difficult to use. I made it as easy as possible. So, you really only have to do this once, and it should make them much more resilient to updates, like Dispatcharr, for example. So initially I was using a lot of private APIs in Dispatcharr. Now, this carries some risk because it can easily be broken by changes they make and kind of cause issues. Some of those private APIs were being used to auto discover the channels DVR URL, which was super convenient but also prone to breakage and kind of ruining everything. Also, I was using some private APIs to just determine other things that were needed, like backup channels and such.

The way it functions now is there are two things you copy and paste into a profile. There is a settings block that ends with a line saying basically just end of settings block. So you only have to touch it once, and it's very easy to see. The settings block explains all the settings you have to set in order for the profile to work. You have to put in your API key for Dispatcharr. That can just be obtained in the settings. It's very easy. You just paste it in and do it once. That lets us do the same things we were doing, but using their publicly documented API. That is much less likely to be broken.

Secondly, there's a section to enter your channels, DVR, URL, and port. The reason I'm doing that is because I don't want it to be auto-discovered and for that process of auto-discovery to be broken with like an update or something.

There's also, of course, the section that was always there to add your transcoding preferences. That was there before, I just kept it there.

Lastly, there's a location to add your Dispatcharr URL. This mostly should not be touched. This is really only needed if you're running it on a non-standard port, not the one that is normally used. So, if you change the port for some reason, like the port is occupied by another application and you had to run it on some other port, then you want to fill this section out so everything functions properly.

And there is another section in the README to easily copy, which contains the actual code that runs, this is also clearly notated. Reason for this and the notations are so if there's an update to the actual code at some point, all you have to do is delete everything below that settings line and replace it with the new code, and you're off to the races and don't have to re-enter your settings. I tried experimenting with environment variables instead, but unfortunately, that was not simple, possible, or easy to do. So, just hard-coding them into each profile was the best solution. Separating these two sections out into two separate copy and pastes, I thought was the best option so it can just be easily found where the settings end and the code begins, and just easy to change out the actual code portion when something needs to be changed out.

Now, I'm not going to post when this is done because it'll be obvious, but I am also reorganizing the README so it's a little less bloated. It's going to have all the same useful information and content and instructions for setup, but it's just going to be a little bit more easy to read and less verbose, less duplicated content, and more things like tables and such that make it less long.