<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Youtube on despatches</title><link>https://icle.es/tags/youtube/</link><description>Recent content in Youtube on despatches</description><generator>Hugo</generator><language>en</language><lastBuildDate>Tue, 15 Jul 2025 10:07:46 +0100</lastBuildDate><atom:link href="https://icle.es/tags/youtube/index.xml" rel="self" type="application/rss+xml"/><item><title>Projector: Keep YouTube Descriptions synced</title><link>https://icle.es/2025/07/07/projector-keep-youtube-descriptions-synced/</link><pubDate>Mon, 07 Jul 2025 20:08:21 +0100</pubDate><guid>https://icle.es/2025/07/07/projector-keep-youtube-descriptions-synced/</guid><description>&lt;p>In my &lt;a href="https://icle.es/projector-Hugo.md">previous post&lt;/a>, I used &lt;a href="https://gohugo.io/">hugo&lt;/a> to
generate correctly linked, always up to date descriptions for my YouTube Videos.&lt;/p>
&lt;p>But if I&amp;rsquo;m generating the descriptions automatically&amp;hellip; I&amp;rsquo;m hardly going to be
excited about copying and pasting them into YouTube - right? right!&lt;/p>
&lt;p>Automating this process brings up a few design choices.&lt;/p>
&lt;h2 id="planning">Planning&lt;/h2>
&lt;h3 id="which-language">Which language&lt;/h3>
&lt;p>There were a few contenders, and here&amp;rsquo;s how I thought them through:&lt;/p>
&lt;h4 id="zig">Zig&lt;/h4>
&lt;p>I’m currently learning &lt;a href="https://ziglang.org/">Zig&lt;/a>, and I love using it for my
game development. But it doesn’t yet have mature libraries for working with the
YouTube Data API - and I don’t feel like writing one. So, sadly, Zig’s out for
this one.&lt;/p></description><content:encoded><![CDATA[<p>In my <a href="https://icle.es/projector-Hugo.md">previous post</a>, I used <a href="https://gohugo.io/">hugo</a> to
generate correctly linked, always up to date descriptions for my YouTube Videos.</p>
<p>But if I&rsquo;m generating the descriptions automatically&hellip; I&rsquo;m hardly going to be
excited about copying and pasting them into YouTube - right? right!</p>
<p>Automating this process brings up a few design choices.</p>
<h2 id="planning">Planning</h2>
<h3 id="which-language">Which language</h3>
<p>There were a few contenders, and here&rsquo;s how I thought them through:</p>
<h4 id="zig">Zig</h4>
<p>I’m currently learning <a href="https://ziglang.org/">Zig</a>, and I love using it for my
game development. But it doesn’t yet have mature libraries for working with the
YouTube Data API - and I don’t feel like writing one. So, sadly, Zig’s out for
this one.</p>
<h4 id="python">Python</h4>
<p>I used Python for <a href="https://icle.es/despatches.md">despatches</a> and it was the right fit there -
good libraries for BlueSky and Reddit.</p>
<p>However, I did not enjoy the experience:</p>
<ul>
<li>
<p><code>bazel</code> was a constant struggle</p>
</li>
<li>
<p><code>poetry</code> is nice… but still a bit of a nightmare. It just makes the pain more
structured</p>
</li>
<li>
<p>Worst of all: blusky failed after reddit succeeded caused a <em>partial success</em>,
which broke the Git commit and silently caused a post to be repeated
(embarrassing!)</p>
<p>That kind of problem <em>can</em> happen in Go (nil pointer), though it wouldn’t in
Zig. But at least with Go, most handleable errors <em>stay</em> errors — they don’t
crash the whole tool.</p>
</li>
</ul>
<h4 id="java">java</h4>
<p>Sure, I could do this in Java - but I really don’t want to mess with the JVM.
And more importantly, I’m doing this for fun. Java doesn’t feel like that
anymore.</p>
<h4 id="golang">golang</h4>
<p>Not quite my favourite any more, but still a close second. It&rsquo;s <em>fast</em>, has
YouTube libraries and it somehow seems fitting that Hugo is also a go baby.</p>
<p>Even though I’m not wiring the two directly, the ecosystem fit is nice.</p>
<h2 id="overall-plan">Overall Plan</h2>
<ul>
<li>
<p>Let <code>Hugo</code> render the YouTube description as plain text</p>
</li>
<li>
<p>Traverse the <code>youtube/*.md</code> files in the source directory</p>
<ul>
<li>Skip videos that are too old to update (maybe older than 30 days?)</li>
<li>Hash the rendered output (title, description, tags, etc.)</li>
<li>Compare that hash with the one stored in the frontmatter</li>
<li>If it doesn’t match,
<ul>
<li>Update the metadata on YouTube</li>
<li>Update the hash</li>
</ul>
</li>
<li>commit and push any updates (should be only hash changes)</li>
</ul>
</li>
</ul>
<h2 id="validation">Validation</h2>
<p>One thing worth being careful about is whether the metadata is valid. We do not
want the sync to fail during its scheduled run - when it won&rsquo;t have many choices
on how to resolve it.</p>
<p>In a bid to mitigate this, we&rsquo;ll add a command to validate the source and
rendered files.</p>
<p>The validation would expect the rendered files to be generated as well, which
seems reasonable since Hugo is probably running as <code>hugo serve</code> while the
content files are being updated.</p>
```go
func validate(sourcePath string, renderedPath string) error {
	targetSourceDir, err := getTargetDir(sourcePath)
	if err != nil {
		return err
	}

	targetRenderedDir, err := getTargetDir(renderedPath)
	if err != nil {
		return nil
	}

	videos, err := findRecentVideos(targetSourceDir)
	for _, video := range videos {
		_, err := video.getDescription(targetRenderedDir)
		if err != nil {
			slog.Warn("unable to find rendered file", "file", video.renderedPath)
		}
	}
	return nil
}
```
<p>The validate function will retrieve the relevant files and check that there is a
corresponding rendered description.</p>
<p>If it errors in that process, we know that it would error out in the sync.</p>
<p>We can&rsquo;t catch errors around the API though at this stage, and that&rsquo;s
unavoidable.</p>
<h2 id="sync">Sync</h2>
<h3 id="hashing-the-description">Hashing the Description</h3>
<p>This part was surprisingly easy:</p>
```go
bdesc, err := video.getDescription(targetRenderedDir)
if err != nil {
    slog.Warn("unable to find rendered file", "file", video.renderedPath)
}

// We want to hash the contents of description
// Check with the hash in the metadata to see if it matches
hash := md5.Sum(bdesc)
strHash := hex.EncodeToString(hash[:])
```
<p>The challenge was trying to write the updated yaml frontmatter back. I was using
the <code>adrg/frontmatter</code> library to read the frontmatter, but it does not support
writing it back.</p>
<h3 id="detour-write-a-small-frontmatter-library">Detour: Write a small frontmatter Library</h3>
<p>I took a little detour to build
<a href="https://icle.es/golang/inscribe.md">inscribe, a little frontmatter library that supports reading and writing back in yaml</a>.</p>
<h2 id="auth">Auth</h2>
<p>We need the YouTube Client to have an OAuth Token, which we can retrieve by:</p>
<ul>
<li><a href="https://console.cloud.google.com/auth/clients">Create a new OAuth Client</a> -
Type of desktop is probably the easiest</li>
<li>add your user account to
<a href="https://console.cloud.google.com/auth/audience">test users</a>:</li>
<li>go to
<a href="https://accounts.google.com/o/oauth2/v2/auth?client_id=YOUR_CLIENT_ID&amp;redirect_uri=urn:ietf:wg:oauth:2.0:oob&amp;response_type=code&amp;scope=https://www.googleapis.com/auth/youtube">https://accounts.google.com/o/oauth2/v2/auth?client_id=YOUR_CLIENT_ID&redirect_uri=urn:ietf:wg:oauth:2.0:oob&response_type=code&scope=https://www.googleapis.com/auth/youtube</a>
<ul>
<li>Remember to substitute your actual client_id</li>
<li>Add any other scopes you might want</li>
<li>Go through the flow steps - it&rsquo;ll warn you that the app is unreleased, which
is expected</li>
</ul>
</li>
<li>Take the code that it provides</li>
<li>Call the following curl command</li>
</ul>
```bash
curl -X POST https://oauth2.googleapis.com/token \
  -d client_id=YOUR_CLIENT_ID \
  -d client_secret=YOUR_CLIENT_SECRET \
  -d code=PASTE_THE_CODE_HERE \
  -d grant_type=authorization_code \
  -d redirect_uri=urn:ietf:wg:oauth:2.0:oob
```
<p>You should finally get something like:</p>
```json
{
  "access_token": "ya29...",
  "expires_in": 3599,
  "refresh_token": "1//0g...",
  "scope": "https://www.googleapis.com/auth/youtube",
  "token_type": "Bearer"
}
```
<p>The <code>refresh_token</code> is what you want to save / use as the <code>access_token</code> will
expire (after an hour in this example).</p>
<p>The authentication was a bit more involved with a refresh token, but the
<code>oauth2</code> library helps us out:</p>
```go
func NewYouTube(ClientId string, ClientSecret string, RefreshToken string) (YouTube, error) {

	conf := &oauth2.Config{
		ClientID:     ClientId,
		ClientSecret: ClientSecret,
		Endpoint:     google.Endpoint,
		Scopes:       []string{"https://www.googleapis.com/auth/youtube"},
	}

	// Construct a token from just the refresh token
	token := &oauth2.Token{RefreshToken: RefreshToken}

	ctx := context.Background()

	// Create an authenticated client
	httpClient := conf.Client(ctx, token)

	ytService, err := youtube.NewService(ctx, option.WithHTTPClient(httpClient))
	if err != nil {
		return YouTube{}, err
	}

	return YouTube{
		service: ytService,
	}, nil

}
```
<h2 id="updating-the-description">Updating the description</h2>
<p>Setting the description is a little more complicated because you can&rsquo;t set just
the description.</p>
<p>Everything defined in the <code>VideoSnippet</code> gets updated.</p>
<p>To support this, what we need to do is get the current snippet for the video,
then update it:</p>
```go
vListCall := ytService.Videos.List([]string{"snippet"})
vListCall = vListCall.Id(videoId)
res, err := vListCall.Do()
if err != nil {
    return err
}

if len(res.Items) != 1 {
    return fmt.Errorf("wrong number of videos returned: %d", len(res.Items))
}

ytVideo := res.Items[0]
ytVideo.Snippet.Description = desc

vUpdateCall := ytService.Videos.Update([]string{"snippet"}, ytVideo)
_, err = vUpdateCall.Do()
```
<h2 id="github-action">GitHub Action</h2>
<p>The GitHub Action is fairly straightforward, mostly a copy of the Hugo one,
then:</p>
<ul>
<li>Add Bazel</li>
<li>Run projector sync</li>
<li>Commit if changed</li>
</ul>
```yaml
- uses: bazel-contrib/setup-bazel@0.15.0
  with:
    # Avoid downloading Bazel every time.
    bazelisk-cache: true
    # Store build cache per workflow.
    disk-cache: ${{ github.workflow }}
    # Share repository cache between workflows.
    repository-cache: true
- name: Run projector sync
  env:
    GOOGLE_CLIENT_ID: ${{ secrets.PROJECTOR_GOOGLE_CLIENT_ID }}
    GOOGLE_CLIENT_SECRET: ${{ secrets.PROJECTOR_GOOGLE_CLIENT_SECRET }}
    GOOGLE_REFRESH_TOKEN: ${{ secrets.PROJECTOR_GOOGLE_REFRESH_TOKEN }}
  continue-on-error: true
  run:
    bazel run //tools/projector:projector -- sync -source blog/content/youtube
    -rendered blog/public/youtube
- name: Commit and push if changed
  run: |
    git config user.name "drone-ah bot"
    git config user.email "github.actions@drone-ah.com"

    if ! git diff --quiet; then
      git add -u
      git commit -m "auto: log youtube updates"
      git push
    else
      echo "No changes to commit"
    fi
```
<p>We also needed to upgrade one permission - <code>contents</code></p>
```yaml
permissions:
  contents: write
```
<h2 id="conclusion">Conclusion</h2>
<p>The Google/YouTube documentation was the hardest part here in that it was pretty
obtuse and hard to understand.</p>
<p>Writing a little frontmatter library was unexpected, but while it took a little
time, was straightforward.</p>
<p>Once I got a handle on that, the rest of it was pretty straightforward, partly
because I was reusing parts from before.</p>
<h2 id="links">Links</h2>
<ul>
<li><a href="https://icle.es/projector-Hugo.md">Part 1: Outputting YouTube Descriptions from Hugo</a></li>
<li><a href="https://icle.es/golang/inscribe.md">inscribe: simple frontmatter yaml library</a></li>
</ul>
]]></content:encoded></item><item><title>Generate YouTube Descriptions from Hugo</title><link>https://icle.es/2025/07/03/generate-youtube-descriptions-from-hugo/</link><pubDate>Thu, 03 Jul 2025 13:18:15 +0100</pubDate><guid>https://icle.es/2025/07/03/generate-youtube-descriptions-from-hugo/</guid><description>&lt;p>Uploading and setting up YouTube videos is fiddly. There are a lot of things to
get right - title, description, chapters, links, tags - the list goes on.&lt;/p>
&lt;p>I also want to link to and from blog posts and social posts - and making sure
those links stay in sync is a hassle.&lt;/p>
&lt;p>It gets more complicated when scheduling multiple videos.&lt;/p>
&lt;p>I wanted to make it easier&lt;/p>
&lt;p>I (at the time of writing) use hugo for this blog site, and I regularly link
from the YouTube description to a page on here. Since I want to save having to
copy and paste that link into YouTube, leveraging the CMS felt sensible.&lt;/p></description><content:encoded><![CDATA[<p>Uploading and setting up YouTube videos is fiddly. There are a lot of things to
get right - title, description, chapters, links, tags - the list goes on.</p>
<p>I also want to link to and from blog posts and social posts - and making sure
those links stay in sync is a hassle.</p>
<p>It gets more complicated when scheduling multiple videos.</p>
<p>I wanted to make it easier</p>
<p>I (at the time of writing) use hugo for this blog site, and I regularly link
from the YouTube description to a page on here. Since I want to save having to
copy and paste that link into YouTube, leveraging the CMS felt sensible.</p>
<h2 id="a-youtube-content-type">A YouTube Content Type</h2>
<p><a href="https://icle.es/archetypes/youtube.md">archetypes/youtube.md</a></p>
```yaml
---
title: "{{ replace .Name "-" " " | title }}"
publishDate: {{ .Date }}
youtubeId: ""
playlist: ""
categoryId: 20
tags: []
chapters:
  - "0:00 Intro"
links:
  - title: <title>
    url: <url>
_build:
  list: never
  render: always
  publishResources: false
sitemap: false
---
```
<ul>
<li><code>title</code>: Title for the youtube video</li>
<li><code>publishDate</code>: When should the video go live</li>
<li><code>youtubeId</code>: The video id from YouTube, used to build links</li>
<li><code>playlist</code>: Which playlist is this a part of? Used to build links</li>
<li><code>categoryId</code>:
<a href="https://mixedanalytics.com/blog/list-of-youtube-video-category-ids/">YouTube category Id</a> -
e.g. gaming</li>
<li><code>tags</code>: Used to add hashtags at the end of the video</li>
<li><code>chapters</code>: Added to description to demarcate chapters</li>
<li><code>links</code>: adds each link to the description. Can be other youtube videos</li>
<li><code>outputs</code>: needed to output in plaintext format</li>
<li><code>_build</code> and <code>sitemap</code>: prevent this file getting linked/crawled</li>
</ul>
<h3 id="cascaded-properties">Cascaded Properties</h3>
<p>We also want to prevent these pages from showing up on:</p>
<ul>
<li>List Pages</li>
<li>Sitemap</li>
</ul>
<p>We also want to prevent them from being published. We could add <code>_build</code> to each
of the <code>md</code> files, or we can cascade it (thanks to
<a href="https://discourse.gohugo.io/u/jmooring">jmooring</a> from the gohugo discourse).</p>
<p><a href="https://icle.es/youtube/_index.md">content/youtube/_index.md</a></p>
```yaml
title: "YouTube"
cascade:
  _build:
    list: never
    render: always
    publishResources: false
  sitemap: false
```
<h3 id="layout-plain-text">Layout (plain text)</h3>
<p>We need a plaintext template to render it as text</p>
<p><a href="https://icle.es/layouts/_default/single.plain.txt">layouts/_default/single.plain.txt</a></p>
```gotmpl
{{ .Content | plainify | htmlUnescape }}

{{- if .Params.links }}
Links:
{{- range .Params.links }}
{{ .title }}: {{ .url | absURL }}
{{- end }}
{{ end }}

{{- if .Params.chapters }}
{{ range .Params.chapters }}
{{- . }}
{{ end -}}
{{ end }}

{{- if .Params.tags }}
{{ range .Params.tags }}#{{ . }} {{ end }}
{{ end }}
```
<h3 id="enable-plaintext-output">Enable plaintext output</h3>
<p>We also need to define plain as an output format.</p>
<p>As far as I could see, there is no way (currently) in hugo to specify a default
output type for a <code>type</code> (i.e. youtube) of content, only a <code>kind</code> (e.g. page) of
content.</p>
<p>However, we can add this to the cascade as well:</p>
```yaml
cascade:
  outputs: ["plain"]
```
<p>I also created a <code>layouts/_default/list.plain.txt</code> file to avoid the error:</p>
<p><code>WARN  found no layout file for &quot;plain&quot; for kind &quot;section&quot;: You should create a template file which matches Hugo Layouts Lookup Rules for this combination.</code></p>
<p>The contents of this file doesn&rsquo;t really matter as we shouldn&rsquo;t be rendering or
using it.</p>
<p><a href="https://icle.es/hugo.toml">hugo.toml</a></p>
```toml
[outputFormats.plain]
	mediaType = "text/plain"
	baseName = "index"
	isPlainText = true
	isHTML = false
	noUgly = true
```
<h2 id="auto-link-to-youtube">Auto link to YouTube</h2>
<p>I&rsquo;d like to be able to link to a local markdown file, and have that resolve to
the correct YouTube URL.</p>
<h3 id="from-posts">From Posts</h3>
<p><a href="https://icle.es/layouts/_default/_markup/render-link.html">layouts/_default/_markup/render-link.html</a></p>
```gotmpl
{{- if eq $page.Type "youtube" -}}
  {{- $href = printf "https://www.youtube.com/watch?v=%s" $page.Params.youtubeId -}}
{{- else -}}
  <a href="{{ $page.RelPermalink | safeURL }}" {{ with .Title }}title="{{ . }}"{{ end }}>{{ $text }}</a>
{{- end -}}

<a href="{{ $href | safeURL }}">{{ $text }}</a>
```
<p>You know what would be nicer? If it took the user to the video in the playlist -
if playlist is defined</p>
```gotmpl
{{- if eq $page.Type "youtube" -}}
  {{- $href = printf "https://www.youtube.com/watch?v=%s" $page.Params.youtubeId -}}
  {{- with $page.Params.playlist }}
    {{- $href = printf "%s&list=%s" $href . -}}
  {{- end }}
{{- else -}}
  <a href="{{ $page.RelPermalink | safeURL }}" {{ with .Title }}title="{{ . }}"{{ end }}>{{ $text }}</a>
{{- end -}}

<a href="{{ $href | safeURL }}">{{ $text }}</a>
```
<h3 id="from-youtube-description">From YouTube Description</h3>
<p>Let&rsquo;s render links to YouTube from the <code>links</code> property:</p>
<p><a href="https://icle.es/layouts/_default/single.plain.txt">layouts/_default/single.plain.txt</a></p>
```gotmpl
{{ with .Params.links }}
Links:
{{- $this := $.Page }}
{{ range . -}}
  {{- $target := $this.GetPage .url -}}
  {{- if and $target (eq $target.Type "youtube") -}}
    {{- $href := printf "https://www.youtube.com/watch?v=%s" $target.Params.youtubeId -}}
    {{- with $target.Params.playlist -}}
      {{- $href = printf "%s&list=%s" $href . -}}
    {{- end -}}
    {{ .title }}: {{ $href }}
  {{- else if $target -}}
    {{ .title }}: {{ $target.Permalink }}
  {{- else -}}
    {{ .title }}: {{ .url | absURL }}
  {{- end }}
{{ end }}
{{ end }}
```
<h3 id="future-links">Future Links</h3>
<p>While we&rsquo;re at it, let&rsquo;s skip rendering any links that go live in the future:</p>
```gotmpl
{{- $target := $this.GetPage .url -}}
{{- if and $target (eq $target.Type "youtube") (not ($target.PublishDate.After now)) -}}
  {{- $href := printf "https://www.youtube.com/watch?v=%s" $target.Params.youtubeId -}}
  {{- with $target.Params.playlist -}}
    {{- $href = printf "%s&list=%s" $href . -}}
  {{- end -}}
  {{ .title }}: {{ $href }}
{{- else if and $target (ne $target.Type "youtube") -}}
  {{ .title }}: {{ $target.Permalink }}
{{- else if not $target -}}
  {{ .title }}: {{ .url | absURL }}
{{- end }}
```
<h3 id="lets-also-skip-draft-posts">Let&rsquo;s also skip draft posts</h3>
```gotmpl
{{- else if not $target -}}
    {{- $url := .url -}}
    {{- $isExternal := or (strings.HasPrefix $url "http") (strings.HasPrefix $url "mailto:") (strings.HasPrefix $url "#") -}}
    {{- $isTag := strings.HasPrefix $url "/tags/" -}}

    {{- if or $isExternal $isTag -}}
        {{ .title }}: {{ $url | absURL }} {{ "\n" }}
    {{- else -}}
        {{- warnf "Unresolved internal link: %q in %q" $url $this.File.Path -}}
    {{- end -}}
{{- end }}
```
<h2 id="next">Next</h2>
<p>This covers the Hugo-side of things.</p>
<p>There are two more parts, that I&rsquo;d like to happen automatically:</p>
<ul>
<li><a href="https://icle.es/projector-upload.md">Uploading the video</a></li>
<li><a href="https://icle.es/projector-sync.md">Syncing metadata</a></li>
</ul>
<h2 id="links--references">Links / References</h2>
<ul>
<li><a href="https://discourse.gohugo.io/t/generating-youtube-descriptions-using-hugo/55233/2?u=drone.ah">Suggestions from <code>jmooring</code> on hugo discourse</a></li>
<li><a href="https://gohugo.io/configuration/cascade">cascade</a></li>
</ul>
<h2 id="updates">Updates</h2>
<ul>
<li>2025-07-15: add note about skipping draft posts</li>
<li>2025-07-15: permalink file references to this commit</li>
</ul>
]]></content:encoded></item><item><title>Let's Play Space Engineers | Pilot Series</title><link>https://icle.es/2018/03/19/lets-play-space-engineers-pilot-series/</link><pubDate>Mon, 19 Mar 2018 15:00:07 +0000</pubDate><guid>https://icle.es/2018/03/19/lets-play-space-engineers-pilot-series/</guid><description>&lt;h2 id="introduction">Introduction&lt;/h2>
&lt;p>I have been watching gameplay videos on youtube for a while now. I have always
been inspired by them and wanted to start a series of my own.&lt;/p>
&lt;p>I hadn't played space engineers for a few months and had been wanting to go
back to it. That made it an ideal candidate to try this on. One thing I always
struggled with Space Engineers is that it doesn't have a goal to work towards.
To this end, I have tried to come up with a backstory that'll give something to
work towards&lt;/p></description><content:encoded><![CDATA[<h2 id="introduction">Introduction</h2>
<p>I have been watching gameplay videos on youtube for a while now. I have always
been inspired by them and wanted to start a series of my own.</p>
<p>I hadn't played space engineers for a few months and had been wanting to go
back to it. That made it an ideal candidate to try this on. One thing I always
struggled with Space Engineers is that it doesn't have a goal to work towards.
To this end, I have tried to come up with a backstory that'll give something to
work towards</p>
<p>It was substantially more difficult than it looks to talk and play a game and
the first couple of episodes are incredibly stumbly. I share them for posterity,
continuity and hopefully to also show how much improvement there is later on,
hopefully.</p>
<h3 id="backstory">Backstory</h3>
<p>A lone space engineer wakes up in his small ship, far away from a home he once
knew. There are only a handful of people still awake, with a few thousand people
across a few factions in cryo-sleep. A capital ship is being built to house
these cryo chambers. Several engineers have been sent out into the galaxies to
build a base.</p>
<p>Their mission is to colonise planets, ideally multiple planets, for each of the
three factions. With a few hundred to a thousand people in each faction. Once
all the habitats have been built, the engineer is to send a radio signal and
await the arrival of the cargo.</p>
<p>With the heavy burden of this mission on their shoulders, this space engineer
wakes up, caught in the gravitational pull of a blue planet.</p>
<h2 id="episodes">Episodes</h2>
<p>Below are the episodes already uploaded to youtube.</p>
<h3 id="01---hunting-for-uranium">#01 - Hunting for Uranium</h3>
<p><a href="https://youtu.be/GOqmD4lVTGM">https://youtu.be/GOqmD4lVTGM</a></p>
<p>In the first episode, we start in a respawn ship within the gravitational pull
of Earth. We then move off into space and go hunting for uranium before we run
out of power. The most excitement came when I realised that I was running out of
oxygen and I hadn't taken a canister with me. Will I die from suffocation? Find
out ;)</p>
<p>This is a very noob video, my very first. Also, due to a recording mistake,
there are no game sounds on this video :(</p>
<h3 id="02---starting-a-base">#02 - Starting a Base</h3>
<p><a href="https://youtu.be/7qVowX5whJ4">https://youtu.be/7qVowX5whJ4</a></p>
<p>We identify a location to start our base out on and start building it in
earnest. Partway through, I realise that the scaffolding that I had painstaking
built out was way too large, so I tear it down and try to build a small base. I
also spend some time mining out a bunch of iron.</p>
<p>This is also a very noob video, though I think there are fewer boring parts
(hopefully). The game audio issue is also fixed part way through.</p>
<h3 id="03---furnishing">#03 - Furnishing</h3>
<p><a href="https://youtu.be/m5Enko3Sxxg">https://youtu.be/m5Enko3Sxxg</a></p>
<p>This episode revolves around finishing construction of some of the items inside
the base. There was some confusion about how to build a cargo container without
dismantling the one on the ship.</p>
<p>This is hopefully starting to get a little better.</p>
<h3 id="04---more-furnishings">#04 - More Furnishings</h3>
<p><a href="https://youtu.be/oqEjvVypnlI">https://youtu.be/oqEjvVypnlI</a></p>
<p>Realise that I am running out of oxygen (again) and we don't have an Oxygen
Generator or Ice. Fix that first, then build a turret for some protection.</p>
<p>I felt this episode was a lot better.</p>
<h3 id="05---the-bug">#05 - The Bug</h3>
<p><a href="https://youtu.be/QXClJZm9Hb0">https://youtu.be/QXClJZm9Hb0</a></p>
<p>This episode starts with building a rudimentary mining ship which I screw up. I
had been away from this game for a while ;) I then fix a bunch of the stuff, do
some mining, then fix a bunch of other things.</p>
<p>This episode also felt pretty ok to me.</p>
<h3 id="06---the-shredder">#06 - The Shredder</h3>
<p><a href="https://youtu.be/3w1T7pClos0">https://youtu.be/3w1T7pClos0</a></p>
<p>In this episode, I build a grinding ship. I then use this ship to grind down the
original respawn ship completely. I also reconstruct the roof of the base to be
a little tidier. The rest of the episode is spent scouting for resources.</p>
<p>It feels like I need to commentate more. While editing, I realise that there are
a few unexpressed thoughts and the sheer amount of time when I am not saying
anything still surprises me. A lot more work still to do :)</p>
<h3 id="07---the-digger">#07 - The Digger</h3>
<p><a href="https://www.youtube.com/watch?v=xcBFEOzxyEQ">https://www.youtube.com/watch?v=xcBFEOzxyEQ</a></p>
<p>We build another version of the miner, so that we don't have to deal with the
container snafu 'bug' ;) This episode runs a little longer, but we end up with
a much better version of the miner which I call the digger. This is a callback
to <a href="https://www.genomised.com/games/digger">a game that was released in 1983</a>
which I loved growing up :) You can
<a href="http://www.futrega.org/digger/">try it online.</a></p>
<p>I feel that the videos are definitely improving and look forward to hearing what
you think :)</p>
<h3 id="08---tim-is-in-charge">#08 - Tim is in Charge</h3>
<p><a href="https://youtu.be/6NCFKtMxRnQ">https://youtu.be/6NCFKtMxRnQ</a></p>
<p>Tidy the base up a bit, plugging the reactor into the conveyor system. I then
set up Talendan's inventory management (TIM) to automate the refinery,
assembler and the inventories. Set up some LCD panels to see the status of these
as well.</p>
<h3 id="09---base-expansion">#09 - Base Expansion</h3>
<p><a href="https://www.youtube.com/watch?v=3PmEuCeQu8U&amp;index=9&amp;t=0s&amp;list=PLQb-fOWHIdUzyM-bJllq3QpWdVGDBhC98">https://www.youtube.com/watch?v=3PmEuCeQu8U&index=9&t=0s&list=PLQb-fOWHIdUzyM-bJllq3QpWdVGDBhC98</a></p>
<p>Fix a couple of things on the base and start on expanding it.</p>
<h3 id="10---the-mole">#10 - The Mole</h3>
<p>Build a tiny mining ship using the Vertex Thrust 2 Script. This doesn't go
exactly according to plan.</p>
<h3 id="11---the-refinery-room">#11 - The Refinery Room</h3>
<p><a href="https://www.youtube.com/watch?v=tiqFMIspVHU">https://www.youtube.com/watch?v=tiqFMIspVHU</a></p>
<p>Get the framework for the refinery room more or less complete</p>
<h3 id="12---the-beaver">#12 - The Beaver</h3>
<p><a href="https://www.youtube.com/watch?v=L7-unJTywWo">https://www.youtube.com/watch?v=L7-unJTywWo</a></p>
<p>Most of this episode was spent trying to build a small and compact enough
welding ship.</p>
<h3 id="13---the-refinery-room-pt-2">#13 - The Refinery Room Pt 2</h3>
<p><a href="https://www.youtube.com/watch?v=hsMY4q_hBHw">https://www.youtube.com/watch?v=hsMY4q_hBHw</a></p>
<p>We weld up the refinery room and link it up to the rest of the cargo network.</p>
<h3 id="14---misbehavin-tim">#14 - Misbehavin' Tim</h3>
<p><a href="https://www.youtube.com/watch?v=CMMrfkdvItM">https://www.youtube.com/watch?v=CMMrfkdvItM</a></p>
<p>Start on boring out the refinery room and run into some trouble with Tim too.</p>
<h3 id="15---assembler-jigsaw">#15 - Assembler Jigsaw</h3>
<p><a href="https://www.youtube.com/watch?v=Nq0E45KqhhM">https://www.youtube.com/watch?v=Nq0E45KqhhM</a></p>
<p>Start putting down assemblers.</p>
<h3 id="16---assembler-room">#16 - Assembler Room</h3>
<p><a href="https://www.youtube.com/watch?v=vORayj8-f-0">https://www.youtube.com/watch?v=vORayj8-f-0</a></p>
<p>Finish construction of the assembler room.</p>
<h3 id="17---base-with-a-view">#17 - Base with a View</h3>
<p><a href="https://www.youtube.com/watch?v=9i2N8o9c1KQ">https://www.youtube.com/watch?v=9i2N8o9c1KQ</a></p>
<p>Prettify the base and tidy things up.</p>
<h3 id="18---the-storage-room">#18 - The Storage Room</h3>
<p><a href="https://www.youtube.com/watch?v=UcmL3luT_8U">https://www.youtube.com/watch?v=UcmL3luT_8U</a></p>
<p>Drilling out the storage room</p>
<h3 id="19---storage-room-complete">#19 - Storage Room Complete</h3>
<p><a href="https://www.youtube.com/watch?v=BrTGpPYQi0c">https://www.youtube.com/watch?v=BrTGpPYQi0c</a></p>
<p>Completed the welding and setup of the storage room.</p>
<h3 id="20---control-room">#20 - Control Room</h3>
<p><a href="https://www.youtube.com/watch?v=TaAL_MOdghY&amp;t=2s">https://www.youtube.com/watch?v=TaAL_MOdghY&t=2s</a></p>
<p>Tidying up the Control room and preparing the base for pressurisation.</p>
<h3 id="21---fully-automated-mining">#21 - Fully Automated Mining</h3>
<p><a href="https://www.youtube.com/watch?v=t3uaLVomaMo">https://www.youtube.com/watch?v=t3uaLVomaMo</a></p>
<p>Using Rdav's AI Autominer Script to put together a fully autonomous mining
ship.</p>
<h3 id="22---ant-mk-ii-better-automated-miner">#22 - Ant Mk II Better Automated Miner</h3>
<p><a href="https://www.youtube.com/watch?v=uvLNVdIRlkg">https://www.youtube.com/watch?v=uvLNVdIRlkg</a></p>
<p>While falling asleep, I had some ideas on how to improve the Ant. I get on with
constructing the Ant Mk II.</p>
<h3 id="23---testing-the-ant-mk-ii">#23 - Testing the Ant Mk II</h3>
<p><a href="https://youtu.be/WhtVJZxtj3E">https://youtu.be/WhtVJZxtj3E</a></p>
<p>Wait, why does the ship try and drill through the asteroid sideways?</p>
<h3 id="24---ant-mk-ii-chassis">#24 - Ant Mk II Chassis</h3>
<p>We build the Chassis around most of the Ant, send it off mining and start
working on airlocks.</p>
<h3 id="25---rotary-airlock">#25 - Rotary Airlock</h3>
<p>Put in Airlocks and start on getting the base airtight.</p>
<h3 id="26---airtight-refinery-room">#26 - Airtight Refinery Room</h3>
<p>We manage to get the refinery room airtight? What was the problem - something I
had done right at the start of setting the room up.</p>
<h3 id="27---fully-pressurised">#27 - Fully Pressurised</h3>
<p>Fix the autominers so they work across reloads. Get the base fully pressurised
and move on to the next project.</p>
<h3 id="28---holey-cave">#28 - Holey Cave</h3>
<p>What I wanted was to have the new section to be mostly just rock, or in this
case, iron deposits. Do I manage to get it airtight?</p>
<h3 id="29---unholey-cave">#29 - Unholey Cave</h3>
<p>Working on making the way to the hanger airtight.</p>
<h3 id="30---fixing-sim-speed">#30 - Fixing Sim Speed</h3>
<p>Space Engineers had been dragging for a few episodes. Fix that.</p>
<h3 id="31---way-to-the-hangar">#31 - Way to the Hangar</h3>
<p>We make progress building our way towards the hangar.</p>
<h3 id="32---building-a-tunnel">#32 - Building a Tunnel</h3>
<p>Building the tunnel that'll take us to the Hangar.</p>
<h3 id="33---finishing-the-tunnels">#33 - Finishing the Tunnels</h3>
<p>We finish off the tunnel to the Hangar</p>
<h3 id="34---under-the-stairs">#34 - Under the Stairs</h3>
<p>We start furnishing under the stairs ;)</p>
<h3 id="35---starting-the-hangar">#35 - Starting the Hangar</h3>
<p>We make our way to the hangar and start on it in earnest.</p>
<h3 id="36---hangar-foundations-pt-1">#36 - Hangar Foundations pt 1</h3>
<p>We start putting in the struts that will hold the hangar together</p>
<h3 id="37---hangar-foundations-pt-2">#37 - Hangar Foundations pt 2</h3>
<p>We continue our work in putting in the struts around the hangar</p>
<h3 id="38---small-steel-tubes">#38 - Small Steel Tubes</h3>
<p>While putting in the tubing around the hangar, we run out of small steel tubes.</p>
<h3 id="39---automining-without-lag">#39 - Automining Without Lag</h3>
<p>Try and get the autominers working without lag.</p>
<h3 id="40---faster-mining">#40 - Faster Mining</h3>
<p>Try and speed up automatic mining by attaching several more drills.</p>
<h3 id="41---hangar-foundations-pt-3">#41 - Hangar Foundations pt 3</h3>
<p>Putting down another set of foundations for the hangar</p>
<h3 id="42---hangar-foundations-pt-4">#42 - Hangar Foundations pt 4</h3>
<p>Piping up the hangar</p>
<h3 id="43---the-printer">#43 - The Printer</h3>
<p>Build a welding ship and get started on the capital ship.</p>
<h3 id="44---everything-is-broken-">#44 - Everything is Broken :(</h3>
<p>One by one fail by fail. At least, that's how it felt.</p>
<h3 id="45---fixing-things">#45 - Fixing Things</h3>
<p>Try and fix everything that broke in the last episode.</p>
<h3 id="46---making-space">#46 - Making Space</h3>
<p>Making more space inside the large grid ship to put things.</p>
<h3 id="47---interior-design">#47 - Interior Design</h3>
<p>So... What should go inside this brand spanking new ship?</p>
<h3 id="48---no-more-gold">#48 - No More Gold!</h3>
<p>We run out of gold while building the jump drive.</p>
<h3 id="49---detaching-the-ship">#49 - Detaching the Ship</h3>
<p>We grind off the supporting beams. Will the ship crash and burn?</p>
<h3 id="50---the-big-five-o">#50 - The Big Five O</h3>
<p>The fiftieth episode of this series. My first ever YouTube series and it has got
to 50 episodes. Hurrah!</p>
<h3 id="51---interior-redesign">#51 - Interior Redesign</h3>
<p>I start off with the intention of finishing off the hanger, but end up grinding
the whole hangar down.</p>
<h3 id="52---rebuilding-the-hangar">#52 - Rebuilding the Hangar</h3>
<p>We get back on to the hangar and get most of it down</p>
<h3 id="53---the-right-wing">#53 - The Right Wing</h3>
<p>No, it's not a political episode, it's about building the wing on the right
hand side of the ship.</p>
<h3 id="54---out-of-cobalt">#54 - Out of Cobalt</h3>
<p>Working on the right wing and I run out of metal grids, which as it turned out
was because we were out of Cobalt.</p>
<h2 id="future-plans">Future Plans</h2>
<p>The main next plan is to flesh out the base a bit and get a solid starting
point. After that, we'll go to the moon. We'll build a moon base with a
habitat of some form.</p>
<p>If I am not bored after that, I might try heading to Mars or the Alien planet
since I've not been to either of those locations.</p>
<h2 id="unlikely-but-would-be-awesome">Unlikely but would be awesome</h2>
<p>In an offline map, kaljack and I were working on building a massive capital ship
with hundreds (or thousands) of cryo chambers. The idea being that this ship
would contain the remaining people from a now dead civilisation. They are
looking for a place to land and call home.</p>
<p>The habitats and the environments we are building are for these people. If we
ever finish that capital ship, we'll get it jump into our world and land on one
or more of these locations.</p>
<h2 id="finally">Finally</h2>
<p>I welcome comments, ideas and thoughts, ideally in the form of compliments ;)
but I also welcome constructive criticisms, ideas, questions and requests.</p>
<p>If you like Space Engineers, you might also like
<a href="https://www.gamecupid.com/games/space-engineers/games-like">games like Space Engineers (by game cupid)</a>\</p>
]]></content:encoded></item></channel></rss>