2

我正在构建一个 JavaFx 应用程序,其中有一个文本文件和一个音频 mp3 文件,可以将其读出。当我使用MediaPlayer对象播放音频并显示文本文件中的文本时。有没有办法在播放每个单词时突出显示它们?我知道字幕是如何编码并保存在一个单独的文件中的,但在这里必须为每个单词完成。即文本文件上的每个单词都应该有元数据,它应该从 mp3 文件的开头突出显示偏移多长时间。

另一种方法是使用公式和文本和音频文件的长度进行计算,并找到每个世界应该保持突出显示的大致时间,但是这个凸轮会使突出显示不同步。

是否有任何标准方式或标准元数据格式可以在其中对信息进行编码,当旁白音频播放时,一个单词应保持突出显示多少时间?

4

1 回答 1

0

我为此使用了直接的逻辑。这些东西不能是自动的(可以,但需要无尽的努力),所以首先你需要让用户设置时间。显示 .txt 文件,并在后台播放歌曲。借助此功能,用户可以突出显示单词,现在您可以借助 System.Current 时间(以毫秒为单位)获取时间,并将时间存储在数组或列表中。完成后,现在您可以播放卡拉 OK。根据时间高亮显示单词。按下 ESC 键时,单词将高亮显示。根据需要更改 .txt 文件。请忽略我糟糕的编码风格:p

这是 Swing 中的演示:

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyEvent;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.reflect.InvocationTargetException;
import java.util.Scanner;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.sound.sampled.LineUnavailableException;
import javax.sound.sampled.UnsupportedAudioFileException;
import javax.swing.*;
import javax.swing.text.*;
import javax.swing.event.*;
import javax.swing.GroupLayout.*;


public class newh extends JFrame
                       implements DocumentListener {
 public static int[] arry=new int[1000];

static int first=0,last=0,scan=0,acount=0;int flag=1,point=0,j=0;long value,stat;
private JTextField entry;private boolean fir=true;
private JLabel jLabel1;
private JScrollPane jScrollPane1;
private JLabel status;
private JTextArea textArea;
private  JFrame frame;
long start;
final static Color  HILIT_COLOR = Color.YELLOW;
final static Color  ERROR_COLOR = Color.PINK;
final static String CANCEL_ACTION = "cancel-search";
final static String SMALL_ICON = "cancel-search";
final Color entryBg;
final Highlighter hilit;
final Highlighter.HighlightPainter painter;
private long start2;
JButton startButton;


public newh() throws FileNotFoundException {
    initComponents();
String[] a=new String[1000];
    InputStream in = getClass().getResourceAsStream("lyri.txt");
    try {
    textArea.read(new InputStreamReader(in), null);

    } catch (IOException e) {
    e.printStackTrace();
    }


   hilit = new DefaultHighlighter();
    painter = new DefaultHighlighter.DefaultHighlightPainter(HILIT_COLOR);
    textArea.setHighlighter(hilit);

    entryBg = entry.getBackground();
    entry.getDocument().addDocumentListener(this);

   InputMap im = entry.getInputMap(JComponent.WHEN_FOCUSED);
    ActionMap am = entry.getActionMap();

     im.put(KeyStroke.getKeyStroke("ESCAPE"), CANCEL_ACTION);
   am.put(CANCEL_ACTION, new CancelAction());




  }




/** This method is called from within the constructor to
 * initialize the form.
 */

  private void initComponents() {

    entry = new JTextField();
    textArea = new JTextArea();
    textArea.setBackground(Color.ORANGE);
    status = new JLabel();
    jLabel1 = new JLabel();
    frame = new JFrame();


  setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
    setTitle("TextFieldDemo");

    textArea.setColumns(20);
    textArea.setLineWrap(true);
    textArea.setRows(5);
    textArea.setWrapStyleWord(true);
    textArea.setEditable(false);
    jScrollPane1 = new JScrollPane(textArea);
 final JFrame jar=new JFrame();

    jLabel1.setText("Enter text to search:");
startButton = new JButton("Start");jar.add(startButton);
jar.setVisible(true);jar.pack();
    startButton.addActionListener(new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent ae) {
            try {
                ColoredTextTest.start();
            } catch (InterruptedException ex) {
                Logger.getLogger(newh.class.getName()).log(Level.SEVERE, null, ex);
            } catch (InvocationTargetException ex) {
                Logger.getLogger(newh.class.getName()).log(Level.SEVERE, null, ex);
            }
           setVisible(false);
           jar.setVisible(false);

            }
    });
    GroupLayout layout = new GroupLayout(getContentPane());
    getContentPane().setLayout(layout);

//Create a parallel group for the horizontal axis
ParallelGroup hGroup = layout.createParallelGroup(GroupLayout.Alignment.LEADING);

//Create a sequential and a parallel groups
SequentialGroup h1 = layout.createSequentialGroup();
ParallelGroup h2 = layout.createParallelGroup(GroupLayout.Alignment.CENTER);

//Add a container gap to the sequential group h1
h1.addContainerGap();

//Add a scroll pane and a label to the parallel group h2
h2.addComponent(jScrollPane1, GroupLayout.Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 600, Short.MAX_VALUE);
h2.addComponent(status, GroupLayout.Alignment.LEADING, GroupLayout.DEFAULT_SIZE, 900, Short.MAX_VALUE);

//Create a sequential group h3
SequentialGroup h3 = layout.createSequentialGroup();
h3.addComponent(jLabel1);
h3.addPreferredGap(LayoutStyle.ComponentPlacement.RELATED);
h3.addComponent(entry, GroupLayout.DEFAULT_SIZE, 900, Short.MAX_VALUE);

//Add the group h3 to the group h2
h2.addGroup(h3);
//Add the group h2 to the group h1
    h1.addGroup(h2);

h1.addContainerGap();

//Add the group h1 to the hGroup
hGroup.addGroup(GroupLayout.Alignment.TRAILING, h1);
//Create the horizontal group
layout.setHorizontalGroup(hGroup);


//Create a parallel group for the vertical axis
ParallelGroup vGroup = layout.createParallelGroup(GroupLayout.Alignment.LEADING);
//Create a sequential group v1
SequentialGroup v1 = layout.createSequentialGroup();
//Add a container gap to the sequential group v1
v1.addContainerGap();
//Create a parallel group v2
ParallelGroup v2 = layout.createParallelGroup(GroupLayout.Alignment.BASELINE);

v2.addComponent(jLabel1);
v2.addComponent(entry, GroupLayout.PREFERRED_SIZE, GroupLayout.DEFAULT_SIZE, GroupLayout.PREFERRED_SIZE);
//Add the group v2 tp the group v1

v1.addGroup(v2);
v1.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED);
v1.addComponent(jScrollPane1, GroupLayout.DEFAULT_SIZE, 900, Short.MAX_VALUE);
v1.addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED);
v1.addComponent(status);
v1.addContainerGap();

//Add the group v1 to the group vGroup
vGroup.addGroup(v1);

layout.setVerticalGroup(vGroup);
pack();
}

@SuppressWarnings("empty-statement")
public void search() throws BadLocationException {

int i;
    start=System.currentTimeMillis();


    arry[point]=(int) (start - start2-10);
    point++;


    if(fir==true)
    {fir=false;point=0;}
    start2=start;



    String s = textArea.getText();

    char[] words=s.toCharArray();


    for(i=last;words[i]!=' '&&words[i]!='\n';i++,last=i)
    {

    }
  try {
           hilit.addHighlight(first, last, painter);

      last++;   first=last;

      } catch (BadLocationException ex) {
           Logger.getLogger(newh.class.getName()).log(Level.SEVERE, null, ex);
    }


  }

void message(String msg) {

 }

// DocumentListener methods

public void insertUpdate(DocumentEvent ev) {
   // search();
}

public void removeUpdate(DocumentEvent ev) {
   // search();
}

public void changedUpdate(DocumentEvent ev) {
}

public void keyTyped(KeyEvent e) throws BadLocationException {

}

public void keyReleased(KeyEvent e) {
    throw new UnsupportedOperationException("Not supported yet.");
}

class CancelAction extends AbstractAction {
    public void actionPerformed(ActionEvent ev) {
        try {
            search();
        } catch (BadLocationException ex) {
            Logger.getLogger(newh.class.getName()).log(Level.SEVERE, null, ex);
        }

    }
 }




 public static void main(String args[]) throws UnsupportedAudioFileException, IOException, LineUnavailableException, InterruptedException {
 start();


}
   public void setvisiblet()
{
setVisible(true);

}
public void setvisiblef()
{
setVisible(false);

}
public static void start()
{

SwingUtilities.invokeLater(new Runnable() {
        public void run() {

            UIManager.put("swing.boldMetal", Boolean.FALSE);
            try {
                new newh().setVisible(true);
            } catch (FileNotFoundException ex) {
                Logger.getLogger(newh.class.getName()).log(Level.SEVERE, null, ex);
            }
        }
    });
 }


}
class ColoredTextTest extends javax.swing.JFrame {
private String[] words=new String[1000];
private JScrollPane sc;
String sentence="";
int stringIndex = 0;
 int index = 0;
 Timer timer;
StyledDocument  doc;
/** Creates new form textdisplay */
@SuppressWarnings("static-access")

public ColoredTextTest() throws FileNotFoundException, IOException {
    initComponents();
     doc = new DefaultStyledDocument();
jTextPane1.setDocument(doc);
 javax.swing.text.Style style = jTextPane1.addStyle("Red", null);
StyleConstants.setForeground(style, Color.RED);



    File file = new File("lyri.txt");
 BufferedReader br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
String line = null;
while( (line = br.readLine())!= null ){
sentence+=line;
sentence+='\n';
}

br.close();
int j=0;
Scanner input = new Scanner(new File("lyri.txt"));
file = new File("lyri.txt");
br = new BufferedReader(new InputStreamReader(new FileInputStream(file)));
while(input.hasNext()) {
words[j] = input.next(); System.out.println(words[j]);j++;words[j]=" ";j++;
}

jTextPane1.setText(sentence);


}


@SuppressWarnings("unchecked")

private void initComponents() {

    jPanel1 = new javax.swing.JPanel();
    jButton1 = new javax.swing.JButton();
    jButton2 = new javax.swing.JButton();
    jButton3 = new javax.swing.JButton();
    jButton4 = new javax.swing.JButton();
    jSeparator1 = new javax.swing.JSeparator();
    jScrollPane1 = new javax.swing.JScrollPane();
    jTextPane1 = new javax.swing.JTextPane();

    setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
    setBackground(new java.awt.Color(0, 0, 0));
    setUndecorated(true);

    jPanel1.setBackground(new java.awt.Color(0, 0, 0));
    jPanel1.setBorder(javax.swing.BorderFactory.createMatteBorder(3, 3, 3, 3, new java.awt.Color(0, 204, 204)));
    jPanel1.setInheritsPopupMenu(true);

    jButton1.setBackground(new java.awt.Color(255, 255, 0));
    jButton1.setFont(new java.awt.Font("Virtual DJ", 0, 14));
    jButton1.setForeground(new java.awt.Color(0, 255, 255));
    jButton1.setText("Back");
    jButton1.setOpaque(false);

    jButton2.setBackground(new java.awt.Color(255, 255, 0));
    jButton2.setFont(new java.awt.Font("Virtual DJ", 0, 14));
    jButton2.setForeground(new java.awt.Color(0, 255, 255));
    jButton2.setText("Pause");
    jButton2.setOpaque(false);

    jButton3.setBackground(new java.awt.Color(255, 255, 0));
    jButton3.setFont(new java.awt.Font("Virtual DJ", 1, 14));
    jButton3.setForeground(new java.awt.Color(0, 255, 255));
    jButton3.setText("Play");
    jButton3.setOpaque(false);
    jButton3.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jButton3ActionPerformed(evt);
        }
    });

    jButton4.setBackground(new java.awt.Color(255, 255, 0));
    jButton4.setFont(new java.awt.Font("Virtual DJ", 0, 14));
    jButton4.setForeground(new java.awt.Color(0, 255, 255));
    jButton4.setText("close");
    jButton4.setOpaque(false);
    jButton4.addActionListener(new java.awt.event.ActionListener() {
        public void actionPerformed(java.awt.event.ActionEvent evt) {
            jButton4ActionPerformed(evt);
        }
    });

    jSeparator1.setBackground(new java.awt.Color(51, 255, 255));

    jTextPane1.setBackground(new java.awt.Color(0, 0, 0));
    jTextPane1.setFont(new java.awt.Font("Tahoma", 0, 36)); // NOI18N
    jTextPane1.setForeground(new java.awt.Color(0, 255, 255));
    jTextPane1.setVerifyInputWhenFocusTarget(false);
    jScrollPane1.setViewportView(jTextPane1);

    javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1);
    jPanel1.setLayout(jPanel1Layout);
    jPanel1Layout.setHorizontalGroup(
        jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(jPanel1Layout.createSequentialGroup()
            .addContainerGap()
            .addComponent(jButton3, javax.swing.GroupLayout.PREFERRED_SIZE, 93, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
            .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 101, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
            .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 114, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED)
            .addComponent(jButton4, javax.swing.GroupLayout.DEFAULT_SIZE, 611, Short.MAX_VALUE)
            .addGap(23, 23, 23))
        .addComponent(jSeparator1, javax.swing.GroupLayout.DEFAULT_SIZE, 982, Short.MAX_VALUE)
        .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 982, Short.MAX_VALUE)
    );
    jPanel1Layout.setVerticalGroup(
        jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel1Layout.createSequentialGroup()
            .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 645, Short.MAX_VALUE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addComponent(jSeparator1, javax.swing.GroupLayout.PREFERRED_SIZE, 10, javax.swing.GroupLayout.PREFERRED_SIZE)
            .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED)
            .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.BASELINE)
                .addComponent(jButton3, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addComponent(jButton2, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addComponent(jButton4, javax.swing.GroupLayout.PREFERRED_SIZE, 37, javax.swing.GroupLayout.PREFERRED_SIZE)
                .addComponent(jButton1, javax.swing.GroupLayout.PREFERRED_SIZE, 36, javax.swing.GroupLayout.PREFERRED_SIZE)))
    );

    javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
    getContentPane().setLayout(layout);
    layout.setHorizontalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(jPanel1, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    );
    layout.setVerticalGroup(
        layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
        .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)
    );

    java.awt.Dimension screenSize = java.awt.Toolkit.getDefaultToolkit().getScreenSize();
    setBounds((screenSize.width-988)/2, (screenSize.height-710)/2, 988, 710);
  }// </editor-fold>

 private void jButton4ActionPerformed(java.awt.event.ActionEvent evt) {

    setVisible(false);
}

 private void jButton3ActionPerformed(java.awt.event.ActionEvent evt) {
    this.sc=jScrollPane1;
    JScrollBar verticalScrollBar = sc.getVerticalScrollBar();
    JScrollBar horizontalScrollBar = sc.getHorizontalScrollBar();
    verticalScrollBar.setValue(verticalScrollBar.getMinimum());
    horizontalScrollBar.setValue(horizontalScrollBar.getMinimum());





 dotimer();
  }

 public void dotimer()
 {

 ActionListener actionListener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent actionEvent) {

             System.out.println("index"+stringIndex);
            doc.setCharacterAttributes(stringIndex, 1, jTextPane1.getStyle("Red"), true);

            stringIndex++;

                try {
                    if (stringIndex >= doc.getLength() || doc.getText(stringIndex, 1).equals(" ")|| doc.getText(stringIndex, 1).equals("\n")) {
                        index++;
                    }
                } catch (BadLocationException ex) {
                    Logger.getLogger(ColoredTextTest.class.getName()).log(Level.SEVERE, null, ex);
                }
                if (index < 600) {

                    double delay = newh.arry[index];
                    timer.setDelay((int) (delay / words[index].length()));
                } else {
                    timer.stop();
                    System.err.println("Timer stopped");
                }

            }

    };
    timer = new Timer(newh.arry[index], actionListener);
    timer.setInitialDelay(0); System.out.println("done.........");
    timer.start();







 }
 public static void main(String args[]) throws InterruptedException, InvocationTargetException {
    start();

 }
 public static void start() throws InterruptedException, InvocationTargetException
 {
 SwingUtilities.invokeLater(new Runnable() {
        public void run() {
            try {
                new ColoredTextTest().setVisible(true);
            } catch (FileNotFoundException ex) {
                Logger.getLogger(ColoredTextTest.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(ColoredTextTest.class.getName()).log(Level.SEVERE, null, ex);
            }
            ColoredTextTest y = null;
            try {
                y = new ColoredTextTest();
            } catch (FileNotFoundException ex) {
                Logger.getLogger(ColoredTextTest.class.getName()).log(Level.SEVERE, null, ex);
            } catch (IOException ex) {
                Logger.getLogger(ColoredTextTest.class.getName()).log(Level.SEVERE, null, ex);
            }

        }
    });


   }

private javax.swing.JButton jButton1;
private javax.swing.JButton jButton2;
private javax.swing.JButton jButton3;
private javax.swing.JButton jButton4;
private javax.swing.JPanel jPanel1;
private javax.swing.JScrollPane jScrollPane1;
private javax.swing.JSeparator jSeparator1;
private javax.swing.JTextPane jTextPane1;


}
于 2013-01-31T09:05:21.730 回答