Creating Ascending Ringtones for iOS / iPhone

When my most recent phone got abandoned by T-Mobile, — leaving me with a pile of security vulnerabilities — I finally give up. Despite really enjoying the Android user interface (particularly with Nova Launcher), I just couldn't stomach buying Yet Another Android Phone™ just to have the latest version. So now I'm the proud owner of an iPhone SE, which is delightfully hand-sized.

On Android, the process of installing a ringtone goes roughly as follows:

  1. Plug in your phone
  2. Drag your audio files (midi, mp3, m4a, etc.) to the proper folder

I had assumed it couldn't possibly be that much more difficult on the iPhone. But getting custom ringtones onto an iPhone is a giant pain in the ass. Guides on the internet go roughly as follows:

  1. Open the Kafkaesque nightmare that is iTunes
  2. Drag your audio file into iTunes
  3. Go into Get Info for the song
  4. Set a start and stop time with a max duration of 30 seconds, because of pointless technical limitations
  5. Right-click on the song and create an AAC version
  6. Show in Finder, finding the file on your local filesystem
  7. Drag that file to your desktop
  8. Rename its extension from .m4a to .mpr
  9. Delete the AAC file from iTunes
  10. Drag the .m4r file into the Tones section of iTunes
  11. Plug in your phone, go to the Tones section, and select the new ringtone
  12. Sync it

Of course, this doesn't get you an ascending ringtone, one of my favorite Android features. So I turned to ffmpeg, one of most byzantine command line applications ever created.

$ ffmpeg -i "Android Ringtone.mp3" -ss 00:00 -t 00:30 -af "afade=t=in:ss=0:d=10" -f mp4 "iOS Ringtone.m4r"
ffmpeg version 3.0 Copyright (c) 2000-2016 the FFmpeg developers
  built with Apple LLVM version 7.0.2 (clang-700.1.81)
  configuration: --prefix=/usr/local/Cellar/ffmpeg/3.0 --enable-shared --enable-pthreads --enable-gpl --enable-version3 --enable-hardcoded-tables --enable-avresample --cc=clang --host-cflags= --host-ldflags= --enable-opencl --enable-libx264 --enable-libmp3lame --enable-libxvid --enable-vda
  libavutil      55. 17.103 / 55. 17.103
  libavcodec     57. 24.102 / 57. 24.102
  libavformat    57. 25.100 / 57. 25.100
  libavdevice    57.  0.101 / 57.  0.101
  libavfilter     6. 31.100 /  6. 31.100
  libavresample   3.  0.  0 /  3.  0.  0
  libswscale      4.  0.100 /  4.  0.100
  libswresample   2.  0.101 /  2.  0.101
  libpostproc    54.  0.100 / 54.  0.100
[mp3 @ 0x7fee0b80a800] Skipping 0 bytes of junk at 10809.
Input #0, mp3, from 'Android Ringtone.mp3':
  Metadata:
    title           : Oh Yeah That Song
    artist          : That One Gal or Guy
    album           : That Album You Keep Buying Again and Again
    TT1             : Some Dumb Organizational Tag
    track           : Insert Integer Here
    genre           : Probably my Favorite Genre
    date            : Another Integer that Represents a Good Year in Music
  Duration: 00:02:01.55, start: 0.011995, bitrate: 167 kb/s
    Stream #0:0: Audio: mp3, 44100 Hz, stereo, s16p, 166 kb/s
Output #0, mp4, to 'iOS Ringtone.m4r':
  Metadata:
    title           : Oh Yeah That Song
    artist          : That One Gal or Guy
    album           : That Album You Keep Buying Again and Again
    TT1             : Some Dumb Organizational Tag
    track           : Insert Integer Here
    genre           : Probably my Favorite Genre
    date            : Another Integer that Represents a Good Year in Music
    encoder         : Lavf57.25.100
    Stream #0:0: Audio: aac (LC) ([64][0][0][0] / 0x0040), 44100 Hz, stereo, fltp, 160 kb/s
    Metadata:
      encoder         : Lavc57.24.102 aac
Stream mapping:
  Stream #0:0 -> #0:0 (mp3 (native) -> aac (native))
Press [q] to stop, [?] for help
size=     620kB time=00:00:30.00 bitrate= 169.2kbits/s speed=  21x
video:0kB audio:614kB subtitle:0kB other streams:0kB global headers:0kB muxing overhead: 0.976624%
[aac @ 0x7fee0b819400] Qavg: 1646.151

Here are what the switches mean:

  • -i "Android Ringtone.mp3" the input file
  • -ss 00:00 the start time (at the beginning, in this case)
  • -t 00:30 how long of a segment (30 seconds)
  • -af "afade=t=in:ss=0:d=10" starting at 0 seconds in, fade in over a duration of 10 seconds
  • -f mp4 treat it as mp4 audio, since ffmpeg doesn't recognize the .m4r extension
  • "iOS Ringtone.m4r" the output file

Just drag that file into iTunes, sync, and it's done:

[Category: Personal] [Tags: ffmpeg, iOS, iPhone]