DEV Community

Cover image for Spotify Keyring Generator
Archie Webster
Archie Webster

Posted on

Spotify Keyring Generator

A tutorial for using Blender and Python to procedurally generate STLs to 3D print

This might also help if you are struggling to use Python with Blender.

Alt Text

The easiest way to understand Blender's Python commands is to open up the GUI into the Scripting workspace. Here, any modification made to Blender's UI is displayed in the console.

For example when deleting the default cube, this is the output to the console:

Alt Text

Clearing the workspace

The first thing you will want to do is delete everything in the default workspace. This makes sure that we are starting from a clean slate with no pesky default cube. Notice that we have to import Blender's python module to be able to interact with Blender.

import bpy
bpy.ops.object.select_all(action='SELECT')
bpy.ops.object.delete()
bpy.ops.object.select_all(action='DESELECT')
Enter fullscreen mode Exit fullscreen mode

Creating the base

Speaking of cubes, the first thing to do is add a cube for the base. As explained before, to find these commands I will add a cube and scale it to a size that looks good, then copy the log from the console.

bpy.ops.mesh.primitive_cube_add(enter_editmode=False, align='WORLD', location=(0, 0, 0))
bpy.context.object.scale = (0.005, 0.03, 0.001)
Enter fullscreen mode Exit fullscreen mode

Cutting the keyring

To make a hole for the keyring I will add a cylinder and then subtract it from the base with a boolean modifier. When creating the cube I copied the entire command from the terminal, however to simplify the code, most of these arguments are actually defaults.

I can also combine translating and scaling the object into the add function. If in any doubt the console will output the actual arguments that have been parsed when you run the script.

bpy.ops.mesh.primitive_cylinder_add(radius=0.003, depth=0.005, location=(.04, -0.024, 0))
Enter fullscreen mode Exit fullscreen mode

This line was actually run like this:

Alt Text

For the next step it will be useful to keep track of the cube and cylinder. You can't assign objects to variables when you create them, however as they are the only objects in the scene, we can reference them like this:

cube = bpy.data.objects['Cube']
cylinder = bpy.data.objects['Cylinder']
Enter fullscreen mode Exit fullscreen mode

Then we can create and apply the boolean modifier:

bool = cube.modifiers.new(type="BOOLEAN", name="bool")
bool.object = cylinder
bool.operation = 'DIFFERENCE'
bpy.context.view_layer.objects.active = cube
bpy.ops.object.modifier_apply(modifier="bool")
Enter fullscreen mode Exit fullscreen mode

After the modifier has been applied, the cylinder can be deleted so that we don't accidently export it with the STL:

bpy.ops.object.select_all(action='DESELECT')
cylinder.select_set(True)
bpy.ops.object.delete()
Enter fullscreen mode Exit fullscreen mode

Getting the Spotify code

Spotify doesn't have an API for it's codes however their website, Spotify Codes makes a request to this url:

https://scannables.scdn.co/uri/plain/{format}/{background-color}/{bar-color}/{resolution}/{URI}

For this purpose we want an SVG so it can be used in Blender, therefore our base URL will look like this:

https://scannables.scdn.co/uri/plain/svg/ffffff/black/640/

Then all we need to do is append the song or playlist URI to the end.

Blender can only open an SVG from a file so we must cache it into a file like this:

import requests

URI = input("Enter a song URI")

r = requests.get("https://scannables.scdn.co/uri/plain/svg/ffffff/black/640/" + URI, stream=True)

with open("SpotifyCodeDownload.svg", 'wb') as f:
    for chunk in r.iter_content(1024): 
        f.write(chunk)
Enter fullscreen mode Exit fullscreen mode

Then we can import it into Blender:

bpy.ops.import_curve.svg(filepath="SpotifyCodeDownload.svg", filter_glob="*.svg")
Enter fullscreen mode Exit fullscreen mode

Processing the SVG

Alt Text

EEEK! The SVG is imported as hundreds of individual curves and there is no way around this.

First of all, the curve named 'curve' is a rectangle surrounding the code so we can delete that. Don't forget to deselect everything before you start selecting.

bpy.ops.object.select_all(action='DESELECT')
bpy.data.objects['Curve'].select_set(True)
bpy.ops.object.delete()
Enter fullscreen mode Exit fullscreen mode

Next we can combine the rest of the curves into one mesh, this can be done by selecting all the curves in the collection named after the SVG file.

In order to do most operations in Blender you need to have an active object, so after selecting the collection we will make Curve.001 the active object.

for obj in bpy.data.collections['SpotifyCodeDownload.svg'].all_objects:
        obj.select_set(True)


bpy.context.view_layer.objects.active = bpy.data.objects["Curve.001"]

bpy.ops.object.join()

bpy.ops.object.convert(target='MESH')

bpy.ops.object.origin_set(type='ORIGIN_GEOMETRY', center='MEDIAN')
Enter fullscreen mode Exit fullscreen mode

The scene currently looks like this:

Alt Text

So the last thing we need to do is move the SVG in the viewport and copy the output. The first two lines of this extract show an absolute rotation on the z axis.

curve = bpy.data.objects["Curve.001"]

curve.rotation_euler[2] = 1.5708

bpy.ops.transform.resize(value=(0.277968, 0.277968, 0.277968))


bpy.ops.transform.translate(value=(-0.0734364, -0.0216113, 0.0009043))
Enter fullscreen mode Exit fullscreen mode

And then extrude it:

bpy.ops.object.mode_set(mode='EDIT')

bpy.ops.mesh.select_all(action='SELECT')

bpy.ops.mesh.extrude_region_move(MESH_OT_extrude_region= TRANSFORM_OT_translate={"value":(0, 0, 0.000875622), "orient_type":'NORMAL'})

bpy.ops.object.mode_set(mode='OBJECT')
Enter fullscreen mode Exit fullscreen mode

Exporting

Finally we can export everything as an stl so it can be 3D printed:

bpy.ops.object.select_all(action='SELECT')
bpy.ops.export_mesh.stl(filepath="out.stl", use_selection=True, global_scale=1000)
Enter fullscreen mode Exit fullscreen mode

And that's it, the program can be run with this command:

blender -b --python BlenderStl.py
Enter fullscreen mode Exit fullscreen mode

Full code

You can find all the code here:

https://github.com/artomweb/Spotify-Code-to-Stl

Top comments (0)