Показать полную графическую версию : [решено] получить длительность аудио (wav)-файла.
Добрый.
Есть необходимость вывести длительность wav-файла в консоль.
Нашел для себя способ такой:
Get-MediaInfoSummary "C:\project\Book0001.wav" | Select-String -Pattern 'Duration'
на выходе получим:
Duration : 58 s 378 ms
Duration : 58 s 378 ms
причем дважды, т.к так выводит модуль.
General
Complete name : C:\project\Book0001.wav
Format : Wave
File size : 19.6 MiB
Duration : 58 s 378 ms
Overall bit rate mode : Constant
Overall bit rate : 2 823 kb/s
Audio
Format : PCM
Format profile : Float
Codec ID : 3
Codec ID/Hint : IEEE
Duration : 58 s 378 ms
Bit rate mode : Constant
Bit rate : 2 822 kb/s
Channel(s) : 2 channels
Sampling rate : 44.1 kHz
Bit depth : 32 bits
Stream size : 19.6 MiB (100%)
Для использования в переменной
$duration = Get-MediaInfoSummary "C:\project\Book0001.wav" | Select-String -Pattern 'Duration'
мне нужно 5-ти значное число и только в единственном экземпляре.
Т.е. было Duration : 58 s 378 ms
Duration : 58 s 378 ms
а нужно:
первый вариант:
58378
второй вариант:
58,378
Помогите с кодом пожалуйста.
$oMatchInfo = Get-MediaInfoSummary "C:\project\Book0001.wav" | Select-String -Pattern '^Duration : (\d+) s (\d+) ms$'
-join $oMatchInfo[0].Matches[0].Groups[1..2].Value
Foreigner
08-06-2021, 22:32
Get-MediaInfoSummary »
Это какая-то обертка mediainfo?
mediainfo --Output="Audio;%Duration/String3%" file.wav # HH:MM:ss.mmm
mediainfo --Output="Audio;%Duration%" file.wav # выводит миллисекунды
mediainfo --Info-Parameters # для другого форматирования вывода.
Это какая-то обертка mediainfo? »
Обёртка над обёрткой, над обёрткой: PowerShell Gallery | Get-MediaInfo 3.7 (https://www.powershellgallery.com/packages/Get-MediaInfo/3.7) → GitHub - stax76/MediaInfo.NET: MediaInfo.NET is a Windows application that shows media file information (https://github.com/stax76/MediaInfo.NET) → MediaInfo.dll (MediaInfo (https://mediaarea.net/en/MediaInfo)).
greg zakharov
08-06-2021, 22:57
Хм, а не проще ли тогда через проводник запросить длительность файла, нежели плодить обёртки?
greg zakharov, если я правильно понял — его миллисекунды интересуют.
greg zakharov
08-06-2021, 23:53
Iska, ежели так, можно и вовсе отказаться от каких-либо библиотек и, приложив к мозгу немного знаний математики, вычислить продолжительность аудио самостоятельно. В противном случае, что-то было в WPF относительно базовых данных по аудио файлам. К слову, можно использовать DirectX.
greg zakharov, возможно. Лень искать, когда не интересно и самому не надо.
Хм, а не проще ли тогда через проводник запросить длительность файла, нежели плодить обёртки? »
милисекунды не важны. как и не нужны лишние обертки.
просто не нашел другого способа.
как это сделать через проводник?
в идеале нужно чтобы результат выводился только в секундах.
т.е, например аудио - 2м43сек... на выходе должно быть - 163
DJ Mogarych
09-06-2021, 10:44
$path = 'C:\project\Book0001.wav'
$shell = New-Object -COMObject Shell.Application
$folder = Split-Path $path
$file = Split-Path $path -Leaf
$shellfolder = $shell.Namespace($folder)
$shellfile = $shellfolder.ParseName($file)
[TimeSpan]::Parse("$($shellfolder.GetDetailsOf($shellfile, 27);)").totalseconds
https://superuser.com/questions/704575/get-song-duration-from-an-mp3-file-in-a-script
https://stackoverflow.com/questions/21894169/calculate-total-seconds-from-string-in-format-hhmmss-fff/21894303
DJ Mogarych, хороший вариант. Спасибо.
помогите с кодировкой пож...
$path = "E:\!!Youtube\АРХИВ\!временное\Ролики\!в работе\tmp\1\Book0001.wav"
$shell = New-Object -COMObject Shell.Application
$folder = Split-Path $path
$file = Split-Path $path -Leaf
$shellfolder = $shell.Namespace($folder)
$shellfile = $shellfolder.ParseName($file)
$seconds = [TimeSpan]::Parse("$($shellfolder.GetDetailsOf($shellfile, 27);)").totalseconds
_________________________________________________________
$frames = $seconds * 30
$music_path = "E:\\!!Youtube\\АРХИВ\\!временное\\Ролики\\!в работе\\tmp\\1\\Book0001.wav"
$video_path = "E:\\!!Youtube\\АРХИВ\\!временное\\Ролики\\!в работе\\tmp\\1\\ProShow Slideshow 1.mp4"
Get-Content C:\project\kc\temp_1.tscproj | ForEach-Object {$_ -replace "music_path", $music_path} | Set-Content C:\project\kc\temp_2.tscproj
Get-Content C:\project\kc\temp_2.tscproj | ForEach-Object {$_ -replace "video_path", $video_path} | Set-Content C:\project\kc\temp_final.tscproj
при выполнении -replace, в конечном файле вместо (русских) значений из переменных - кракозябры!
(скрин кое как прикрепил)
Кодировка начального файла - utf-8. (без BOM). Так должно и остаться.
Помогите с кодом пож
DJ Mogarych
09-06-2021, 13:22
Get-Content C:\project\kc\temp_1.tscproj -Encoding UTF8 | ForEach-Object {$_ -replace "music_path", $music_path} | Set-Content C:\project\kc\temp_2.tscproj -Encoding utf8
огромное спасибо, значение вставляется корректно.
но на выходе получаем utf-8 С BOM (если верить notepad++).
А софту, который использует этот файл - нужен обычный UTF-8, и с utf-8 С BOM он не работает (пишет мол файл поврежден)
Стоит в notepad++ выставить обычный UTF-8, сохранить и все ок, все работает.
Могу сразу после замены получить обычный UTF-8 (БЕЗ BOM)?
-Encoding ASCII
дает желаемую кодировку, но все русские буквы внутри файла становятся "???"
DJ Mogarych
09-06-2021, 15:12
Потому что -Encoding ASCII - это 7-битная кодировка.
Судя по всему, проще всего поставить Powershell Core (https://github.com/PowerShell/powershell/releases/latest), там UTF8 without BOM - это кодировка по умолчанию.
https://stackoverflow.com/a/34969243
Либо воспользоваться решением оттуда же.
Есть вариант выключить BOM на уровне системы (в Windows 10), но лично я не стал бы так делать.
DJ Mogarych, поставил core. Спасибо
greg zakharov
09-06-2021, 17:02
DJ Mogarych, уже дал ответ как решается задача, через системный шелл. Давайте до кучи рассмотрим как вычислить продолжительность математически (Iska вроде бы сетовал, что ему не шибко хочется заморачиваться с расчётами). Для примера возьмём RIFF Wave (это те самые WAV, что можно отыскать в %systemroot%\Media). Формат такого WAV беспрецедентно прост: первые 12 байт - т.н. RIFF описатель, следующий 24 байта - описатели формата, далее два блока по четыре байта - пролог данных, а там и сами данные.
https://cdn1.savepice.ru/uploads/2021/6/9/ef6897377b12203e5be6b490849c719b-full.gif
Как видим всё просто, бутылка, дабы разобраться, нам не потребуется.
Обобщённый алгоритм вычисления длительности в миллисекундах:
using namespace System.IO
$br = [BinaryReader]::new(($fs = [File]::OpenRead(<# наш wav файл #>))
$fs.Position = 0x1C
$byterate = $br.ReadUInt32() # см. в таблицу касательно последовательности байт
$ms = (($fs.Length - 0x2C) * 1000) / $byterate # искомое значение
$br.Dispose()
Перевести в секунды, минуты, часы (нужное подчеркнуть) полученное значение, полагаю, уже не составит труда.
Serguei Kouzmine
10-06-2021, 07:15
@DJ Mogarych а не проще разве отрезать бом ?
. .\strip_bom.ps1 test1.txt
Directory: C:\Users\Serguei
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 6/10/2021 12:01 AM 10 test1.txt.new
-a---- 6/10/2021 12:00 AM 13 test1.txt
od -x test1.txt ; od -x test1.txt.new
0000000 bbef d1bf d082 d0b5 d1ba d181 0082
0000015
0000000 82d1 b5d0 bad0 81d1 82d1
0000012
UTF-8
The UTF-8 representation of the BOM is the (hexadecimal) byte sequence 0xEF,0xBB,0xBF.
сам скрипт:
param(
[String]$source,
[String]$dest = "${source}.new"
)
# https://stackoverflow.com/questions/288111/remove-byte-order-mark-from-a-file-readallbytes-byte
$text = [System.IO.File]::ReadAllText($source)
$writer = new-object System.IO.StreamWriter($dest, $false, (new-object System.Text.UTF8Encoding($false)))
$writer.Write($text)
$writer.Close()
@DJ Mogarych а не проще разве отрезать бом ? »
Не проще. Проще не писать BOM.
[System.IO.File]::WriteAllLines('C:\Мои проекты\0309\Sample.txt', 'Мама мыла раму', [System.Text.UTF8Encoding]::new($false))
Serguei Kouzmine
11-06-2021, 04:36
не писать BOM можно в своих логах а в чужих его придется отрезать
Serguei Kouzmine, в каком сообщении темы Вы видите «чужой лог»?
© OSzone.net 2001-2012
vBulletin v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.