18

I have many MP3 files on my website and I have decided to upload them to Youtube, but unfortunately for me, YouTube does not allow me to do that. It requires video format only.

How can I convert these MP3s to video and add same set of images (one or more images) to the resulting video format.

I need to do this in bulk, not individually, I have hundreds of MP3 files.

It can be either a Windows-based or Linux-based application.

5 Answers 5

19

There's some info about using FFmpeg to encode audio with a still image for YouTube, here, and some advice for doing bulk conversions in Windows, here.

As for encoding, I find that this works:

ffmpeg -loop 1 -r 1 -i pic.jpg -i audio.mp3 -c:a copy -shortest -c:v libx264 output.mp4

The -c:v libx264 encoding considerably reduces the output file size as mentioned at: https://superuser.com/a/1472572/128124

4
  • I also found that adding -vcodec libx264 drastically reduces the video size increase relative to the MP3: superuser.com/a/1472572/128124 Aug 20, 2019 at 9:16
  • @CiroSantill Yes, that's a much better solution. I updated the answer.
    – slhck
    Aug 21, 2019 at 9:29
  • @slhck thanks for confirming! I edited to also add a link to my answer as attribution :-) Aug 21, 2019 at 9:33
  • Fantastic, that took under 20 seconds and actually made the video file smaller than the mp3, instead of it being blown up to gigabytes and needing a recode with handbrake after whatever video editor I used like a noob. Linux and command line rule, thanks! Sep 17, 2023 at 21:18
4

You could also consider simple bash oneliner instead of python script -

for i in *.mp3; do ffmpeg -v quiet -i "picture.jpg" -i "$i" -shortest -acodec copy "`sed 's/mp3/mp4/g'<<<$i`"; done

This will convert all mp3 files in your current dir into mp4 videos with picture.jpg.

For converting flac to mp3 that would be

for i in *.flac; do ffmpeg -v quiet -i "$i" -ab 320k -ac 2 -ar 48000 "`sed 's/flac/mp3/g'<<<$i`"; done

Notice "-v quiet", which shuts ffmpeg's loud mouth and also double quotes around $i and sed - this will ensure it won't fail with filenames containing spaces.

A tip: converting to video takes quite some time (at least for me). Try using -threads 4 (or any other value, of course. It won't make any sense on single-core cpu)

Edit: I've found out that "-loop 1" (suggested by others) creates loop (how surprising!) which is actually infinite. On my gentoo that means it will eat all your tasty bites. Without "-loop 1" it works just fine, so I suggest you to go with that.

2

There are some solutions for Ubuntu and other Linux systems at http://ubuntuforums.org/showthread.php?t=1686664. Most are shell commands or some other quick scripting language that can be looped for all of the MP3s, outputting video files. Then, you can just queue the video files for upload to YouTube. Among the solutions listed on the page:

  1. FFmpeg, then upload files to YouTube
    ffmpeg -loop 1 -i picture.jpg -i music.mp3 -shortest -acodec copy video.mp4 Loop accordingly for all mp3 files, then upload all the resulting video files.

  2. Python, convert to mp4 then upload files to YouTube

    #! /usr/bin/env python

    import sys, os

    inputOne = sys.argv[1] inputTwo = sys.argv[2]

    for i in sys.argv[1:]: if '.mp3' in i: output = i.replace('mp3','mp4')

    cmd = 'ffmpeg -loop_input -i "'+inputOne+'" -i "'+inputTwo+'" -shortest -acodec copy "'+output+'"'

    os.system(cmd)

It also uses ffmpeg, and accepts music and picture as arguments.

2
  • loop_input is deprecated in ffmpeg—you need to use -loop 1 now.
    – slhck
    Jan 12, 2014 at 3:45
  • Can we have more than one picture in the first solution (1. FFmpeg)?
    – Rasoul
    Apr 15, 2015 at 18:10
1

Convert recursively in subdirectories

Here is a simple find version that converts all .mp3 in the current directory and its subdirectories to mp4:

find . -iname '*.mp3' | sort | while IFS="" read -r f; do
  ffmpeg \
    -nostdin \
    -loop 1 \
    -r 1 \
    -i image.jpg \
    -i "$f" \
    -vcodec libx264 \
    -acodec copy \
    -shortest \
    "$(basename "${f%.*}.mp4")" \
  ;
done

Obtain some test data:

wget -O image.jpg https://upload.wikimedia.org/wikipedia/commons/8/83/Lama_Portrait_06072007_01.jpg
wget -O audio.ogg https://upload.wikimedia.org/wikipedia/commons/4/4f/BackUpAndPush.ogg
ffmpeg -i audio.ogg audio.mp3

Uploaded output: https://www.youtube.com/watch?v=tv3a6kP6BDA

If ffmpeg complains that the image size is not a multiple of 2 (required for libx264), you can first find the image size with Imagemagick:

identify image.jpg

and then round both width and height down to be even, e.g. if the size were 1023x513 we would use:

 convert image.jpg -resize 1024x512! imag2.jpg

where the ! forces that size to be used: https://unix.stackexchange.com/questions/319504/force-graphicsmagick-to-resize-image-to-specific-width

The -nostdin is required because ffmpeg reads bytes from stdin otherwise, and breaks our read!!! https://stackoverflow.com/questions/52374260/bash-variable-changes-in-loop-with-ffmpeg

The -vcodec libx264 drastically reduces the final video size to be much closer to that of the original MP3: the default video codec appears to be much worse. It might be possible to reduce the increase in size further by having less keyframes: https://stackoverflow.com/questions/30979714/how-to-change-keyframe-interval-in-ffmpeg In our sample data, we had +3 MB on a 3 minute 3 MB MP3 with a 1.1 MB image.

See also: Combine one image + one audio file to make one video using FFmpeg

Procedural video representation of audio

ffmpeg is very featureful, and you can generate several video representations of your audio using with commands of the form:

ffmpeg -i audio.mp3 \
  -filter_complex "[0:a]avectorscope=s=1920x1080,format=yuv420p[v]" \
  -map "[v]" -map 0:a avectorscope.mp4

Here avectorscope is the specific representation type.

Here is a handy list of such formats: https://gist.github.com/seyoum/4455e9bed74241bfbd640a8083fd38b3 all of which are documented under: http://ffmpeg.org/ffmpeg-filters.html#Multimedia-Filters

See also:

Procedural image representation of audio

https://stackoverflow.com/questions/4468157/how-can-i-create-a-waveform-image-of-an-mp3-in-linux/63869342#63869342

enter image description here

Tested in Ubuntu 19.04, ffmpeg 4.1.3. The files uploaded fine to YouTube as of August 2019.

5
  • I would not recommend to use AVI as output container. Use MP4 instead. Also for scaling you can use the scale filter in ffmpeg e.g. stackoverflow.com/a/40497904/435093
    – slhck
    Aug 21, 2019 at 9:30
  • @slhck thanks for this info. I still have to wrap my head around the formats at some point :-) Aug 21, 2019 at 9:33
  • 1
    See superuser.com/a/300997/48078
    – slhck
    Aug 21, 2019 at 9:36
  • 1
    Love the procedural video representation example! Just what I needed! Thanks for sharing!
    – tftd
    Jan 14, 2020 at 4:42
  • You'd better enclose .mp3 in quotes, like this: find . -iname ".mp3" Because if the filename contains spaces the command returns an error. Apr 8, 2020 at 15:26
-2

Copy your mp3 files (or what ever you want to encode, change your audio format accordingly.) to one folder. Also put an instance of ffmpeg in it, with a cover picture titled herringbone.jpg.

Then go to CMD and navigate to the folder.

Copy this:

for %a in (*.mp3) do "ffmpeg" -loop 1 -r 1 -i "Herringbone.jpg" -vcodec mpeg4 -i %a -acodec copy -shortest %a".mp4"

(To paste to CMD window click on the cmd line window upper left. Choose EDIT / Paste.)

Press enter.

Works with latest version of ffmpeg encoder (4.1.1)

I imagine you can change the video format too. Just change from mp4 to whatever you desire and what ffmpeg supports.

I found this at another forum, but it did not work until I switched the place of the -shortest in the script.

1
  • “Also put an instance of ffmpeg in it…” This is a ridiculous recommendation. FFmpeg is a binary that can be run from anywhere; forcing a copy into a specific directory is wasteful and overly complex. Aug 22, 2019 at 14:29

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .