Chris Padilla/Blog

My passion project! Posts spanning music, art, software, books, and more
You can follow by Newsletter or RSS! (What's RSS?) Full archive here.

    The Alchemist

    A boy and his sheep

    Read Paulo Coelho's The Alchemist over winter break!

    Automating YouTube Uploads in Python

    My command line script for generating my art posts is working like a charm! This week, I wanted a workflow for YouTube as well.

    The music I share on the socials also end up on this blog. Video hosting is provided by YouTube, which is still a social platform, but it's closer to the Own Your Content ethos than just letting it live on Instagram1.

    My current manual procedure:

    1. Upload video to YouTube
    2. Fill out the form for title, description, etc.
    3. Copy the video URL
    4. Write out the Blog Post, pasting the copied url in
    5. Share to The Grams

    While step 5 will be a fun project for both workflows, today I'm going to focus on truncating steps 1-4.

    Youtube Setup

    For the most part, this has already been solved. Much of the Boiler plate code will come from YouTube's Data API docs. I'll document the tweaks unique to my situation..

    Class Encapsulation

    I'm going to want to reuse the args that we'll receive. So instead of a single script, I'll wrap this in a class:

    class YoutubeUploader:
        def __init__(self, args):
            self.args = args
            self.prompt_for_video_details(args)
        
        . . . 
        
    if __name__ == '__main__':
    
        # Get args
        YTU = YoutubeUploader(args)

    Getting Arguments

    The provided script uses argparser to get video details when running our command:

    if __name__ == '__main__':
        argparser.add_argument("--file", help="Video file to upload")
        argparser.add_argument("--title", help="Video title", default="")
        argparser.add_argument("--description", help="Video description",
            default="")
        argparser.add_argument("--category", default="22",
            help="Numeric video category. " +
                "See https://developers.google.com/youtube/v3/docs/videoCategories/list")
        argparser.add_argument("--keywords", help="Video keywords, comma separated",
            default="")
        argparser.add_argument("--privacyStatus", choices=VALID_PRIVACY_STATUSES,
            default=VALID_PRIVACY_STATUSES[0], help="Video privacy status.")
        args = argparser.parse_args()

    index.py

    Personally, I find this cumbersome to write out, so I'm going to opt for command line prompts. I'll add a prompt_for_video_details() method to the class:

    def prompt_for_video_details(self, args):
        if not self.args.file:
            file = input("File: ")
            file = file.replace("'", "").strip()
            setattr(self.args, 'file', file)
        if not self.args.title:
            title = input("Title (Gurlitt ā€“ The Return): ")
            setattr(self.args, 'title', title)
        if not self.args.description:
            description = input("Description: ")
            setattr(self.args, 'description', description)
        if not os.path.exists(self.args.file):
            exit("Please specify a valid file using the --file= parameter.")
        
        self.slug = input("slug(default to title): ")

    setattr() is being here as a workaround. The args dictionary provided by argparser does not allow direct attribution setting with the usual args['key'] approach. I can see the reasoning to keep it immutable, but for my case, I'm ok with mutating it since I likely won't be using the flags in most cases.

    Getting the YouTube ID

    Within the resumable_upload provided, I'll be getting the video id returned in the response. Here, I'll also respond with the remaining automation.

    if response is not None:
        if 'id' in response:
            video_id = response['id']
            print(("Video id '%s' was successfully uploaded." % response['id']))
            self.generate_blog_post(video_id=video_id)
            self.open_video(response['id'])
        else:
            exit("The upload failed with an unexpected response: %s" % response)

    Completing the Form

    Unfortunately, the API doesn't expose all of the required fields in the form. So while the video will upload, I have to complete another step by opening up the page. Here, I'm simply sticking in the video ID returned from the upload and using webbrowser to open those tabs:

    def open_video(self, id):
        print("Opening YouTube Studio!")
        print("Switch YT accounts if needed?")
        webbrowser.open_new_tab(f"https://studio.youtube.com/video/{id}/edit")
        webbrowser.open_new_tab(f"https://www.youtube.com/")

    Generating Markdown

    This will look very familiar compared to last week! I'm essentially reusing the same logic here:

    def generate_blog_post(self, video_id: str = '') -> bool:
        today = datetime.datetime.now()
    
        weekday = today.weekday()
        days_from_target = datetime.timedelta(days=MUSIC_TARGET_WEEKDAY - weekday)
        target_date = today + days_from_target
        target_date_string = target_date.strftime('%Y-%m-%d')
    
        date_ok = input(f"{target_date_string} date ok? (Y/n): ")
        if "n" in date_ok:
            print("Set date:")
            target_date_string = input()
            print(f"New date: {target_date_string}")
            input("Press enter to continue ")
    
        md_body = MUSIC_POST_TEMPLATE.format(self.args.title, target_date_string, video_id, video_id, self.args.description)
        with open(BLOG_POST_DIR + f"/{self.slug}.md", "w") as f:
            f.write(md_body)

    And that's it! Many future keystrokes and button clicks saved!

    1: Actually, looking up the Indie Web Wiki, I'm taking some comfort in this definition: "You own your own domain but use Tumblr.com or WordPress.com or some other hosted content solution to publish content (like posts) on your site. You own your permalinks so you can change hosting and (with some work) keep your permalinks working." With some work, indeed. Sounds like an interesting future project.

    Happy New Year!

    šŸŖ©

    šŸ¦•šŸŽŠ

    Auld Lang Syne

    Listen on Youtube

    2024 let's goooo!

    2023

    2023 has been a meaty year. In 2022 and the years just prior, I was planting several seeds. A few creative projects here and there, starting a new career, and making the move to Dallas. With 2023, much of the new is now integrating into my day to day life. A garden is growing!

    From that garden, here were some of the fruits:

    Sketching

    A Year of Working With the Garage Door Open

    I time capsuled an intention at the start of 2023. In January, I wrote:

    When I was a teenager leaving for college, I very ceremoniously made a promise to myself: Whatever I do, I want to be making things everyday.

    I was inspired by internet pop culture, largely webcomics, artists, musicians, developers, bloggers, and skit comedy on Youtube.

    Because of that, I had a dream as a kid. A weird dream - but my dream was to have a website. A home on the internet where I could create through all the mediums I loved - writing, music, art, even code!

    Since I have this dot com laying around, my aim for this year is to use it! I plan to work with the garage door open. Sharing what I'm learning, what I'm exploring in drawing and music, what I'm reading, and what I'm learning through my work in software.

    I can happily say: mission accomplished! Counting it all up, 205 posts made it on the blog this year. Not quite 365 days, but not bad. :)

    But the volume isn't really the point. The joy is in the making. And it's been a thrill to be lit up to make so much this year!

    So, while I'm not hitting a fully-algorithm-satiating level of daily output, I'm pretty ok with what's making it up here! Next year, I'm even planning to scale back. Making things everyday, but sharing when I'm ready. I want to fully honor the creative cycle, leaving in space for resting between projects.

    Charcoal!

    Art

    I drew! A LOT! in September of 2022 I committed to drawing and learning some technique. This year I stuck with it, finding time everyday to sketch.

    In 2022, it was life changing to be making music regularly - having a new voice to express through. I realized that you don't have to have "The Gift" to compose, you just do it!

    Same is true for art, and it's been equally life changing!

    With music, I've always been learning to listen, but composing and improvising taught me to listen to intuition. The same thing has happened through drawing. I've been really intentional about making time to just doodle everyday. Not worrying about the end result, I just wanted to have an idea and get it out the page. Being able to do that with drawing is a game changer ā€“ to see an image and then at least have a rough idea of it on the page is like nothing else!

    I have to say, music writing is fantastic because it expresses what otherwise is really difficult to express. It's almost other worldly. Art is thrilling, because it can capture things that do exist, or things that could exist - in a vocabulary that's part of the daily vernacular: shapes and color.

    Once you know the building blocks - anatomy, spheres, boxes, cylinders - and you can build with that... the real fun comes with drawing something that isn't in front of you. True invention!

    Even when drawing from reference, especially drawing people, there's something so satisfying about capturing life, just from moving the pencil across the page...

    So, yeah, I kind of love drawing now. You can see what I've been making on my blog and read about a few more lessons learned from drawing.

    Ice

    Music

    Picking up art, I had this worry that I wouldn't have any juice left for writing music. I'm thankful that the opposite has been true!

    I wanted to up the ante by recording acoustic instruments more than I did in 2022. And I managed to for Cinnamon, Spring, Sketches and Meditations! I have fun with pure music production projects like Forest, Whiteout, Floating, Ice. But, having spent a couple of decades on an acoustic instrument, I have a soft spot for making the music with my own hands!

    This year, I played lots of piano, got a classical guitar, listened to a wide variety of music (according to Spotify, mainly chill breakcore, math rock, and J-Ambient.)

    I love my new nylon string guitar, I spend a lot of time simply improvising melodies on it. Learned finger style, played some classical, and spent a lot of the year demystifying the neck of the guitar.

    I may be crazy for thinking this, but I'm really interested in learning jazz piano before spending more time on jazz sax. So I spent some time reading a few standards and some simple blues improv.

    A fun year for music, all in all! Looking to do more jazz in 2024!

    Stack of sketchbooks

    Tech

    My second full year in software! I've learned tons on the job and am absolutely proud to work with the team I'm on. No better place to be learning and making alongside really smart and driven folks!

    This year, I had the intent of really exploring in my spare coding time. By the start of the year, I was really comfortable with JavaScript development. I wanted to further "fatten the T," as it were. Explore new languages, investigate automated testing, and get familiar with cloud architecture. A tall order!!

    I started the year with testing, first understanding the philosophy of TDD, taking a look at what a comprehensive testing environment looks line in an application, and then getting my hands dirty with a few libraries. All of those articles can be found through the testing tag

    From there, I was itching to learn a new language. One of my previous projects was with a .NET open source application, and I was curious to see how an ecosystem designed for enterprise functioned. So, on to C##! I learned a great deal about Object Oriented Programming through the process, dabbled with the ASP.NET framework, and deployed to Azure. You can read more through the CSharp tag on my blog

    As if one language wasn't enough, I dabbled a bit in Go towards the end of the year. Now having an understanding of a server backend language, I was curious to see what a cloud-centric scripting language looked like. So I did a bit of rudimentary exploring for fun. Take a look at the Go tag for more.

    Honorary mention to spending time learning SQL! More through the SQL tag

    We'll see where the next year goes. After having gone broad, I'm ready to go deep. While I know Python, I'm interested in getting a few more heavy projects under my belt with it as well as further familiarizing myself with AWS.

    Stack of sketchbooks

    Reading

    I spent time making reading just for fun again! In that spirit, 2023 became the year of comics for me. I still read plenty of art, music, and non fiction books this year. You can see what my favorites were on my wrap up post.

    Life

    Dallas is great! Seeing plenty of fam, Miranda's making it through school, and I'm playing DnD on the regs with A+ folks. Can't ask for much more!

    2024

    My sincere hope for next year is to be open to what comes next. I like what's cooking and I'd love to see more, but the real thrill of this year was in exploring so many interests. We'll see! Happy New Year!