简体   繁体   English

在Swift 3内部命令行程序中如何执行“说”?

[英]How to do a “say” in Swift 3 inside command-line program?

What should I do in this case with the following code? 在这种情况下,我应该使用以下代码做什么?

func convertToM4A(filename: String, voice: String) -> Bool {

    let full_string = speaking_queue?.joined(separator: " ")
    let command_string: [String] = [/"-v \"\(voice)\"",*/ "--progress", "--output-file=\"\(filename)\"","-i", " \"\(full_string!)\""]
    print(command_string)

    /
    let DocumentsDirectory = FileManager().homeDirectory(forUser: "shyamalchandra")
    print((DocumentsDirectory?.absoluteString)!)
    */

    let task = Process()

    task.launchPath = "/usr/bin/say"
    task.arguments = command_string
    let pipe = Pipe()
    task.standardOutput = pipe
    task.launch()

    let data = pipe.fileHandleForReading.readDataToEndOfFile()
    let output: String? = String(data: data, encoding: String.Encoding.utf8)
    task.waitUntilExit()

    if let output = output {
        if !output.isEmpty {
            print(output.trimmingCharacters(in: .whitespacesAndNewlines))
        }
    }

    return true
}

At run-time, it complains about the TERM environment being not set and furthermore, doesn't write the file to disk. 在运行时,它抱怨未设置TERM环境,并且没有将文件写入磁盘。 What to do? 该怎么办?

The main error is how you build the argument array. 主要错误是如何构建参数数组。 The given arguments are passed directly to the process. 给定的参数直接传递给该过程。 Process does not use the shell to interpret the arguments, therefore you must not enclose them in quotation marks. Process不使用外壳程序来解释参数,因此您不得将其用引号引起来。

Another problem is that the "-i" (interactive) option cannot be used when writing to a file. 另一个问题是写入文件时无法使用“ -i”(交互式)选项。

So your code should look like this: 因此,您的代码应如下所示:

func convertToM4A(filename: String, voice: String) -> Bool {

    let fullString = "Hello world"

    let task = Process()
    task.launchPath = "/usr/bin/say"
    task.arguments = [ "-v", voice, "-o", filename, fullString]

    task.launch()
    task.waitUntilExit()

    return true
}

The "--progress" option causes a progress meter to be displayed on standard error. “ --progress”选项使进度表显示为标准错误。 If you want to display that then you would have to read asynchronously from standard error. 如果要显示该内容,则必须从标准错误中异步读取。

If you're writing a native Mac app and want to record synthesized speech to an audio file, don't go trying to wrap a shell command — there's native API for that. 如果您正在编写本机Mac应用程序,并且想要将合成语音记录到音频文件中,请不要尝试包装shell命令-有本机API。 NSSpeechSynthesizer is the macOS API for text-to-speech in general, and it has a method startSpeaking(_:to:) that records output to an audio file. NSSpeechSynthesizer是用于文本到语音NSSpeechSynthesizer的macOS API,它具有startSpeaking(_:to:) ,可将输出记录到音频文件中。

This API outputs to an AIFF file, but there are numerous APIs you can use to convert/encode that to M4A: AVAssetReader / AVAssetWriter , AVAudioFile , lower-level CoreAudio C APIs, etc. 该API输出到AIFF文件,但是有许多API可用于将其转换/编码为M4A: AVAssetReader / AVAssetWriterAVAudioFile ,较低级别的CoreAudio C API等。

(Generally, if you're writing a native Mac program and there's something you want to do, check to see if there's an API for it before you go trying to wrap a shell command. Usually those shell commands are using the same API, so you're just punishing yourself with all the indirection, I/O parsing, etc.) (通常,如果您正在编写本机Mac程序,并且需要执行某些操作,请在尝试包装Shell命令之前检查是否有适用于该程序的API。通常,这些Shell命令使用的是同一API,因此您只是通过所有间接,I / O解析等来惩罚自己)

Yes, NSSpeechSynthesizer is an AppKit API, but you can use it in a command line tool. 是的, NSSpeechSynthesizer是AppKit API,但是您可以在命令行工具中使用它。

Take a look at this lib, I've used it before and it is very capable of running shell script. 看看这个lib,我以前使用过它,它非常有能力运行shell脚本。 With that then you can use the "say" command and send in some arguments. 这样,您就可以使用“ say”命令并发送一些参数。 https://github.com/kareman/SwiftShell https://github.com/kareman/SwiftShell

You could try it this way for instance 你可以这样尝试

import SwiftShell

try runAndPrint("say", "Hello world", 4, "arguments")

let array = ["Hello world", "we", "are"]
try runAndPrint("say", array, array.count + 2, "arguments")

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用 Swift 使用 PythonKit 调用带有参数的 python 命令行工具 - Calling a python Command-line tool with arguments, with PythonKit using Swift Swift共享库是否为命令行应用程序静态链接? - Swift shared libraries getting statically linked for command-line apps? 命令行 Swift 脚本的最小可行 GUI 是什么? - What is the minimally-viable GUI for command-line Swift scripts? Swift命令行程序中的CFRunLoop - CFRunLoop in Swift Command Line Program 命令行C程序到Swift - Command Line C program to Swift 构建具有关联Swift库的Swift命令行工具时,为什么要嵌入框架? - When building a Swift command-line tool with associated Swift library why is the Framework being embedded? 命令行 Swift 测试出现奇怪的链接错误(可能是 Swift Package 管理器相关) - Strange Link Error With Command-Line Swift Test (May Be Swift Package Manager-Related) 从 Swift 命令行程序使用 NSURLSession - Using NSURLSession from a Swift command line program 如何处理命令行应用程序用户输入中的冒号? - How to handle colons in command-line application user inputs? 如何在 Swift 中访问命令行参数? - How do you access command line arguments in Swift?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM