Can't give metadata of comment to MP3 file using ffmpeg - audio

I want to covert an AAC audio file to MP3 and add a comment in the metadata of the MP3 file using ffmpeg.
The -metadata comment option doesn't work and ffmpeg doesn't return an error.
The complete command I'm running is
ffmpeg -i "test.aac" -ab 128k -metadata comment='this is test' "test.mp3"
I also tried -metadata description='this is test' and even updated ffmpeg. Other options such as -metadata artist and -metadata album work well.
What's wrong with this approach?
Output
Stream mapping:
Stream #0:0 -> #0:0 (aac (native) -> mp3 (libmp3lame))
Press [q] to stop, [?] for help
Output #0, mp3, to 'test.mp3':
Metadata:
description : this is test
TSSE : Lavf58.29.100
Stream #0:0: Audio: mp3 (libmp3lame), 48000 Hz, stereo, fltp, 128 kb/s
Metadata:
encoder : Lavc58.54.100 libmp3lame
Environment
ffmpeg version 4.2.2 Copyright (c) 2000-2019 the FFmpeg developers
built with Apple clang version 11.0.3 (clang-1103.0.32.59)

Possible bug. ffmpeg is writing comment metadata as user text frame (TXXX) instead of the expected comment (COMM).
For now I suggest using a different tool for comment tag. eyeD3 example:
eyeD3 --comment "added a comment" input.mp3

ffmpeg by default writes an ID3v2 tag to MP3 output files. As of version 4.3.1 (or even snapshot 2021-02-10 and 2022-09-20) it is still wrongly written as a TXXX frame instead of COMM - /libavformat/id3v2.c does nowhere handle the needed association, and /libavformat/id3v2enc.c indicates that the -comment parameter is only used when providing a graphic to embed (i.e. album cover).
As an alternative you could force an ID3v1 tag (with all its shortcomings). You must also disable an ID3v2 tag creation, as almost every software encountering both ID3 versions prefers data from v2 over v1. The parameters to be added would be -write_id3v1 true -id3v2_version 0, so the overall execution is (on Windows):
ffmpeg -i "test.aac" -ab 128k -metadata "comment=this is a test" -write_id3v1 true -id3v2_version 0 "test.mp3"
This works as expected: no ID3v2 tag, only an ID3v1 tag where only the comment is filled. The quotation marks starting before comment and ending after test are needed so Windows knows where that one whole parameter starts and where it ends (and not with the next space character, as per default - that's also the reason why filenames should go into quotation marks).

Related

FFmpeg - how to set output sample_size

Trying to create a simple command line player for .dsf (DSD audio) files, and output to an alsa device that supports up to 24-bit 192 kHz sample rate. The following command almost works and it does play the track. Examining the bold text below, the dsf input file is converted to 24-bit/192 kHz, but the output is then truncated to 16-bit 192 kHz (pcm_s16le i.e, 16 bit little endian).
ffmpeg -i '01 - Sweet Georgia Brown.dsf' -f alsa hw:0,0
After displaying the ffmpeg banner and song metadata (tags), here is the result, bold is my emphasis:
Duration: 00:05:14.83, start: 0.000000, bitrate: 9234 kb/s
Stream #0:0: Audio: flac, 192000 Hz, stereo, s32 (24 bit)
Stream mapping:
Stream #0:0 -> #0:0 (flac (native) -> pcm_s16le (native))
Press [q] to stop, [?] for help
Output #0, alsa, to 'hw:0,0':
Since I can play this and many other tracks at full resolution using another player (foobar2000) it seems there might be an option in the encoder which is part of FFmpeg: Lavf57.83.100 I can find no information in any of the FFmpeg documentation that helps. Tried finding options in FFplay and even guessing using other FFmpeg options like this example.
ffmpeg -sample_fmt s24 -i '01 - Sweet Georgia Brown.dsf' -f alsa hw:0,0 ***** same results.
I'm stuck. Any suggestions?
Environment: Linux Mint 19.2, 64-bit, ASUS Xonar STXii sound card.
Each output format or device has a default encoder registered for each media type it accepts. ALSA accepts audio and its default encoder is 16-bit signed PCM.
You can change the encoder by specifying one.
ffmpeg -i '01 - Sweet Georgia Brown.dsf' -c:a pcm_s24le -f alsa hw:0,0

FFmpeg not copying all audio streams

I'm having trouble getting ffmpeg to copy all audio streams from a .mp4 file. After hours of searching online, it appears this should copy all streams (as shown in example 4 here):
ffmpeg -i in.mp4 -map 0 -c copy out.mp4
in.mp4 contains 3 streams:
Video
Audio track 1
Audio track 2
out.mp4 (which should be identical to in.mp4) contains only 2 streams:
Video
Audio track 1
FFmpeg does appear to correctly identify all 3 streams, but doesn't copy all of them over. Output from FFmpeg:
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Stream #0:1 -> #0:1 (copy)
Stream #0:2 -> #0:2 (copy)
Edit: Output from ffmpeg -v 9 -loglevel 99 -i in.mp4:
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from in.mp4':
Metadata:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf57.36.100
Duration: 00:00:06.03, start: 0.000000, bitrate: 5582 kb/s
Stream #0:0(und), 1, 1/15360: Video: h264 (Main), 1 reference frame (avc1 /
0x31637661), yuv420p(tv, bt470bg/unknown/unknown, left), 1920x1080 (0x0) [SAR 1:
1 DAR 16:9], 0/1, 5317 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Metadata:
handler_name : VideoHandler
Stream #0:1(und), 1, 1/48000: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz,
stereo, fltp, 128 kb/s (default)
Metadata:
handler_name : SoundHandler
Stream #0:2(und), 1, 1/48000: Audio: aac (LC) (mp4a / 0x6134706D), 48000 Hz,
stereo, fltp, 128 kb/s
Metadata:
handler_name : SoundHandler
Successfully opened the file.
At least one output file must be specified
[AVIOContext # 0000000001c2b9e0] Statistics: 153350 bytes read, 2 seeks
Edit 2 (solved): I managed to find the correct syntax from this ticket. For any others that are interested, the correct syntax is:
ffmpeg -i in.mp4 -vcodec copy -c:a copy -map 0 out.mp4
This will copy all streams.
FFmpeg have option to map all streams to output, you have to use option -map 0 to map all streams from input to output.
In full line it might look like:
ffmpeg -i in.mp4 -c copy -map 0 out.mp4
For more info see the documentation on stream selection and the -map option.
Apparently this is a popular question, so I'm posting my solution as an answer (was previously a comment reply) so that others can see.
I managed to find the correct syntax from this ticket. The correct syntax is:
ffmpeg -i in.mp4 -vcodec copy -c:a copy -map 0:0 -map 0:1 -map 0:2 out.mp4
This will copy all 3 streams.
OK, I read pretty deep into the ffmpeg man page and found this which should be useful:
Note that currently each output stream can only contain channels from
a single input stream; you can't for example use "-map_channel" to
pick multiple input audio channels contained in different streams
(from the same or different files) and merge them into a single output
stream. It is therefore not currently possible, for example, to turn
two separate mono streams into a single stereo stream. However
splitting a stereo stream into two single channel mono streams is
possible.
If you need this feature, a possible workaround is to use the amerge
filter. For example, if you need to merge a media (here input.mkv)
with 2 mono audio streams into one single stereo channel audio stream
(and keep the video stream), you can use the following command:
ffmpeg -i input.mkv -filter_complex "[0:1] [0:2] amerge" -c:a pcm_s16le -c:v copy output.mkv
You may want to read through and experiment with the man page instructions on man ffmpeg-filters to understand just what level of complexity you're getting into for naming channels and expected output.
[Edit: As Mulvya noted, this answers a question, but it was not quite the original poster's question.]
First I tried this broader answer here: https://stackoverflow.com/a/54616353/1422630
But I had trouble with a not supported subtitle track so I ended having to use this command:
avconv -i INFILE -c copy -map 0:a -map 0:v OUTFILE
I understand that, after I asked to copy, it basically copied only what I mapped (and it mapped all audio of course), as I don't care for the subtitles being embedded at all. If you want to map the subtitles, just add this -map 0:s.
It seems that specific ffmpeg versions ignore -c copy option and skip audio stream copy, thus resulting in final file with no audio, e.g. does not copy audio tracks and produce video with no sound.
The ffmpeg affected is for example used on Synology Disk Station devices:
ffmpeg version 2.7.7 Copyright (c) 2000-2015 the FFmpeg developers
built with gcc 4.9.3 (crosstool-NG 1.20.0) 20150311 (prerelease)
To resolve that, without analyzing file structure and manually mapping all audio streams with -map 0:1 -map 0:2 etc, I found very simple command to process it automatically:
ffmpeg -i INFILE -map 0 -c copy -c:a copy OUTFILE
This is different from -c:v -c:a as preserves chapters and subtitles together with video and all audio tracks with different languages, like english, spanish, french, russian or chineese.
Also in case you have more hardly broken file, which simple copy does not fix, please try this command, which potentially fix more errors, which could crash video player, or stuck video or audio:
ffmpeg -err_detect ignore_err -i INFILE -map 0 -c copy -c:a copy OUTFILE

How to join AAC files with AVCONV CONCAT using an input txt file?

I have a number of AAC files and want to concatenate them into one AAC file. When I do this with AVCONV at the command line and I am specific with the file names, it works. When I try to do this with a text file that holds a list of files, it fails. What led me here is the FFMPEG tutorial page at Concatenating media files. I get a variety of results depending on what I try and I cannot find any info on what I am doing wrong with the syntax.
My file list (list.txt in the same directory)...
file 'sr_program_2015_03_23_05_44_01.aac'
file 'sr_program_2015_03_23_07_44_58.aac'
When I follow the example at the page I mentioned above, I get an error. I included both the use of ffmpeg AND avconv but the results are the same.
ffmpeg...
ffmpeg -f concat -i list.txt -c copy output
ffmpeg version 0.8.17-6:0.8.17-1, Copyright (c) 2000-2014 the Libav developers
built on Mar 15 2015 17:00:31 with gcc 4.7.2
The ffmpeg program is only provided for script compatibility and will be removed
in a future release. It has been deprecated in the Libav project to allow for
incompatible command line syntax improvements in its replacement called avconv
(see Changelog for details). Please use avconv instead.
Unknown input format: 'concat'
avconv...
avconv -f concat -i list.txt -c copy output
avconv version 0.8.17-6:0.8.17-1, Copyright (c) 2000-2014 the Libav developers
built on Mar 15 2015 17:00:31 with gcc 4.7.2
Unknown input format: 'concat'
When I remove the "-f" and use the filenames directly, it works. I have no idea why. The resulting file also plays as expected.
avconv -i concat:sr_program_2015_03_23_05_44_01.aac\|sr_program_2015_03_23_07_44_58.aac -c copy output.aac
avconv version 0.8.17-6:0.8.17-1, Copyright (c) 2000-2014 the Libav developers
built on Mar 15 2015 17:00:31 with gcc 4.7.2
[aac # 0xcb6cc0] channel element 3.5 is not allocated
[aac # 0xcb4b20] max_analyze_duration reached
[aac # 0xcb4b20] Estimating duration from bitrate, this may be inaccurate
Input #0, aac, from 'concat:sr_program_2015_03_23_05_44_01.aac|sr_program_2015_03_23_07_44_58.aac':
Duration: 01:58:34.29, bitrate: 65 kb/s
Stream #0.0: Audio: aac, 44100 Hz, stereo, s16, 65 kb/s
Output #0, adts, to 'output.aac':
Metadata:
encoder : Lavf53.21.1
Stream #0.0: Audio: aac, 44100 Hz, stereo, 65 kb/s
Stream mapping:
Stream #0:0 -> #0:0 (copy)
Press ctrl-c to stop encoding
size= 57148kB time=7315.03 bitrate= 64.0kbits/s
video:0kB audio:57148kB global headers:0kB muxing overhead 0.000000%
Noticing that the working approach does not use the '-f' option, I tried that again with my first attempt and got a completely different error.
avconv concat -i list.txt -c copy output.aac
avconv version 0.8.17-6:0.8.17-1, Copyright (c) 2000-2014 the Libav developers
built on Mar 15 2015 17:00:31 with gcc 4.7.2
Unable to find a suitable output format for 'concat'
The reason I want to process these 'broken stream' aac files from a file list in a file is because I want to create the list from a script/code and then process it as part of a daily automated process. When the streams have broken, there are numerous files with the same date. When all goes well, there is only one file. It happens every other week or so. I want to automate the fix that I usually do manually. I have already accomplished creating the target file list, ironically, from examples on the same page mentioned above when I became stuck with this odd behavior.
I also want to know what it is I am doing wrong. I see the example I used first everywhere. I have tried this on two different machines running debian but different architectures (arm and x86) and received the same results.
Also, to make sure I had the latest ffmeg, I compiled it on each system using this page... Compile FFmpeg on Ubuntu, Debian, or Mint
Thank you for your time.
You have two versions of ffmpeg installed on your system.
When you enter ffmpeg on the command line the older program gets launched. You can see this in your output:
ffmpeg version 0.8.17-6:0.8.17-1
0.8.17 is an older branch which might not include the concat demuxer.
To make sure you launch the correct version, use the full path to the
ffmpeg you compiled yourself in your home directory.
/home/your-user/bin/ffmpeg -f concat ...
If you got the latest snapshot the version should be:
ffmpeg version 2.6.git

RTMP: Is there such a linux command line tool?

I have looked everywhere to find a linux utility that will allow me to download rtmp streams. Not flv video but MP3 streams. The location of the streams I want to download are in this format.
rtmp://live.site.com/loc/45/std_fc74a6b7f79c70a5f60.mp3
Anyone know of such a command line tool? Or even anything close to what I am asking for?
I do not want full software applications and it would be great if it worked on Linux via Shell or something.
Thanks all
One of the following should do, if you have mplayer or vlc compiled with RTMP access.
mplayer -dumpstream rtmp://live.site.com/loc/45/std_fc74a6b7f79c70a5f60.mp3
This will generate a ./stream.dump.
vlc -I dummy rtmp://live.site.com/loc/45/std_fc74a6b7f79c70a5f60.mp3 \
--sout file/ts:output.mpg vlc://quit
This will generate a ./output.mpg. You'll have to demux it to extract just the audio stream out.
This question is old but this can help to another users with this doubt.
To download directly, without any conversion, there is two options (the author of both programs is the same and the behavior is the same):
RTMPDump. Example: rtmpdump -r "rtmp://host.com/dir/file.flv" -o filename.flv
flvstreamer. Example: flvstreamer -r "rtmp://od.flash.plus.es/ondemand/14314/plus/plustv/PO770632.flv" -o salida.flv
And if you want download and convert the video at same time, the best way is use ffmpeg:
ffmpeg -i rtmp://server/live/streamName -acodec copy -vcodec copy dump.mp4
I think the landscape has changed a bit since the time of some of the previous answers. At least according to the rtmp wikipedia page. It would appear that the rtmp protocol specification is open for public use. To that end you can use 2 tools to accomplish what the original poster was asking, rtmpdump and ffmpeg. Here's what I did to download a rtmp stream that was sending an audio podcast.
step #1 - download the stream
I used the tool rtmpdump to accomplish this. Like so:
% rtmpdump -r rtmp://url/to/some/file.mp3 -o /path/to/file.flv
RTMPDump v2.3
(c) 2010 Andrej Stepanchuk, Howard Chu, The Flvstreamer Team; license: GPL
Connecting ...
INFO: Connected...
Starting download at: 0.000 kB
28358.553 kB / 3561.61 sec
Download complete
step #2 - convert the flv file to mp3
OK, so now you've got a local copy of the stream, file.flv. You can use ffmpeg to interrogate the file further and also to extract just the audio portion.
% ffmpeg -i file.flv
....
[flv # 0x25f6670]max_analyze_duration reached
[flv # 0x25f6670]Estimating duration from bitrate, this may be inaccurate
Input #0, flv, from 'file.flv':
Duration: 00:59:21.61, start: 0.000000, bitrate: 64 kb/s
Stream #0.0: Audio: mp3, 44100 Hz, 1 channels, s16, 64 kb/s
From the above output we can see that the file.flv contains a single stream, just audio, and it's in mp3 format, and it's a single channel. To extract it to a proper mp3 file you can use ffmpeg again:
% ffmpeg -i file.flv -vn -acodec copy file.mp3
....
[flv # 0x22a6670]max_analyze_duration reached
[flv # 0x22a6670]Estimating duration from bitrate, this may be inaccurate
Input #0, flv, from 'file.flv':
Duration: 00:59:21.61, start: 0.000000, bitrate: 64 kb/s
Stream #0.0: Audio: mp3, 44100 Hz, 1 channels, s16, 64 kb/s
Output #0, mp3, to 'file.mp3':
Metadata:
TSSE : Lavf52.64.2
Stream #0.0: Audio: libmp3lame, 44100 Hz, 1 channels, 64 kb/s
Stream mapping:
Stream #0.0 -> #0.0
Press [q] to stop encoding
size= 27826kB time=3561.66 bitrate= 64.0kbits/s
video:0kB audio:27826kB global headers:0kB muxing overhead 0.000116%
The above command will copy the audio stream into a file, file.mp3. You could also have extracted it to a wav file like so:
ffmpeg -i file.flv -vn -acodec pcm_s16le -ar 44100 -ac 2 file.wav
This page was useful in determining how to convert the flv file to other formats.

How to join webcam FLVs

I want my website to join some webcam recordings in FLV files (like this one). This needs to be done on Linux without user input. How do I do this? For simplicity's sake, I'll use the same flv as both inputs in hope of getting a flv that plays the same thing twice in a row.
That should be easy enough, right? There's even a full code example in the ffmpeg FAQ.
Well, pipes seem to be giving me problems (both on my mac running Leopard and on Ubuntu 8.04) so let's keep it simple and use normal files. Also, if I don't specify a rate of 15 fps, the visual part plays extremely fast. The example script thus becomes:
ffmpeg -i input.flv -vn -f u16le -acodec pcm_s16le -ac 2 -ar 44100 \
- > temp.a < /dev/null
ffmpeg -i input.flv -an -f yuv4mpegpipe - > temp.v < /dev/null
cat temp.v temp.v > all.v
cat temp.a temp.a > all.a
ffmpeg -f u16le -acodec pcm_s16le -ac 2 -ar 44100 -i all.a \
-f yuv4mpegpipe -i all.v -sameq -y output.flv
Well, using this will work for the audio, but I only get the video the first time around. This seems to be the case for any flv I throw as input.flv, including the movie teasers that come with red5.
a) Why doesn't the example script work as advertised, in particular why do I not get all the video I'm expecting?
b) Why do I have to specify a framerate while Wimpy player can play the flv at the right speed?
The only way I found to join two flvs was to use mencoder. Problem is, mencoder doesn't seem to join flvs:
mencoder input.flv input.flv -o output.flv -of lavf -oac copy \
-ovc lavc -lavcopts vcodec=flv
I get a Floating point exception...
MEncoder 1.0rc2-4.0.1 (C) 2000-2007 MPlayer Team
CPU: Intel(R) Xeon(R) CPU 5150 # 2.66GHz (Family: 6, Model: 15, Stepping: 6)
CPUflags: Type: 6 MMX: 1 MMX2: 1 3DNow: 0 3DNow2: 0 SSE: 1 SSE2: 1
Compiled for x86 CPU with extensions: MMX MMX2 SSE SSE2
success: format: 0 data: 0x0 - 0x45b2f
libavformat file format detected.
[flv # 0x697160]Unsupported audio codec (6)
[flv # 0x697160]Could not find codec parameters (Audio: 0x0006, 22050 Hz, mono)
[lavf] Video stream found, -vid 0
[lavf] Audio stream found, -aid 1
VIDEO: [FLV1] 240x180 0bpp 1000.000 fps 0.0 kbps ( 0.0 kbyte/s)
[V] filefmt:44 fourcc:0x31564C46 size:240x180 fps:1000.00 ftime:=0.0010
** MUXER_LAVF *****************************************************************
REMEMBER: MEncoder's libavformat muxing is presently broken and can generate
INCORRECT files in the presence of B frames. Moreover, due to bugs MPlayer
will play these INCORRECT files as if nothing were wrong!
*******************************************************************************
OK, exit
Opening video filter: [expand osd=1]
Expand: -1 x -1, -1 ; -1, osd: 1, aspect: 0.000000, round: 1
==========================================================================
Opening video decoder: [ffmpeg] FFmpeg's libavcodec codec family
Selected video codec: [ffflv] vfm: ffmpeg (FFmpeg Flash video)
==========================================================================
audiocodec: framecopy (format=6 chans=1 rate=22050 bits=16 B/s=0 sample-0)
VDec: vo config request - 240 x 180 (preferred colorspace: Planar YV12)
VDec: using Planar YV12 as output csp (no 0)
Movie-Aspect is undefined - no prescaling applied.
videocodec: libavcodec (240x180 fourcc=31564c46 [FLV1])
VIDEO CODEC ID: 22
AUDIO CODEC ID: 10007, TAG: 0
Writing header...
[NULL # 0x67d110]codec not compatible with flv
Floating point exception
c) Is there a way for mencoder to decode and encode flvs correctly?
So the only way I've found so far to join flvs, is to use ffmpeg to go back and forth between flv and avi, and use mencoder to join the avis:
ffmpeg -i input.flv -vcodec rawvideo -acodec pcm_s16le -r 15 file.avi
mencoder -o output.avi -oac copy -ovc copy -noskip file.avi file.avi
ffmpeg -i output.avi output.flv
d) There must be a better way to achieve this... Which one?
e) Because of the problem of the framerate, though, only flvs with constant framerate (like the one I recorded through facebook) will be converted correctly to avis, but this won't work for the flvs I seem to be recording (like this one or this one). Is there a way to do this for these flvs too?
Any help would be very appreciated.
I thought it would be a nice learning exercise to rewrite it in Ruby.
It was.
Six months later and three gems later, here's the released product.
I'll still be working a bit on it, but it works.
You'll encounter a very subtle problem here because most video and audio formats (especially in ordinary containers) use "global headers," meaning at the start of the file they have a single header which specifies compression information (like width, height, etc) for the whole file. Concatting two streams will clearly fail, as it will now have two headers instead of one and the muxer may not like this. Converting to AVI probably is resolving the issue in your case because mencoder has code to concat AVIs--that code properly handles the header issue.
After posting my question on mencoder's mailing list, trying other things, I resorted to write my own tool! I started from flvtool and after some digging in the code and writing about 40 lines of code, it works, with no loss in quality (since there is no transcoding).
I'll release it asap, in the meantime anyone interested can contact me.
dont know if this will actually work but try using this command :
cat yourVideos/*.flv >> big.flv
this will probably damage meta information so after executing that command use "flvtool" (ruby script you can find it with google) to fix it.

Resources