Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Split into equal parts and convert many mp4 videos using ffmpeg

I have a ton of videos I need to convert from mp4 to wmv using ffmpeg and break up each file into 10 minute segments, but I am a total cmd scripting newb (in fact, I am a scripting newb :)

After spending six hours trying to find an answer, I thought I would bring it to you guys.

The code I have is working a little bit, but I need to be able to read data coming from the command line and send it back into the script for evaluation. I am not sure what code ffmpeg will spit out when it is done processing a video file (when the timestamp reaches an end), but this FOR loop just keeps on trying to create new file segments even though the video is over. This is what I saw when it tried to create a new file, so I think it might work to search for this:

frame= 0 fps=0.0 q=0.0 Lsize= 1kB time=00:00:00.00 bitrate=N/A

This is the code I have come up with so far (Don't laugh :)

@echo off
setlocal ENABLEEXTENSIONS
setlocal ENABLEDELAYEDEXPANSION

for %%a in ("*.mp4") do (
set hour=00

for /L %%i IN (1,1,10) do (
:Beginning
    set /a start=%%i-1
        set end=%%i
        if !start! lss 10 set start=!start!0
        if !end! lss 10 set end=!end!0
        ffmpeg -ss !hour!:!start!:00 -i "%%a" -b:v 1500k -vcodec msmpeg4 -acodec wmav2 -t !hour!:!end!:00 "Converted\%%~na-!hour!-!start!-!end!.wmv"
        if end==60 CALL :Increment
    )   
)

:Increment
    set /a !hour!+1
    set %%i=1
    GOTO :Beginning
pause

Based on reading this thread was thinking something like this might go in the code, but not sure what to do with it:

set "dosstring=%*"

echo.!dosstring!|findstr /C:"frame=    0 fps=0.0 q=0.0 Lsize=       1kB time=00:00:00.00 bitrate=N/A" >nul 2>&1

Thanks so much for you help!

like image 558
bobafetta Avatar asked Oct 30 '22 19:10

bobafetta


1 Answers

A more efficient method is to invoke ffmpeg just once per file and use its segmenting feature.

The segments will be numbered sequentially so if you absolutely need to include timestamps in the name we'll also generate a list of the segment's timestamps in CSV format:

tmp000.wmv,0.000000,60.281000
tmp001.wmv,60.281000,120.041000

Then parse it and rename the segments.

@echo off

for %%a in (*.mp4) do (

    ffmpeg -i "%%a" ^
        -f segment -segment_time 10:00 -segment_list tmp.csv -reset_timestamps 1 ^
        -b:v 1500k -vcodec msmpeg4 -acodec wmav2 converted\tmp%%03d.wmv

    setlocal enableDelayedExpansion
    for /f "delims=, tokens=1-3" %%b in (tmp.csv) do (
        set sec=%%c & set sec=!sec:.*=!
        set /a hour="sec / 3600"
        set /a mins1="sec / 60 %% 60" & set mins1=0!mins1!
        set sec=%%d & set sec=!sec:.*=!
        set /a mins2="sec / 60 %% 60" & set mins2=0!mins2!

        ren "converted\%%b" "%%~na-!hour!-!mins1:~-2!-!mins2:~-2!.*"
    )
    endlocal
    del tmp.csv
)
pause

This example won't rename files with ! in the name as I didn't want to overcomplicate the code to work around this case.

like image 179
wOxxOm Avatar answered Nov 09 '22 16:11

wOxxOm