Пакетный скрипт для автоматического преобразования файлов WAV в MP3 путем обхода подкаталогов

РЕДАКТИРОВАТЬ 1

ШАГ 1: Телефонные разговоры записываются в формате .WAV в определенную папку и подпапки (созданные АВТОМАТИЧЕСКИ программой записи голоса в текущем формате даты, т. е. 20121119 (ГГГГММДД) . Это соглашение об именах нельзя изменить. Подпапки с текущей датой автоматически создаются на Диске D в папке с именем RECFILED. Например, если записи предназначены для сегодня файлы будут храниться в подпапке 20121119. Вчерашние файлы хранились в 20121118.

ШАГ 2: В конце дня эти файлы *.WAV необходимо преобразовать в формат *.MP3 и загрузить на Amazon S3. В настоящее время этот процесс является ручным. Так как существует много файлов WAV, поэтому я использую SOX для пакетного преобразования WAV в MP3. Для этой цели я создал пакетный файл (объясненный в моем исходном вопросе), чтобы этот процесс преобразования можно было автоматизировать. Этот пакетный файл преобразует WAV в MP3 и сохраняет файлы MP3 в той же папке, что и файлы WAV. Для этого мне нужно скопировать пакетный файл в папку и запустить его. Он конвертирует файлы и сохраняет их в той же папке.

ШАГ 3: После преобразования файлов. Затем на Amazon S3 в определенной корзине я должен создать новую папку с текущей датой, чтобы все эти MP3 можно было хранить там. НО формат даты здесь ДД.ММ.ГГГГ. Иерархия папок: \BucketName\Voice\201211\19.11.2012\*.MP3 (на сегодня), \BucketName\Voice\201211\20.11.2012\*.MP3 (на завтра) ) и так далее.

Теперь проблема в следующем:

  1. Перейдите к последней папке (загляните в d:\RecFileD\ГГГГММДД) и посмотрите, есть ли в папке файлы WAV. Если да, преобразуйте эти файлы в MP3 и сохраните их в папке с именем ДД.ММ.ГГГГ на локальном сервере в любом определенном месте. (сегодняшняя дата, но в другом формате).

  2. Однажды папка создается (с соглашением об именах ДД.ММ.ГГГГ. Те же самые папки должны быть загружены на S3 в определенном месяце (т. пойдет в папку 201212 и так далее.

  3. Проблема здесь в том, что на локальном сервере соглашение об именах - ГГГГММДД (без пробелов, точек или запятых), а на S3 соглашение об именах - ДД.ММ.ГГГГ (с точками).

ИСХОДНЫЙ ВОПРОС

Пожалуйста, помогите мне написать пакетный файл, чтобы я мог автоматизировать процесс преобразования файлов WAV в MP3, а затем загружать их непосредственно на Amazon S3 в определенные папки. Сейчас это ручной процесс.

На самом деле, у нас есть небольшой колл-центр, и все голосовые вызовы записываются и сохраняются на сервере на диске D: в папке с именем RecFileD и в подпапках, названных с текущей датой (например, 20121117, 20121116 и т. д.). По умолчанию файлы сохраняются в формате WAV. Мне нужно преобразовать файлы в MP3, прежде чем загружать их на Amazon S3 для хранения.

Требование состоит в том, что мне нужно ежедневно загружать файлы MP3 на S3 в определенное время в конце дня. Проблема заключается в том, как перейти к последней папке (папке с текущей датой) и преобразовать файлы. На локальном сервере голосовые файлы сохраняются в d:\RecFileD\20121117\*.wav, а на Amazon S3 файлы загружаются в папки:

  • \BucketName\Voice\201211\17.11.2012\*.mp3 (это ноябрь месяц);

  • \bucketName\Voice\201212\01.12.2012\*.mp3 (это будет декабрьский месяц) (31 папка за все дни).

Чтобы автоматизировать преобразование, я создал приведенный ниже пакетный файл. Этот файл использует приложение SOX для преобразования файлов WAV в MP3 в текущей папке.

@echo off
call :treeprocess
goto :eof

:treeprocess
for %%f in (*.wav) do 
(
  sox %%~nf.WAV %%~nf.mp3
  sox %%~nf.WAV %%~nf-short.mp3 trim 0:30 1:00
)

for /D %%d in (*) do 
(
  cd %%d
  call :treeprocess
  cd ..
)
exit /b

Чтобы автоматизировать загрузку файлов на S3, я бы использовал инструмент командной строки S3.

Вкратце, необходимы следующие шаги:

  1. Перейдите только к папке текущей даты (20121115, 20121116, 20121117 и т. д.) на локальном сервере и конвертируйте файлы WAV в MP3 (используя приведенный выше скрипт).

  2. Переместите эти файлы MP3 в отдельную папку, созданную автоматически, с именем 17.11.2012 (на текущую дату).

  3. Загрузите папку в Amazon S3 в определенное место. то есть \bucketname\voice\201211\17.11.2012.


person N_D    schedule 17.11.2012    source источник
comment
какая у тебя проблема?   -  person PA.    schedule 17.11.2012
comment
Ваш вопрос кажется довольно сложным на данный момент. Как правило, предпочтительнее, когда вопрос касается одной конкретной проблемы. Таким образом, легче сделать ответ ясным и универсальным, на благо многих людей, которые могут позже столкнуться с вопросом. И я думаю, что можно разделить ваш вопрос на два или три более конкретных вопроса. Например, как перемещаться по каталогам в пакетных файлах? Как отформатировать текущую дату как «...» в пакетных файлах? и т. д. Обратите внимание, что на некоторые из этих конкретных вопросов, возможно, уже были даны ответы. Поэтому, прежде чем спрашивать, подумайте о поиске на этом сайте.   -  person Andriy M    schedule 17.11.2012
comment
Вы в основном даете описание того, что должно делать ваше программное обеспечение, и просите кого-нибудь рассказать вам, как это сделать ... Извините, но я думаю, что это не то, о чем SO.   -  person MartinStettner    schedule 17.11.2012
comment
Вы приводите пример пути к исходным файлам .wav. Вы описываете некоторые соглашения об именах для сгенерированных файлов .mp3, как локальных, так и удаленных. Приведите конкретный пример пути .mp3 (полный локальный путь и удаленный путь на S3). Также, пожалуйста, покажите, какую команду S3 вы используете, с примером ее использования. После того, как файлы загружены, вы сохраняете локальную копию (я думаю, что вам следует, если это возможно). Как узнать, обработана ли дата? Что произойдет, если обработка будет пропущена или не удалась в один прекрасный день? Как бы вы заметили, восстановили и обработали пропущенный день?   -  person jimhark    schedule 19.11.2012
comment
В мое второе решение для перехода к последней папке добавлен «последний» фильтр.   -  person jimhark    schedule 19.11.2012
comment
В мое решение добавлен текст, описывающий, как генерируются пути назначения. Ранее я описывал только разделение имени исходного каталога.   -  person jimhark    schedule 19.11.2012
comment
У вас есть работающее решение?   -  person jimhark    schedule 24.11.2012


Ответы (2)


Ух ты! Этот звук намного сложнее, чем есть на самом деле!

@echo off
rem Create folder names from current date, MM/DD/YYYY locale format is assumed
for /F "tokens=1-3 delims=/" %%a in ("%date%") do (
   set YYYYMMDD=%%c%%a%%b
   set YYYYMM=%%c%%a
   set DD.MM.YYYY=%%b.%%a.%%c
)
rem Enter into target folder
cd /D D:\RecFileD\%YYYYMMDD%
rem Convert WAV files to MP3 using SOX
for %%f in (*.wav) do (
   sox %%~nf.WAV %%~nf.mp3
   sox %%~nf.WAV %%~nf-short.mp3 trim 0:30 1:00
)
rem Move MP3 files to brother folder
md ..\%DD.MM.YYYY%
move *.mp3 ..\%DD.MM.YYYY%
rem Upload the folder to Amazon S3
echo S3COPY from ..\%DD.MM.YYYY% to \bucketname\voice\%YYYYMM%\%DD.MM.YYYY%

Я предлагаю вам быть максимально лаконичным при описании вашей проблемы, но не забывайте ни о каких деталях. Например, в вашем (длинном) описании локальная папка с именем 17.11.2012 недостаточно объяснена!

Я надеюсь, это то, что вы хотели...

Антонио

person Aacini    schedule 17.11.2012

То, что у вас есть, довольно хорошо, вы довольно близки.

Среда, которую я тестировал, требовала do (, чтобы открывающая скобка находилась в той же строке, что и do. Ваше форматирование с новой строкой в ​​середине может вызывать проблемы.

Чего вам совершенно не хватает, так это разбора имени каталога, который, как ожидается, будет ГГГГММДД. Вы можете сделать это с помощью:

set dirname=%%d

set year=%dirname:~0,4%
set month=%dirname:~4,2%
set day=%dirname:~6,2%

Как только вы это сделаете, легко создать имена файлов и пути на основе ГГГГ, ММ, ДД:

set s3path=!file_year!!file_month!\!file_day!.!file_month!.!file_year!

будет генерировать путь вида ГГГГММ\ДД.ММ.ГГГГ.

Вы можете получить «последний» каталог, используя:

for /f "tokens=1" %%a IN ('dir /b /a:d /o:n ????????') do (
  set dirset=%%a
)

Примечание: это реализовано только во втором решении. Давайте разберем это:

dir /b /a:d /o:n ????????

Создает каталог в «голом» формате (просто список совпадающих файлов, по одному в строке), с каталогом атрибутов (только список каталогов), упорядочивает по имени (это значение по умолчанию в NTFS, но не в FAT, поэтому лучше указать порядок сортировки ), соответствующий ??????????, любые 8 символов (поскольку ожидается, что каталоги будут называться в формате ГГГГММДД, поэтому всегда 8 символов). Это возвращает упорядоченный список из 8-символьных имен каталогов.

for /f "tokens=1" %%a IN ('command') do echo %%a

Выполняет command и анализирует результаты построчно. Здесь будет отображен первый токен каждого результата.

for /f "tokens=1" %%a IN ('dir /b /a:d /o:n ????????') do (
  set dirset=%%a
)

Собираем все вместе и видим, что dirset будет установлено для каждого подходящего имени каталога. Но после завершения цикла for для него будет установлено последнее значение или «последний» каталог.

В приведенном ниже коде я установил dirname отдельно, чтобы избежать проблем с правилами раскрытия переменных. В качестве альтернативы вы должны иметь возможность использовать:

setlocal enableextensions enabledelayedexpansion 

set dirname=%%d
set year=!dirname:~0,4!

Ваша задача, как сказано, не требует рекурсии. Мой код просто повторяет каждый каталог, а затем повторяет каждый файл. Если макет файла менее структурирован, чем вы указываете, может потребоваться рекурсия.

Вы не указали, какой инструмент командной строки Windows S3 вы используете, поэтому я повторяю *S3COPY* с локальным полным и частичным путем. Вы должны быть в состоянии заменить это своей командой копирования.

Вам нужно будет запустить это из d:\RecFileD или вы можете добавить это вверху bat-файла:

d:
cd \RecFileD

Вам, вероятно, потребуется изменить s3root на фактический корневой каталог вашей локальной копии S3. Вместо того, чтобы перемещать файлы, sox создает их в правильном месте.

Я установил переменные года, месяца, дня в processfiles, потому что установка их в processdirs осложнена правилами раскрытия переменных.

Если вы делаете гораздо больше, чем это, я бы порекомендовал изучить Python. У него отличное сообщество/экосистема, с ним легко начать работу, и он бесплатен. Кроме того, вы не тратите все свое время на борьбу с языком.

Вот моя первая попытка:

@echo off

setlocal

set s3root=d:\s3\bucket\voice

call :processdirs
goto :eof

:processfiles
  set year=%dirname:~0,4%
  set month=%dirname:~4,2%
  set day=%dirname:~6,2%

  set s3path=%year%%month%\%day%.%month%.%year%
  set s3dir=%s3root%\%s3path%
  if not exist "%s3dir%" md "%s3dir%"

  for %%f in (*.wav) do (
    sox "%%~nf.WAV" "%s3dir%\%%~nf.mp3"
    sox "%%~nf.WAV" "%s3dir%\%%~nf-short.mp3" trim 0:30 1:00
  )

  echo *S3COPY* %s3dir% %s3path%
  goto :eof

:processdirs
  for /D %%d in (*) do (
    set dirname=%%d
    cd "%%d"
    call :processfiles
    cd ..
  )
  goto :eof

Ответ @Aacini заставил меня понять, что, к сожалению, моего решения не хватает. Он не обрабатывает только сегодняшние файлы. Но меня беспокоит, что происходит, когда день пропускается.

Я добавил два параметра для управления тем, что обрабатывается. Первый параметр указывает именованный фильтр и может быть одним из следующих:

  • newlatest — новые файлы в последнем каталоге на основе имени файла (по умолчанию)
  • latest — все файлы в последнем каталоге, в зависимости от имени файла
  • today — сегодняшний каталог.
  • newdirs — все каталоги (отсутствуют даты), которые не существуют в дереве S3.
  • newfiles — все файлы, которых нет в дереве S3.
  • all — все файлы (используется для перезаписи повреждений в дереве S3)

Если используется фильтр newdirs, newfiles или all, то можно использовать второй параметр для дальнейшей фильтрации по имени каталога. Вы можете использовать * и ? подстановочные знаки для соответствия набору файлов.

Если вы сохраните скрипт как ProcDirs.bat, то вот несколько примеров:

ProcDirs all 20121119
Вызовет обработку (или повторную обработку) указанного каталога.

ProcDirs newdirs 201211??
Будет обрабатывать новые каталоги (отсутствующие в дереве вывода), соответствующие имени каталога (любой день указанного года и месяца).

ProcDirs newfiles 2012????
Будет обрабатывать новые файлы (отсутствующие в дереве вывода) в каталогах, соответствующих имени каталога (любой день указанного года).

ProcDirs
ProcDirs newlatest
Совершенно одинаковы, поскольку newlatest используется по умолчанию. Это будет обрабатывать новые файлы в (лексически) «последнем» каталоге.

Код сложнее, но не так уж и плохо. Я пытался использовать код @Aacini, чтобы получить текущий месяц/день/год, но он не работал в моей системе (поскольку мой формат даты должен отличаться от требуемого). Поэтому я использую другой подход, который не зависит от локальных форматов даты.

Мое первое решение не требовало отложенного расширения, но это требует, поэтому я включаю его с помощью setlocal (работает в Win XP, но, возможно, не в более старых Windows) и использую ! вместо % для подстановки переменных среды.

@echo off

setlocal enableextensions enabledelayedexpansion

set s3root=d:\s3\bucket\voice

rem Set the default filter mode

set newfilter=none
set dirsetfilter=none

set arg=%1
if "!arg!" == "" set arg=newlatest

if "!arg!" == "newdirs" (
  set newfilter=newdirs
) else if "!arg!" == "newfiles" (
  set newfilter=newfiles
) else if "!arg!" == "all" (
  set dirsetfilter=none
  set newfilter=none
) else if "!arg!" == "today" (
  set dirsetfilter=today
) else if "!arg!" == "latest" (
  set dirsetfilter=latest
) else if "!arg!" == "newlatest" (
  set newfilter=newfiles
  set dirsetfilter=latest
)

if !dirsetfilter! == today (
  for /f "skip=1 tokens=1-3" %%a IN ('wmic path Win32_LocalTime Get Day^,Month^,Year /Format:table') do (
    if %%a GTR 0 (
      set now_day=%%a
      set now_month=%%b
      set now_year=%%c
    )
  )
  set dirset=!now_year!!now_month!!now_day!
  if not "%2" == "" echo Second parameter, dirset, ignored when filter is today
) else if !dirsetfilter! == latest (
  rem pull out the name of the 'last' directory
  for /f "tokens=1" %%a IN ('dir /b /a:d /o:n ????????') do (
    set dirset=%%a
  )
  if not "%2" == "" echo Second parameter, dirset, ignored when filter is latest
) else if not "%2" == "" (
  rem The second parameter is dirset. Wild card chars, *? allowed
  rem only matched dir(s) processed
  set dirset=%2
) else (
  rem process all dirs that match filter
  set dirset=*
)

call :processdirs
goto :eof

:processfiles
  set file_year=!dirname:~0,4!
  set file_month=!dirname:~4,2!
  set file_day=!dirname:~6,2!

  set s3path=!file_year!!file_month!\!file_day!.!file_month!.!file_year!
  set s3dir=!s3root!\!s3path!

  set skipdir=FALSE
  if not exist "!s3dir!" (
    md "!s3dir!"
  ) else (
    if newdirs == !newfilter! set skipdir=TRUE
  )

  if !skipdir! == FALSE (
    set havenewfiles=FALSE

    for %%f in (*.wav) do (
      set skipfile=FALSE
      if newfiles==!newfilter! if exist "!s3dir!\%%~nf.mp3" set skipfile=TRUE
      if !skipfile! == FALSE (
        set havenewfiles=TRUE
        echo sox "%%~nf.WAV" "!s3dir!\%%~nf.mp3"
        sox "%%~nf.WAV" "!s3dir!\%%~nf.mp3"
      )

      set skipfile=FALSE
      if newfiles == !newfilter! if exist "!s3dir!\%%~nf-short.mp3" set skipfile=TRUE
      if !skipfile! == FALSE (
        set havenewfiles=TRUE
        echo sox "%%~nf.WAV" "!s3dir!\%%~nf-short.mp3" trim 0:30 1:00
        sox "%%~nf.WAV" "!s3dir!\%%~nf-short.mp3" trim 0:30 1:00
      )
    )

    if !havenewfiles! == TRUE (
      echo *S3COPY* !s3dir! !s3path!
    )
  )
  goto :eof

:processdirs
  for /D %%d in (!dirset!) do (
    echo Process Dir: %%d
    set dirname=%%d
    cd "%%d"
    call :processfiles
    cd ..
  )
  goto :eof

Удачи. Надеюсь, это поможет.

person Community    schedule 17.11.2012
comment
Ну, я пропустил ваш первый пункт, касающийся только сегодняшней даты. Мой код предполагает, что вы перемещаете обработанные файлы в какой-то момент. @Aacini правильно обрабатывает только сегодняшние файлы. Что касается вашего второго пункта, перемещения файлов, мне больше повезло с созданием файлов на месте, чтобы пропустить перемещение. Это на один шаг меньше и меньше возможных состояний, если процесс падает на полпути (не может падать во время перемещения). Мой код никогда не должен перемещать файлы. - person jimhark; 18.11.2012
comment
Также подумайте о проблемах в производстве. Если ваша работа не выполняется один день или дает сбой, убедитесь, что обработка файлов предыдущего дня не слишком сложна. - person jimhark; 18.11.2012
comment
Я опубликовал крупное обновление со второй версией, в которой вы можете выбрать, что обрабатывать: сегодняшние файлы, новые каталоги, новые файлы или все файлы. К сожалению, это сложнее. - person jimhark; 18.11.2012
comment
Привет, Джимхарк: Большое спасибо за быстрое возвращение. Позвольте мне попробовать это в моем сценарии. Обязательно сообщу вам об этом. - person N_D; 19.11.2012
comment
Добавлен второй параметр, разрешающий дополнительную фильтрацию по имени каталога. - person jimhark; 20.11.2012
comment
Добавлено объяснение кода, определяющего «последний» каталог. - person jimhark; 20.11.2012