I spend 3 hours per day in commute. And while generally it’s tempting to be on my laptop, or staring at my phone, it’s not healthy for your eyes. (And you get headaches etc).
Solution consists of noise-cancelling headphones and audio files to listen. Regular music and audio books are handled by iTunes, that’s not an issue. But I want to have a separate application for lectures that I find on youtube or elsewhere, or stand-up commedians, meditation and breathing exercises.
VLC iPhone App to the rescue
Good things about VLC mobile:
- it can play while phone is locked (unlike Youtube app)
- it can organize content by directories
- it can display embedded APIC attached picture of mp3 files (for easier navigation)
Some bad quirks of the VLC mobile:
- directories are determined by album names in ID3V2,
- not all mp3 have ID3V2 tags set properly, you have to set it yourself,
- it will cache background image of mp3 files,
- you might need to reinstall the VLC app if it does not recognize background images.
With that being said my solution consists 1 python helper script and a following directory structure with all mp3s:
./tag.py
./Comedian 1/skit 1.mp3
./Comedian 1/skit 2.mp4
./Comedian 2/background.jpg
./Comedian 2/skit 1.mp3
./Lecture 1/background.jpg
./Lecture 1/Lesson 1.mp3
./Lecture 1/Lesson 2.mp3I made a helper script to
- convert any
mp4s orwebms tomp3s - set album name, song title, track name, so that VLC content resembles the directory
- set the background image of the mp3 of
background.jpg
Big warnings:
- This is destructive operation, and your files can lose original ID3V2 tags, only use this on duplicate of files (keep the backup)
background.jpgshould have dimensions 436x436 (smaller dimensions don’t work)
How to copy?
Use iTunes file sharing while iPhone is connected to laptop with lightning cable.
tag.py
#!/usr/local/bin/python
import os
import sys
import subprocess
import re
import mutagen, mutagen.id3
D = '/Users/emir/Commute Audios/'
for d, dirs, files in os.walk(D):
videos = [f for f in files if f.endswith('.mp4') or f.endswith('.webm')]
if d:
d += '/'
for video in videos:
mp3 = video.rsplit('.', 1)[0]+'.mp3'
if os.path.exists(d + mp3):
print('Consider deleting: ' + d + video)
continue
subprocess.check_call([
"ffmpeg",
"-i", d + video,
"-c:a", "libmp3lame",
"-q:a", "4",
d + mp3,
])
def check_and_apply(filename, edits, APIC=None, PRIV=None):
id3 = mutagen.id3.ID3(filename)
mutation = False
for name, value in edits.items():
if name not in ['TIT2', 'TRCK', 'TPE1', 'TALB']:
raise Exception("not implemented")
cur_frame = None
for frame in id3.values():
cur_name = repr(frame)[0:4]
if cur_name == name:
cur_frame = frame
break
if cur_frame is None:
cur_frame = mutagen.id3.Frames[name](encoding=3, text='')
id3.add(cur_frame)
cur_value = cur_frame.text[0]
if value != cur_value:
print('Diff', name, value, cur_value)
cur_frame.text[0] = value
mutation = True
if APIC is not None:
with open(APIC) as f:
apic_data = f.read()
existing_apic_data = None
for frame in id3.values():
cur_name = repr(frame)[0:4]
if 'APIC' == cur_name:
existing_apic_data = frame.data
break
if apic_data != existing_apic_data:
print('Diff APIC', filename)
id3.delall('APIC')
id3.add(mutagen.id3.APIC(
encoding=mutagen.id3.Encoding.LATIN1,
mime='image/jpeg',
type=mutagen.id3.PictureType.OTHER,
desc='',
data=apic_data,
))
mutation = True
if mutation:
id3.save(filename)
for d, dirs, files in os.walk(D):
if '/.git/' in d:
continue
mp3s = sorted([f for f in files if f.endswith('.mp3')])
assert d.startswith(D)
album_name = d[len(D):].replace('/', '_').replace('"', '_')
if not album_name:
continue
for i, mp3 in enumerate(mp3s):
track_num = str(i + 1) # .zfill(3)
artist = album_name
title = mp3
check_and_apply(
d + '/' + mp3,
{
"TALB": album_name,
"TPE1": artist,
"TIT2": title,
"TRCK": '{}/{}'.format(track_num, len(mp3s)),
},
APIC=(d+'/background.jpg') if os.path.exists(d + '/background.jpg') else None,
)