Войти

Показать полную графическую версию : [решено] получить длительность аудио (wav)-файла.


Страниц : [1] 2

9119
08-06-2021, 21:39
Добрый.

Есть необходимость вывести длительность 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


Помогите с кодом пожалуйста.

Iska
08-06-2021, 22:20
$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 # для другого форматирования вывода.

Iska
08-06-2021, 22:53
Это какая-то обертка 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
Хм, а не проще ли тогда через проводник запросить длительность файла, нежели плодить обёртки?

Iska
08-06-2021, 23:07
greg zakharov, если я правильно понял — его миллисекунды интересуют.

greg zakharov
08-06-2021, 23:53
Iska, ежели так, можно и вовсе отказаться от каких-либо библиотек и, приложив к мозгу немного знаний математики, вычислить продолжительность аудио самостоятельно. В противном случае, что-то было в WPF относительно базовых данных по аудио файлам. К слову, можно использовать DirectX.

Iska
09-06-2021, 03:44
greg zakharov, возможно. Лень искать, когда не интересно и самому не надо.

9119
09-06-2021, 10:07
Хм, а не проще ли тогда через проводник запросить длительность файла, нежели плодить обёртки? »
милисекунды не важны. как и не нужны лишние обертки.
просто не нашел другого способа.

как это сделать через проводник?

в идеале нужно чтобы результат выводился только в секундах.
т.е, например аудио - 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

9119
09-06-2021, 12:35
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

9119
09-06-2021, 14:24
огромное спасибо, значение вставляется корректно.

но на выходе получаем 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), но лично я не стал бы так делать.

9119
09-06-2021, 15:46
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()

Iska
10-06-2021, 21:54
@DJ Mogarych а не проще разве отрезать бом ? »
Не проще. Проще не писать BOM.
[System.IO.File]::WriteAllLines('C:\Мои проекты\0309\Sample.txt', 'Мама мыла раму', [System.Text.UTF8Encoding]::new($false))

Serguei Kouzmine
11-06-2021, 04:36
не писать BOM можно в своих логах а в чужих его придется отрезать

Iska
11-06-2021, 19:23
Serguei Kouzmine, в каком сообщении темы Вы видите «чужой лог»?




© OSzone.net 2001-2012