How to use ffmpeg to encode files from folder1 to folder2 keeping output files in same output folder structure.
I couldn't fit all of above into Title:
Despite valiant efforts I have come up empty. The files are always saved to the output folders root, not into the output folders subfolders similar to the source subfolders layout.
There may be a completely different and better way than the 2 trys below, hopefully.
I hope someone can help with this. Thanks.
The XTREE command initially creates the correct empty folder structure in the output folder.
The ffmpeg command syntax is an arbitrary scaling, but can be anything else.
I am including here my own effort ("Version-2.bat") and one posted on inet ("reconvert.bat") but both fail.
Reconvert ...
REM -----------------------------------------------------------------------------
REM user dirkgently on stackoverflow. https://stackoverflow.com/users/66692/dirkgently
REM https://mostlybuggy.wordpress.com/2012/09/25/windows-batch-file-how-to-copy-and-conver...y-with-ffmpeg/
@echo off
mode CON:cols=228 lines=30
color 0A
SETLOCAL EnableDelayedExpansion
REM keep a counter for files converted
set /A nfile=0
REM do not copy empty folders or any files
@echo Copying directory structure from %0 to %1 ...
xcopy /T %1 %2
REM walk directory structure and convert each file in quiet mode
for /R %1 %%v in (*.mp4, *.aac, *.flv, *.m4a, *.mp3) do (
echo converting "%%~nxv" ...
ffmpeg -v quiet -i "%%v" "%2\%%~nv.mp3"
set /A nfile+=1
)
echo Done! Converted %nfile% file(s)
REM To use it simply fire up a command prompt and type in:
REM rconvert G:\Music Z:\Fun\
REM Note that the trailing ‘\’ is necessary to indicate that Fun is a directory and not a file.
REM PS: I threw in a counter too just so you know how many files you’ve copied
pause
exit
REM -----------------------------------------------------------------------------
REM My try ... Version-2
REM -----------------------------------------------------------------------------
@echo off
SETLOCAL EnableDelayedExpansion
MD #02-Output
XCOPY /T /E ".\#01-Source\" ".\#02-Output\"
FOR /R ".\#01-Source\" %%G in (*.mov, *.mp4, *.mp3) do (
ffmpeg -y -i "%%G" -c:v h264_nvenc -pix_fmt yuv420p -cq 23 -vf scale=-2:1080 -bf:v 0 -b:v 0 -maxrate 100 -g 25 -c:a copy ".\#02-Output\%%~nxG"
)
REM pause
exit
+ Reply to Thread
Results 1 to 20 of 20
-
Last edited by JN-; 16th May 2025 at 08:31.
-
The problem in your batch file is that in:
Code:".\#02-Output\%%~nxG"
returns only the FILENAME (and the extension) without any path, so every file processed is stored in "\#02-Output\". -
Yes, I suspected that was the issue, thanks for confirming.
Any idea on how to overcome "?
I’ll try just removing .\#02-Output\ and see, thought I think that I had already done that. ill be back.Last edited by JN-; 16th May 2025 at 10:22.
-
This obviously doesn't work either. Version-2.bat
MD #02-Output
XCOPY /T /E ".\#01-Source\" ".\#02-Output\"
FOR /R ".\#01-Source\" %%G in (*.mov, *.mp4, *.mp3) do (
REM ffmpeg -y -i "%%G" -c:v h264_nvenc -pix_fmt yuv420p -cq 23 -vf scale=-2:1080 -bf:v 0 -b:v 0 -maxrate 100 -g 25 -c:a copy ".\#02-Output\%%~nxG"
ffmpeg -y -i "%%G" -c:v h264_nvenc -pix_fmt yuv420p -cq 23 -vf scale=-2:1080 -bf:v 0 -b:v 0 -maxrate 100 -g 25 -c:a copy "%%~nxG"
)
I need to give output the full subdirectories paths ?Last edited by JN-; 16th May 2025 at 10:25.
-
This has been VERY difficult, I had to think a lot and then to study a lot that damn BATCH mess.. and, finally, to experiment a lot. I was very close to give up more than one time.
It's a sort of trick and workaround, playing with all that messy stuff in CMD .. but.. I think it should work.
You need to put the batch file in a folder with an IN Folder with all the files to process (even with subfolders).
Code:@echo off SETLOCAL EnableDelayedExpansion REM Name of the Folder with Files to be processed SET inputdir=IN REM Name of the Folder where the Output should go SET outputdir=OUT MD "%outputdir%" XCOPY /T /E "%inputdir%" "%outputdir%" FOR /R "%inputdir%" %%G in (*.mov, *.mp4, *.mp3) do ( call :Parse %%G ) pause exit :Parse set input=%* set cut=%~dp0 set cut=%cut%%inputdir% call set output=%%input:%cut%=%% set fulloutput=%outputdir%%output% ffmpeg -y -i "%input%" -c:v h264_nvenc -pix_fmt yuv420p -cq 23 -vf scale=-2:1080 -bf:v 0 -b:v 0 -maxrate 100 -g 25 -c:a copy "%fulloutput%" )
Last edited by krykmoon; 16th May 2025 at 12:19.
-
AOK. Thanks for all of that. I'll give it a try and get back.
I spent most of yesterday and up to past 3 in the morning without a solution. So I appreciate that it's difficult. -
-
OK. No joy yet.
I created a folder named "IN" only and put files in root of "IN" plus subfolders with files in them also. So a proper subfolder structure with a few files.
Running script it produced an output folder "OUT" with correct subfolder structure but only processed a single file into the root of OUT folder.
There is an mp3 + mov file in the root. It's as if the script stopped after the 1st. file being processed ?
@echo off
mode CON:cols=228 lines=60
color 0A
SETLOCAL EnableDelayedExpansion
REM Name of the Folder with Files to be processed
SET inputdir=IN
REM Name of the Folder where the Output should go
SET outputdir=OUT
MD "%outputdir%"
XCOPY /T /E "%inputdir%" "%outputdir%"
FOR /R "%inputdir%" %%G in (*.mov, *.mp4, *.mp3) do ( call :Parse %%G )
REM pause
REM exit
:Parse
set input=%*
set cut=%~dp0
set cut=%cut%%inputdir%
call set output=%%input:%cut%=%%
set fulloutput=%outputdir%%output%
ffmpeg -y -i "%input%" -c:v h264_nvenc -pix_fmt yuv420p -cq 23 -vf scale=-2:1080 -bf:v 0 -b:v 0 -maxrate 100 -g 25 -c:a copy "%fulloutput%"
)
pause
exit -
NO Joy. Script only processed a single mov file into root of "OUT" folder.
It's as if processing stopped after processing a single file.
The IN folder has a subfolder structure with files in them and 2 in the root, an mp3 and mov file.
Only the mov file was processed.
I used this below and only created the IN folder with subfolders etc.
--------------------------------------------------------------------------
@echo off
mode CON:cols=228 lines=60
color 0A
SETLOCAL EnableDelayedExpansion
REM Name of the Folder with Files to be processed
SET inputdir=IN
REM Name of the Folder where the Output should go
SET outputdir=OUT
MD "%outputdir%"
XCOPY /T /E "%inputdir%" "%outputdir%"
FOR /R "%inputdir%" %%G in (*.mov, *.mp4, *.mp3) do ( call :Parse %%G )
REM pause
REM exit
:Parse
set input=%*
set cut=%~dp0
set cut=%cut%%inputdir%
call set output=%%input:%cut%=%%
set fulloutput=%outputdir%%output%
ffmpeg -y -i "%input%" -c:v h264_nvenc -pix_fmt yuv420p -cq 23 -vf scale=-2:1080 -bf:v 0 -b:v 0 -maxrate 100 -g 25 -c:a copy "%fulloutput%"
)
pause
exit -
I posted twice because I thought the 1st. post was lost.
I REMmed out the 1st. pause and exit because never used.Last edited by JN-; 16th May 2025 at 13:11.
-
This works. Truly spectacular.
Many many thanks.
Brilliant !!!
@echo off
mode CON:cols=228 lines=60
color 0A
SETLOCAL EnableDelayedExpansion
REM Name of the Folder with Files to be processed
SET inputdir=IN
REM Name of the Folder where the Output should go
SET outputdir=OUT
MD "%outputdir%"
XCOPY /T /E "%inputdir%" "%outputdir%"
FOR /R "%inputdir%" %%G in (*.mov, *.mp4, *.mp3) do ( call :Parse %%G )
pause
exit
)
:Parse
set input=%*
set cut=%~dp0
set cut=%cut%%inputdir%
call set output=%%input:%cut%=%%
set fulloutput=%outputdir%%output%
ffmpeg -y -i "%input%" -c:v h264_nvenc -pix_fmt yuv420p -cq 23 -vf scale=-2:1080 -bf:v 0 -b:v 0 -maxrate 100 -g 25 -c:a copy "%fulloutput%"
EXIT /BLast edited by JN-; 16th May 2025 at 14:08.
-
Is that correct? Krykmoon.
I have no idea how you worked your magic.
Are the ) ( brackets still correctly placed.
FOR /R "%inputdir%" %%G in (*.mov, *.mp4, *.mp3) do ( call :Parse %%G )
pause
exit
) Should this stay or go, thanks. -
Me neither. xD
The fact is that I tend to become obsessed by this kind of challenges. xD
The most difficult part has been to figure out how to retrieve the relative path starting from the absolute path of each input file (since there were also nested subfolders to take into account it wasn't an easy task, due to the limitations of the CMD environment )
That was the very clever part. -
Truly.
I spent a good bit of time googling it beforehand then hacking away at it for hours to no avail.
There wasn't much I could find on inet so I believe you have cracked it. Really well done.
I can do stuff up to a point but that's beyond me. Thanks again, terrific. -
-
Mistakes and retries are the name of the game. Ive spent a bit of time integrating it into my batch file (make proxies) this evening and more mistakes, but tiredness mainly. I should finish all by tomorrow.
I really appreciate you doing that as I wasn’t sure it could be done. -
If you are into automitizing encoding and just starting , choose Python instead of windows batch, I wasted 5 years with hacky and limited windows batch. Quick and dirty, yes, it is good, but soon it will not be enough
Example of encoding source directory structure into a destination structure as you wanted , where encoding shows a progress bar, one of many examples:
Code:from pathlib import Path import shutil from tqdm import tqdm import shlex import re import subprocess source_directory = "source_folder" destination_directory = "destination_directory" FFMPEG_SETTINGS = '-y -i "{source}" -c:v h264_nvenc -pix_fmt yuv420p -cq 23 -vf scale=-2:1080 -bf:v 0 -b:v 0 -maxrate 100 -g 25 -c:a copy "{output}"' EXTENSIONS = [".mov", ".mp4", ".mp3"] FFMPEG = shutil.which("ffmpeg") # looks for ffmpeg in PATH or current dir FFMPEG = Path(FFMPEG).resolve().as_posix() # absolute path FFPROBE = shutil.which("ffprobe") FFPROBE = Path(FFPROBE).resolve().as_posix() source_directory = Path(source_directory) destination_directory = Path(destination_directory) destination_directory.mkdir(parents=True, exist_ok=True) def encode(command): print(command) cmd = shlex.split(command) process = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, text=True) total_duration = get_video_duration(cmd[cmd.index('-i') + 1]) progress_bar = tqdm(total=total_duration, unit='s', desc='Encoding', ncols=80) while True: output = process.stderr.readline() if output == '' and process.poll() is not None: break if output: match = re.search(r'time=(\d{2}:\d{2}:\d{2}\.\d{2})', output) if match: current_time = match.group(1) seconds = time_to_seconds(current_time) progress_bar.update(seconds - progress_bar.n) progress_bar.close() return process.wait() def get_video_duration(video_path): command = [FFPROBE, '-v', 'error', '-show_entries', 'format=duration', '-of', 'default=noprint_wrappers=1:nokey=1', video_path] result = subprocess.run(command, capture_output=True, text=True) return float(result.stdout) def time_to_seconds(time_str): hours, minutes, seconds = map(float, time_str.split(':')) return hours * 3600 + minutes * 60 + seconds if __name__ == '__main__': for source in source_directory.rglob("*"): relative_path = source.relative_to(source_directory) if source.is_dir(): (destination_directory / relative_path).mkdir(exist_ok=True) else: if source.suffix not in EXTENSIONS: continue source_absolute_path = source.resolve().as_posix() dest_absolute_path = (destination_directory / relative_path).resolve().as_posix() settings = FFMPEG_SETTINGS.format(source=source_absolute_path, output=dest_absolute_path) command = f'"{FFMPEG}" {settings}' encode(command)
Last edited by _Al_; 18th May 2025 at 00:23.
-
“and just starting”
Just ending would be closer to reality. Thanks for code and going to the trouble.
My hobbyist interest of photo/video means I sometimes come here for solution.
I climbed a small hill, batch files, Quickbasic, Delphi 2 - 5 then had no further use. Retired now so I occasionally make up a simple ffmpeg based util to complement my interest in Vegas Pro editing.
I know I could use Handbrake but enjoy rolling my own occasionally.
I came across this VP thread recently and so decided to make up a simple external to VP util to create proxy files.
https://www.vegascreativesoftware.info/us/forum/correct-workflow-to-use-video-proxy-ge...fmpeg--142440/
A lot of the time it’s a case of re-inventing the wheel but given the rate the little grey ones are escaping out the door, I could be doing worse.
I'm also quite lazy so batch files are sufficient for my small needs.Last edited by JN-; 18th May 2025 at 09:11.
Similar Threads
-
FFMPEG deinterlace before SD h264 encode in one batch possible ?
By Gwar in forum Video ConversionReplies: 10Last Post: 30th Oct 2022, 18:51 -
Cutting away sections from a video using ffmpeg without re-encode
By BosseB in forum EditingReplies: 33Last Post: 24th Aug 2022, 14:32 -
need to efficent encode this .MXF from Canon XF300 to .MP4 with FFmpeg
By marcorocchini in forum Newbie / General discussionsReplies: 4Last Post: 15th Mar 2022, 16:13 -
FFMPEG encode keep first track audio
By iKron in forum Newbie / General discussionsReplies: 1Last Post: 31st Dec 2021, 11:28 -
how to force ffmpeg to encode mpeg2 interlaced ?
By hydra3333 in forum Video ConversionReplies: 19Last Post: 25th Jun 2021, 07:22