eConti - программирование в вопросах и ответах

Получить информацию о ffmpeg из Pipe (stdout)

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

ffmpeg -i MyVideo.MOV 2>&1 | grep "Duration"

Я получаю это:

  Duration: 00:01:23.53, start: 0.000000, bitrate: 39822 kb/s

Это идеально для меня. Но теперь я попробовал этот вызов из своего кода:

func shell(launchPath: String, arguments: [String]) -> String
{
    let task = Process()
    task.launchPath = launchPath
    task.arguments  = arguments

    let pipe = Pipe()
    task.standardOutput = pipe
    
    do {
        try task.run()
        // task.launch() till 10.12, but now catchable!
    } catch let error as NSError {
        print(error.localizedDescription)
        return ""
    }
    
    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output: String = NSString(data: data, encoding: String.Encoding.utf8.rawValue)! as String

    return output
}

Этот код отлично работает для всех других внешних команд. Но здесь я получаю ошибку:

[NULL @ 0x107808800] Unable to find a suitable output format for '2>&1'
2>&1: Invalid argument

Я определил аргументы для ffmpeg следующим образом:

let arguments = ["-i", video.path, "2>&1", "|", "grep \"Duration\"" ]

Даже если я помещу их все в один аргумент в виде большей строки, это не сработает. Использование pipe:1 вместо 2›&1 и остальных аргументов также приводит к ошибке.

Есть идеи, как мне заставить его работать?

12.08.2020

  • 2>&1 что значит перенаправить вывод ошибок в стандартный вывод, нет? Вам это действительно нужно? Вы знаете, что можете сделать это вручную, создав новый Pipe и написав task.standardError = newPipe 12.08.2020
  • Да, я знаю о 2›&1, но без этого завершающего элемента он не будет работать в терминале. Это место, где я сначала проверяю все команды. 12.08.2020
  • Согласно stackoverflow. com/questions/6239350/, он выводится в sdterror, так почему бы вам не сделать grep самостоятельно? task.standardOutput = pipe =› task.standardError = pipe и let durationLine = output.components(separatedBy: .whitespacesAndNewlines).filter{ $0.contains("Duration") } 12.08.2020

Ответы:


1

2>&1 означает, что все в стандартном Error (выводе) переходит в стандартный вывод.

Ну, тебе это совсем не нужно, да?

Почему бы не прочитать стандартную ошибку (выход) напрямую и не выполнить grep самостоятельно?

let pipe = Pipe()
task.standardError = pipe

... //task.run()

let data = pipe.fileHandleForReading.readDataToEndOfFile()
let output: String = String(data: data, encoding: .utf8)

Кстати, давайте избегать NSString и двойного преобразования в String.

Давайте сделаем grep сами.

let durationLine = output.components(separatedBy: .newlines).first(where: { $0.contains("Duration") }) 

Шаги: Давайте получим массив новых строк и найдем первую строку с длительностью.

12.08.2020
  • Большой! Вот и все. Мне пришлось перенаправить стандартную ошибку, потому что нужная мне информация была не из stdout, а из stderr! Большое спасибо, вы спасли мой день! :-) 12.08.2020
  • Кстати: пусть durationLine... выводит начальный текст Duration, а не время. Но я решил это самостоятельно с небольшим количеством кода. 12.08.2020
  • .whitespacesAndNewlines Я имел в виду .newlines * 12.08.2020
  • Новые материалы

    ИИ для общего блага, часть вторая
    В нашем последнем блоге мы исследовали возможности ИИ для общего блага, указав на несколько инициатив по поиску действенных решений для продвижения справедливых и беспристрастных систем ИИ. По..

    Время расцвета закончилось
    Большую часть своей карьеры в индустрии программного обеспечения программисты работали с головой в песок. Успех в отрасли требует навыков презентации и обучения других. Ценность улучшенных..

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

    Состояние совместной фильтрации в 2022 году, часть 1
    ResBeMF: Улучшение прогнозируемого охвата совместной фильтрации на основе классификации (arXiv) Автор: Анхель Гонсалес-Прието , Авраам Гутьеррес , Фернандо Ортега , Рауль Лара-Кабрера..

    Зачем изучать PYTHON в 2022 году !
    Python — востребованный, доступный язык программирования с активным, постоянно растущим сообществом пользователей. Для тех, кто хочет сменить профессию в мире технологий с помощью..

    Решение капч с помощью Puppeteer
    Это руководство предназначено для текстовых кодов, а не для reCAPTCHA Google (см. конец этого сообщения). Требования: Антикапча или любой другой сервис по разгадыванию капчи. Модуль..

    7 встроенных библиотек Python, которые необходимо знать
    7 встроенных библиотек Python, которые необходимо знать Стандартная библиотека Python значительно упрощает жизнь программистов, предоставляя широкий набор функций. Мы выбираем несколько..