2017-02-16 4 views
0

Was soll ich in diesem Fall mit dem folgenden Code tun?Wie man ein "Sagen" in Swift 3 im Befehlszeilenprogramm ausführt?

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 
} 

Zur Laufzeit, klagt sie über die Umwelt TERM ist nicht festgelegt und darüber hinaus schreibt die Datei nicht auf der Festplatte. Was ist zu tun?

+0

Es ist nicht klar, was Sie erreichen möchten. Möchten Sie Konsolenprotokolle drucken? –

+0

@ShyamalChandra Warum würden Sie eine Variable namens 'command_string' erstellen, wenn es sich tatsächlich um ein Array handelt? ಠ_ಠ – Alexander

Antwort

1

Der Hauptfehler ist, wie Sie das Argument-Array erstellen. Die angegebenen Argumente werden direkt an den Prozess übergeben. Process verwendet die Shell nicht zu interpretieren Sie die Argumente, daher müssen Sie sie nicht in das Zitat Markierungen einschließen.

Ein weiteres Problem ist, dass die Option "-i" (interaktiv) beim Schreiben in eine Datei nicht verwendet werden kann.

So sollte der Code wie folgt aussehen:

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 
} 

Die "--progress" Option wird eine Statusanzeige auf Standardfehler angezeigt werden. Wenn Sie das anzeigen möchten, müssten Sie asynchron von Standardfehler lesen.

0

Werfen Sie einen Blick auf diese Lib, ich habe es zuvor verwendet und es ist sehr fähig Shell-Skript ausführen. Damit können Sie dann den Befehl "say" verwenden und einige Argumente einsenden. https://github.com/kareman/SwiftShell

Sie könnten es versuchen, auf diese Weise zum Beispiel

import SwiftShell 

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

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

Wenn Sie eine native Mac App gerade schreiben und wollen synthetisierte Sprache in eine Audiodatei aufzunehmen, gehen Sie nicht versuchen, einen Shell-Befehl zu wickeln - Dafür gibt es eine native API . NSSpeechSynthesizer ist die macOS-API für Text-to-Speech im Allgemeinen, und es hat eine Methode startSpeaking(_:to:), die Ausgabe in eine Audiodatei aufzeichnet.

Diese API gibt an AIFF-Datei, aber es gibt zahlreiche APIs Sie konvertieren verwenden können, um/kodieren, das zu M4A: AVAssetReader/AVAssetWriter, AVAudioFile, niedrigerer Ebene CoreAudio- C APIs usw.

(Im Allgemeinen Wenn Sie ein natives Mac-Programm schreiben und etwas tun möchten, prüfen Sie, ob es eine API dafür gibt, bevor Sie versuchen, einen Shell-Befehl zu umbrechen. Normalerweise verwenden diese Shell-Befehle die gleiche API, also Sie nur bestrafen Sie sich mit allen Indirektion, I/O Parsing, etc.)

Ja, NSSpeechSynthesizer ist eine AppKit API, aber Sie können es in einer Befehlszeile verwenden Werkzeug.

Verwandte Themen