Is it possible to extract SubRip (SRT) subtitles from an MP4 video with ffmpeg? - ffmpeg

I have checked the FFMpeg documentation and many forums and figured out the correct command-line to extract subtitles from an .MP4 video should look like so:
ffmpeg -i video.mp4 -vn -an -codec:s:0 srt out.srt
However, I get the following error, which lends me to question whether this is feasible at all:
Error while opening encoder for output stream #0:0 - maybe incorrect parameters
such as bit_rate, rate, width or height
Using ffmpeg -codecs, I can confirm that ffmpeg should be able to encode subrip subtitles.
Using ffmpeg -i video.mp4, I can see that there is two subtitle tracks embedded in the video :
Input #0, mov,mp4,m4a,3gp,3g2,mj2, from 'video.mp4':
...
Stream #0:0(und): Video: h264 (Constrained Baseline) (avc1 / 0x31637661), yuv420p, 720x572 [SAR 64:45 DAR 256:143], 1341 kb/s, 25 fps, 25 tbr, 90k tbn, 180k tbc
Stream #0:1(eng): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 191 kb/s
Stream #0:2(fra): Audio: aac (mp4a / 0x6134706D), 48000 Hz, stereo, fltp, 191 kb/s
Stream #0:3(eng): Subtitle: dvd_subtitle (mp4s / 0x7334706D)
Stream #0:4(und): Subtitle: mov_text (text / 0x74786574)
EDIT
I have tested with the simplified command-line shown in the comments but I still get the same error. Here is a link to the detailed verbose output from running the command. I have also tried to completely disable metadata and chapters in the resulting output but that still produces the same error.

I enventually figured out why I did not succeed:
The specified command-line would have been perfectly fine if the subtitles from the source video were encoded in a text-based representation. However, as can be seen in the output to the ffmpeg -i command-line, the subtitles are encoded in the "dvd_subtitle" format.
The dvd_subtitle format stores bitmaps for each subtitle in the video. Therefore, there is no way ffmpeg would be able to translate the bitmaps into text.
For this task, one has to resort to an OCR-based software which assists a user with the task of identifying each subtitle as text from its bitmap représentation.
(There is a secondary text-based subtitle in the source video, but I don't know where it came from and is not seen by most popular players. For all intents and purposes, this "mov_text" subtitle seems to be a stub placeholder, probably an artifact of the conversion from the original DVD)

Just FYI, (Can't comment due to rep yet), but extracting SRT from an MP4 will result in a file formatted as MOV_Text not the regular SRT. It will still get added and work but its like changing mp4 to m4v. While it usually works, things don't work the same in the code. Mov_text is horrible for manually adjusting font/size etc etc. Best bet is to download and test an SRT from the web!
This will work, but will result in mov_text coded srt file:
ffmpeg -i in.mp4 out.srt

Try using map option...
if there are too many streams in input files....
Syntax would be:
ffmpeg -i video.mp4 -map 0:4 out.srt
Since there are two subtitle streams in your video, first on 0:3 which is dvdsubtitle so cannot be converted to srt so we will convert second subtitle on 0:4 stream which is mov_text and is soft copy of subtitle so can be easily converted....

Related

Does Webm support cover art?

I am converting MP3 to Webm and the MP3 file includes a video stream for the cover art.
ffprobe filename.mp3
...
Stream #0:0: Audio: mp3, 22050 Hz, stereo, fltp, 64 kb/s
Stream #0:1: Video: mjpeg (Baseline), yuvj444p(pc, bt470bg/unknown/unknown), 300x300, 90k tbr, 90k tbn, 90k tbc (attached pic)
Using ffmpeg with libopus codec to convert the file causes a VP9 video stream that doesn't work well. I noticed:
VLC Player doesn't show the duration and the progress scrubber doesn't move when playing.
Android Media Player doesn't show image for the cover art of the track.
ffprobe filename.webm
...
Input #0, matroska,webm, from 'webm_bad/B01___01_Matthew_____ENGWEBN2DA.webm':
...
Stream #0:0: Video: vp9 (Profile 1), yuv444p(tv, progressive), 300x300, SAR 1:1 DAR 1:1, 1k tbr, 1k tbn, 1k tbc (default)
If I tried to use -vcodec copy option, then I get this error:
[webm # 0x7fdddf028e00] Only VP8 or VP9 or AV1 video and Vorbis or Opus audio and WebVTT subtitles are supported for WebM.
Could not write header for output file #0 (incorrect codec parameters ?): Invalid argument
Error initializing output stream 0:1 --
Does WebM support cover art? If so, how do I transfer the MP3 cover art over using ffmpeg (or other tool)?
No, WebM does not support cover art.
From the FAQ:
The WebM file structure is based on the Matroska media container.
The cover art in a Matroska container is stored in an attachment:
Attachment Elements can be used to store related cover art, [...]
A WebM container does not support attachments:
Attachment
WebM Support
Element Name
Description
Unsupported
Attachments
Contain attached files.
Unsupported
AttachedFile
An attached file.
Unsupported
FileDescription
A human-friendly name for the attached file.
Unsupported
FileName
Filename of the attached file.
Unsupported
FileMimeType
MIME type of the file.
Unsupported
FileData
The data of the file.
Unsupported
FileUID
Unique ID representing the file, as random as possible.
Unsupported
FileReferral
A binary value that a track/codec can refer to when the attachment is needed.
Unsupported
FileUsedStartTime
DivX font extension
Unsupported
FileUsedEndTime
DivX font extension
Maybe you can consider using a different container. Opus audio streams, like the ones in a WebM container, are supported by other containers:
Opus was originally specified for encapsulation in Ogg containers
If you still want to use WebM, an alternative would be to create a video stream with a still image along with an audio stream. The FFmpeg wiki covers that topic in the Slideshow page. Combining that with this answer, which explains how to extract the cover art of an MP3 file, you could do the following:
ffmpeg -i filename.mp3 -an -c:v copy cover.jpeg
ffmpeg -loop 1 -i cover.jpeg -i filename.mp3 -c:v libvpx-vp9 -c:a libopus -b:a 64k -shortest filename.webm
64k is the bitrate that you show in the output of ffprobe.
The encoding might be slow with the second command. The Encode/Youtube page in the FFmpeg wiki shows an example command to create a video with an still image that uses the -framerate 2 option, like this:
ffmpeg -loop 1 -framerate 2 -i cover.jpeg -i filename.mp3 -c:v libvpx-vp9 -c:a libopus -b:a 64k -shortest filename.webm
For some reason I do not know, the output video of that last command cannot be reproduced by my VLC and the player crashes. 6 was the minimum -framerate that did not crash my player, so be careful.

Is there a function to add a title to multiple videos? FFMPEG

I'm getting started with FFMPEG to add a title video to a few dozen videos I have. What would be the proper command to do this?
Use the concat demuxer
There are several methods to join/merge/concatenate one video to another. This method uses the concat demuxer in ffmpeg to join the title video to the main video. Although there are several steps, it has the advantage that it does not re-encode the video you are adding a title to. So the process is quick and the quality is preserved.
Example
See the attributes of the video you want to add a title video to. In this example it is named main.mp4. When making the title video you will need to ensure that it matches the attributes of the video you want to add a title to.
ffmpeg -i main.mp4
...
Stream #0:0(und): Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 988 kb/s, 29.97 fps, 29.97 tbr, 30k tbn, 59.94 tbc (default)
Stream #0:1(eng): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
Generate the title video. Make sure the title video matches the attributes of the main file so it can concatenate properly. This example uses the color and anullsrc source filters to make 5 seconds of black video and silent audio, and the drawtext filter to make text:
ffmpeg -f lavfi -i color=size=1280x720:rate=30000/1001:duration=5:color=black -f lavfi -i anullsrc=sample_rate=44100:channel_layout=stereo -vf "drawtext=text='your title':fontcolor=white:fontsize=48:x=(w-text_w)/2:y=(h-text_h)/2" -c:v libx264 -profile:v main -c:a aac -shortest title.mp4
Make a text file named input.txt. This will be used by the concat demuxer and lists the files that you want to concatenate.
file 'title.mp4'
file 'main.mp4'
Finally, concatenate the title video to the main video with the concat demuxer:
ffmpeg -f concat -i input.txt -c copy output.mp4
Batch mode
ffmpeg does not have a batch mode to automatically do this for a folder of videos. However, it can be done with shell scripting but that is a whole new topic that deserves its own question. See How do you convert an entire directory with ffmpeg? for some examples.

How to process a video to mp4 with ffmpeg for quality and compatibility?

I am beginning to be more serious about video. I am processing my videos with ffmpeg in a fully updated Linux into mp4 to use it in HTML5 directly.
Now, I have old AVI videos that I want to convert to mp4 with ffmpeg for use with HTML5. In particular, I have this one:
http://luis.impa.br/photo/1101_aves_ce/caneleiro-de-chapeu-preto_femea_Quixada-CE-110126-E_05662+7a.avi
(I know, terrible quality... sorry). According to ffprobe:
Duration: 00:01:35.30, start: 0.000000, bitrate: 1284 kb/s
Stream #0:0: Video: mpeg4 (Simple Profile) (DX50 / 0x30355844), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 1144 kb/s, 30 fps, 30 tbr, 30 tbn, 30 tbc
Stream #0:1: Audio: mp3 (U[0][0][0] / 0x0055), 44100 Hz, stereo, s16p, 128 kb/s
That seems perfect: mpeg4 video and mp3 audio. So I tried:
ffmpeg -i input.avi -acodec copy -vcodec copy output.mp4
It generates a file that plays nicely in mplayer, but not in firefox getting an error:
Video format or MIME type not supported.
Chrome plays the audio, but no video is shown... Now, if I do:
ffmpeg -i input.avi output.mp4
firefox works, but the video is reencoded in another one with half the size (half the bitrate). This is what ffprobe says about the reencoded video:
major_brand : isom
minor_version : 512
compatible_brands: isomiso2avc1mp41
encoder : Lavf57.71.100
Duration: 00:01:35.30, start: 0.000000, bitrate: 685 kb/s
Stream #0:0(und): Video: h264 (High) (avc1 / 0x31637661), yuv420p, 640x480 [SAR 1:1 DAR 4:3], 548 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Stream #0:1(und): Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 128 kb/s (default)
I suppose that I am loosing lots of quality (and time processing the video). So, my questions:
Why are browsers not playing my video with the copy codecs ?
Can I work with ffmpeg in this particular file without reencoding? If yes, how?
If I need to reencode, which are "reasonable" parameters to keep close to the original quality? Would something like
ffmpeg -i input.avi -b:v 1024k -bufsize 1024k output.mp4
suffice for this video? This generates a new video with size closer to the original one.
Thanks!
According to ffprobe and if I see it correctly, you have a DivX (5) video file. Do not use it for web!! ;)
mpeg4 (Simple Profile) (DX50 / 0x30355844)
So I don't see any chance to use this video without reencoding. Not if you wish to support firefox.
Use WebM or h264: https://developer.mozilla.org/en-US/docs/Web/HTML/Supported_media_formats
UPDATE
Good settings for reencode depends on your input (bitrate, resolution, fps, kind of material ...), so there is no standard answer.
But you have to specify a codec or ffmpeg choose one depending on your output file extension (so it can be the wrong one).
You can try this:
ffmpeg -i input.avi -c:v libx264 -preset slow -crf 22 -c:a copy output.mkv
Presets and tunes can help to find the best choice: https://trac.ffmpeg.org/wiki/Encode/H.264

Concat mp4 files with a command line tool

I am blocked trying to do something, and I'm ready to make a donation if somebody can help me:
I try to concat http://s.serero.free.fr/rolex.mp4 video and http://s.serero.free.fr/video.mp4 video in one output mp4 file and I tried during a big time without results.
I want to concat http://s.serero.free.fr/rolex.mp4 + http://s.serero.free.fr/video.mp4
or http://s.serero.free.fr/video.mp4 + http://s.serero.free.fr/rolex.mp4.
I tried with ffmpeg command line software and with mp4box command line software, I think that I don't have the good method.
I tried to transform http://s.serero.free.fr/video.mp4 in the same format of http://s.serero.free.fr/rolex.mp4 (and vice versa):
I transformed http://s.serero.free.fr/rolex.mp4 with the same frame rate of http://s.serero.free.fr/video.mp4
I transformed http://s.serero.free.fr/rolex.mp4 with the same video bitrate of http://s.serero.free.fr/video.mp4
I transformed http://s.serero.free.fr/rolex.mp4 with the same video audio bitrate of http://s.serero.free.fr/video.mp4
Can somebody help me?
Explain to me what is wrong in my strategy?
Your input parameters vary, so you have to make them similar before concatenation.
rolex.mp4
Video: h264 (Main) (avc1 / 0x31637661), yuv420p(tv, bt709), 1280x720 [SAR 1:1 DAR 16:9], 835 kb/s, 25 fps, 25 tbr, 90k tbn, 50 tbc (default)
Audio: aac (LC) (mp4a / 0x6134706D), 44100 Hz, stereo, fltp, 125 kb/s (default)
video.mp4
Video: h264 (High) (avc1 / 0x31637661), yuvj420p(pc), 1152x720, 1749 kb/s, 30 fps, 30 tbr, 15360 tbn, 60 tbc (default)
Audio: mp3 (mp4a / 0x6134706D), 44100 Hz, stereo, s16p, 127 kb/s (default)
This example will make video.mp4 more like rolex.mp4 then concat them:
ffmpeg -i rolex.mp4 -i video.mp4 -filter_complex \
"[1:v]pad=1280:720:(ow-iw)/2:0,fps=25,format=yuv420p[v1]; \
[0:v][0:a][v1][1:a]concat=n=2:v=1:a=1[v][a]" \
-map "[v]" -map "[a]" output.mp4
You don't actually need to declare fps or format because, as the concat filter documentation states:
All corresponding streams must have the same parameters in all
segments; the filtering system will automatically select a common
pixel format for video streams, and a common sample format, sample
rate and channel layout for audio streams, but other settings, such as
resolution, must be converted explicitly by the user.
...but doing so will allow you to manually choose the "common" settings instead of relying on the filter automatically doing so and potentially selecting a setting you don't want.
Thanks for LordNeckbeard for his excellent answer, he just let a little mistake on the command, i just want to a little explanation :
If I want to concat video.mp4(1152X720) with rolex.mp4(1280X720), we must understand that "video.mp4" is the main video so the video(s) to concatene must have exactly the same frame size.
So before to do this operation you need to resize rolex.mp4 video with the same size like video.mp4 with ffmpeg :
ffmpeg -i rolex.mp4 -s 1152x720 -c:a copy newrolexsized.mp4
No video.mp4 and newrolexsized.mp4 has the same frame size, and you can use the command (spcifying pad=1152:720 => size of the main video):
ffmpeg -i video.mp4 -i newrolexsized.mp4 -filter_complex "[1:v]pad=1152:720:(ow-iw)/2:0,fps=25,format=yuv420p[v1];[0:v][0:a][v1][1:a]concat=n=2:v=1:a=1[v][a]" -map "[v]" -map "[a]" out.mp4

How to use the information from ffprobe to use with ffmpeg. Is there a shortcut to the syntax?

Want to batch convert a bunch of different video files from cli instead of Rolands old-and-slow-drag-and-drop-one-file-at-a-time-software. I have used ffprobe in OS X Terminal here. This shows us what the software did to the file and I want to do the same. MJPEG AVI I get but the rest, how would my ffmpeg syntax look to achieve this result efter converting?
Example: My ffprobe give me this
Input #0, avi, from 'P10_0001.AVI':
Metadata:
comment :
encoder : Roland Corporation
Duration: 00:03:17.64, start: 0.000000, bitrate: 16694 kb/s
Stream #0:0: Video: mjpeg (MJPG / 0x47504A4D), yuvj422p(pc, bt470bg/unknown/unknown), 640x480, 15285 kb/s, 25 fps, 25 tbr, 25 tbn, 25 tbc
Stream #0:1: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 44100 Hz, 2 channels, s16, 1411 kb/s
What would the ffmpeg syntax look like to do this with a new file.
I've been trying some simple ones but those are not accepted by the machine (Edirol p-10) and I hope someone can point me in the right direction. :)
Edit:
OK. The syntax I want to do is involving 3 files.
File that has the correct codec and everything to work with the machine. P10_0001.AVI
A file that does not have the correct format (codec etc.) softvision.mpg
A new file just as file 2 but with the codec of file number 1. P10_0002.AVI
ffmpeg -i gradomat.mpg -framerate 25 -vf scale=640:480 -vcodec mjpeg -pix_fmt yuvj422p -b:v 15285k -b:a 1411k -acodec pcm_s16le -ar 44100 -ac 2 -metadata encoder="Roland Corporation" P10_000X.AVI
Think this solved it temporarily but the problem is that I have to write that my self, it would have been better if ffprobe gave me that syntax instead.
This is also a solution, but in python.
https://github.com/cskonopka/rolandp10fp

Resources