I need to cut MP4 videos. A part at the beginning and a part at the end in a batch fashion
Asked Answered
H

5

5

I have several training videos. All .MP4s.

I want to remove 3.5 seconds from the beginning and 4.5 seconds from the end of the entire folder of them...

I know of ffmpeg and ffprobe - but my knowledge and mastery of them both is limited.

Can someone provide a script for this, or, at least a program that will make this easy for me? I keep searching and I reach dead-ends everytime or scripts that do not work.

I am also open to using Linux/Windows but not mac.

edit: First part completed. Will keep on studying this command further in order to learn batch; Here's the easy part, how to batch trim an entire folder of MP4s:

for %%a in ("*.mp4") do ffmpeg -i "%%a" -ss 00:00:03.5 -vcodec copy -acodec copy "newfiles\%%~na.mp4"

pause
Heteropterous answered 6/8, 2015 at 17:55 Comment(3)
May I encourage you to show what you have tried? We ask people not to request fully-formed solutions here, but to demonstrate an honest attempt - including thorough web searching and getting stuck - and then reaching out when they've gone through that process.Pelt
This looks like a good resource - maybe there is a batch mode in one of those utilities?Pelt
This is about [tags:batch-processing] rather than [tags:batch-file], right? please edit the question and adapt the tags accordingly... thanks!Slumber
H
8

I kindly thank everyone here for encouraging me to keep searching, I found a solution that is perfect. Here it is. I am afraid the examples given even in the comments elude me but I will still try to read up and educate myself on how those commands work. Thanks again. Replace 8.25 (end trim) and 4.25 (beginning trim) and change the values until you are satisfied with the outputs.

@Echo Off
SetLocal
Set "ext=mp4"
Set "opts=-v quiet"
Set "opts=%opts% -print_format "compact=print_section=0:nokey=1:escape=csv""
Set "opts=%opts% -show_entries "format=duration""
If Exist *.%ext% (If Not Exist "Trimmed\" MD Trimmed)
For %%a In (*.%ext%) Do Call :Sub "%%~a"
Exit/B

:Sub
For /f "Tokens=1* Delims=." %%a In (
    'FFProbe %opts% %1') Do (Set/A "ws=%%a-8.25" & Set "ps=%%b")
rem If %ws% Lss 20 GoTo :EOF
Set/A hh=ws/(60*60), lo=ws%%(60*60), mm=lo/60, ss=lo%%60
If %hh% Lss 10 Set hh=0%hh%
If %mm% Lss 10 Set mm=0%mm%
If %ss% Lss 10 Set ss=0%ss%
FFMpeg -i %1 -ss 00:00:04.2500 -to %hh%:%mm%:%ss%.%ps:~,3% -c:v copy -c:a copy "Trimmed\%~1"
Heteropterous answered 10/8, 2015 at 16:15 Comment(1)
The first 5 seconds are frozen/glitched after cropping, however. Tested on multiple video players. Any way to fix this?Lamonica
C
2

Eric Lalonde script was good enough, thank you!

For those who can't or don't like installing ffmpeg, I added ffmpeg path variable. In my scenario I am cutting the 14 seconds from the beginning and 9 seconds at the end.

@Echo Off
SetLocal
Set "ext=mp4"
Set "opts=-v quiet"
Set "opts=%opts% -print_format "compact=print_section=0:nokey=1:escape=csv""
Set "opts=%opts% -show_entries "format=duration""
Set ffmpeg=C:\Users\user\Downloads\ffmpeg-20180102-57d0c24-win64-static\bin\
If Exist *.%ext% (If Not Exist "Trimmed\" MD Trimmed)
For %%a In (*.%ext%) Do Call :Sub "%%~a"
Exit/B

:Sub
For /f "Tokens=1* Delims=." %%a In (
    '%ffmpeg%\ffprobe %opts% %1') Do (Set/A "ws=%%a-9.00" & Set "ps=%%b")
Set/A hh=ws/(60*60), lo=ws%%(60*60), mm=lo/60, ss=lo%%60
If %hh% Lss 10 Set hh=0%hh%
If %mm% Lss 10 Set mm=0%mm%
If %ss% Lss 10 Set ss=0%ss%
%ffmpeg%\ffmpeg -i %1 -ss 00:00:14.000 -to %hh%:%mm%:%ss%.%ps,~3% -c:v copy -c:a copy "Trimmed\%~1"
Circlet answered 4/1, 2018 at 9:4 Comment(0)
C
1

a small enchantment for op answer (i cant reply under his comment because of low points): last line make it this way instead:

FFMpeg -ss 00:00:04.2500 -to %hh%:%mm%:%ss%.%ps:~,3% -i %1 -c:v copy -c:a copy -avoid_negative_ts make_zero "Trimmed\%~1"

this way it cut on key frame to avoid out of sync audio if you are playing the video on old tv

Cob answered 10/12, 2019 at 14:55 Comment(0)
C
0

Responding to Erkko's answer.

Set ffmpeg=C:\Users\user\Downloads\ffmpeg-20180102-57d0c24-win64-static\bin\

I used,

Set ffmpeg="C:\Program Files (x86)\K-Lite Codec Pack\Tools"

and for some reason it won't work.

I want to cut 10 seconds from the start and 30 seconds from the end.

'%ffmpeg%\ffprobe %opts% %1') Do (Set/A "ws=%%a-30.00" & Set "ps=%%b")

%ffmpeg%\ffmpeg -i %1 -ss 00:00:10.000 -to %hh%:%mm%:%ss%.%ps:~,3% -c:v copy -c:a copy "Trimmed2\%~1"

resulting in 10 seconds at the start and 20 seconds at the end. I had to change 30 to 40

'%ffmpeg%\ffprobe %opts% %1') Do (Set/A "ws=%%a-40.00" & Set "ps=%%b")

to enable 30 seconds cut at the end. Is this how the batch intend to work or is there an error?

Cholecalciferol answered 26/1, 2020 at 15:0 Comment(0)
A
-4

I solved it. I don't mind helping you, but I'm not going to provide the full solution. I will, however, give you hints with the trickiest parts. I'll leave it up to you to fill in the blanks.

ffmpeg will let you do what you want. The -ss switch specifies the start position. -t specifies duration. Unfortunately, there's no switch or program substitution variable that'll internally perform the needed math on the video length to trim-right. You'll have to compute that via scripting.

First you'll need the total length of the unmodified video:

for /f "tokens=2" %%x in (
    '2^>^&1 ffmpeg -i "%%~fI" ^| find /i "duration"'
) do set "length=%%x"

To calculate the value for the -t switch, you can invoke PowerShell to determine newLength = totalLength - (leftTrim + rightTrim). Here's the secret sauce:

powershell "'{0}' -f ([timespan]'%length:,=%').add([timespan]::fromseconds(-(%trim-left% + %trim-right%)))"

Once you get your target length calculated, plug it into ffmpeg like this:

ffmpeg -i "%%~fI" -ss %trim-left% -t %target_length% -c:v copy -c:a copy "%destination-dir%\%%~nxI"
Aeneid answered 6/8, 2015 at 19:21 Comment(3)
Going to have to get into extensive Batch programming learning mode for a while before I understand these commands. I understand a little...but this is the objective, to learn. I will need this skill set later. I will post what I tried later today, or maybe even compare what has been offered as hints to what I found earlier to see if I can understand and adapt the code to make it work.Heteropterous
ffmpeg -i "filename" will output a bunch of information about the file to the stderr stream. That's why 2>&1 is needed, to redirect stderr to stdout. But in a for /f loop, you have to escape pipes and redirections with a caret -- hence, 2^>^&1. The find command filters the output of the ffmpeg command and outputs only lines that match "duration" with a case-insensitive match. The for /f loop takes the second token (the second word) and assigns it to %%x temporarily. You can then more persistently set "length=%%x". There's a lot going on there, but hopefully it makes sense.Aeneid
Here's another tip: to capture the output of another command to a variable, use a for /f loop like I've done in the first code block. So to capture the output of the powershell command, enclose it in a for /f loop. Do for /? in a cmd console for more information. Because the powershell command includes single quotes as part of the command, you should use the "usebackq" switch with that particular for /f.Aeneid

© 2022 - 2024 — McMap. All rights reserved.