【问题标题】:How to play gif while using pyttsx3如何在使用 pyttsx3 时播放 gif
【发布时间】:2021-09-23 20:52:31
【问题描述】:

我有一个应用程序,它会询问用户应该回答的问题。 该应用程序使用 pyttsx3(2.9 版)来生成语音,我希望它在说话的同时,只有这样,只要它说话,一个 gif 动画就会播放。 如何实现? 例如:

import pyttsx3
engine = pyttsx3.init()
engine.say("I will speak this text")
engine.runAndWait()

我希望 gif 动画在 runAndWait 运行时开始运行并在它停止时停止

【问题讨论】:

  • 你运行的是什么 pyttsx3 版本?一个小的编码示例会有所帮助。
  • 好的,我发现 2.90 版在事件处理方面存在问题。 2.5 版适用于我。我会找到一些可能有帮助的代码。

标签: python gif pyttsx3


【解决方案1】:

好的,我找到了另一个可以处理我拥有的 GIF 图像的程序。

这个程序不言自明并显示一个 gif 图像。

我使用tkinterText 对象作为输出,使用Label 来保存图像。

它应该允许 GIF 动画运行,但它需要有关 GIF 的特定信息。

这在 Windows 10 和 pyttsx3 - 2.5 上运行

"""
Program outputs text while voice is speaking.

This program works on Python 2.6.14 and Python 3.7.3

"""

import tkinter as tk
from tkinter import filedialog as fido
import random, pyttsx3

class chatter:

    terminate = False

    def showText( self, m ):
        """talk.showText( m )"""
        self.main.insert( "insert", m )
        self.master.update( )
        self.main.edit_separator( )

    def Start( self, name ) ->"":
        """talk.Start( name )"""
        self.sentence = name.split(  )

    def Use( self, name, location, length ) ->"":
        """talk.Use( name, location, length )"""
        name = self.sentence.pop( 0 )
        self.showText( f"{name} " )

    def End( self, name, completed ) ->"":
        """talk.End( name, completed )"""
        if len( self.sentence ) > 0:
            while len( self.sentence ) > 0:
                name = self.sentence.pop( 0 )
                self.showText( f"{name}\n" )
        else:
            self.showText( "\n" )

    def Error( self, name, exception ) ->"":
        """talk.Error( name, exception )"""
        self.terminate = True
        self.engine.stop( )
        self.showText( f"\n{name}\n{exception}\n" )

    def say( self, m ):
        """talk.say( m )"""
        self.engine.say( m, m )
        self.engine.runAndWait(  )

    def intro( self ):
        for m in [
            "This program works on Python 2.6 and Python 3",
            "I am PYTTSX version 2.5" ]:
            talk.say( m )
        self.master.after( 100, self.imageUpdate, 0 )

    def displayInCanvas( self ):
        """talk.displayInCanvas( )"""
        self.image = fido.askopenfilename( title = 'Pick Gif' )
        w, h = self.image.width() + 14, self.image.height() + 46
        self.item = self.canvas.create_image( 2,2, anchor = "nw" )
        self.canvas.itemconfig( self.item, image = self.image )
        self.master.geometry( f"{w}x{h}" )
        self.labelframe[ "text" ] = self.image

    def getImage( self ):
        """talk.getImage( )"""
        self.item = tk.Label( anchor = "nw" )
        self.item.grid( row=0, column=1, sticky="nsew" )
        self.image = fido.askopenfilename( title = 'Pick Gif' )
        # This requires specific knowledge about the GIF image
        # n = number of animation frames
        # self.frame = [ tk.PhotoImage( master = self.master, file=self.image, format = 'gif -index %i' %( i ) ) for i in range( n ) ]
        self.frame = [ tk.PhotoImage(
            master = self.master, file = self.image, format = "gif -index 0" ) ]
        self.item.configure( image = self.frame[ 0 ] )

    def imageUpdate( self, ind ):
        """imageUpdate( ind )"""
        frame = self.frame[ ind ]
        ind += 1
        print( ind )
        # Will play gif infinitely
        if ind > 0: 
            ind = 0
        self.item.configure( image = frame )
        self.master.after( 100, self.imageUpdate, ind )

    def closer( self, ev = None ):
        self.master.destroy( )

    def __init__( self ):
        """talk.init"""

        self.engine =  pyttsx3.init(  )

        self.startUtter = self.engine.connect(
            "started-utterance", self.Start )
        self.wordsUtter = self.engine.connect(
            "started-word", self.Use )
        self.endsUtter  = self.engine.connect(
            "finished-utterance", self.End )
        self.erraUtter  = self.engine.connect(
            "error", self.Error )

        self.persona = self.engine.getProperty( "voices" )[~0].id
        self.engine.setProperty( "voice", self.persona )

        for a,b in [ ("rate", 150 ), ( "volume", 0.25 ) ]:
            self.engine.setProperty( a,b )
        self.engine.runAndWait( )

        self.master = tk.Tk()
        self.main = tk.Text(
            self.master, undo =1, wrap = "word",
            block = 1, width = 80, height = 25 )
        self.main.grid( row = 0, column = 0, sticky = "nsew" )

        self.master.bind( "<Escape>", self.closer )
        self.showText( __doc__ + "\n" )
        self.main.update_idletasks( )
        self.getImage( ) # load and display gif
        self.main.focus_set()
        self.master.after( 100, self.intro )

if __name__ == "__main__":

    talk = chatter( )
    tk.mainloop()

【讨论】:

  • 所以 gif 运行,程序会说话,但它们不协调。您是否知道如何让动画在程序说话时运行而在程序不说话时停止?
  • 如果这有效,那么pyttsx 事件有效,这是个好消息。如果您检查 gif 例程,您会发现我已将图像数量设置为零。换句话说,只会显示第一张图像。如果你想要动画,那么你需要知道动画帧的数量并将n设置为该数字,然后为self.frame设置un-rem相关代码。
  • 我最初使用PIL ImageTk,但遇到tkinter Text 冻结问题,因此改为纯tkinter 解决方案。如果这不起作用,PIL 仍然是一个选项。
  • 所以我设法做的是相当令人愉快的事情——我创建了 2 个从 tkinter 对象继承的独立对象——一个具有 TTS 方法,另一个激活动画。动画组件一直在监听并根据 TTS 包装器中的某些属性更新 gif,该属性根据计算机是否说话而更改。我认为它由 tkinter 事件循环工作和管理,但 gif 有一些延迟
  • 优秀的@username_94。我一直在修修补补PIL ImageTk,但取得了有限的成功。
猜你喜欢
  • 2020-01-07
  • 2014-01-21
  • 1970-01-01
  • 2018-06-05
  • 1970-01-01
  • 2013-12-23
  • 2022-11-14
  • 2017-06-23
  • 2023-04-08
相关资源
最近更新 更多