code: def make_word_level_ass_file(
      utt_obj, output_dir_root, ass_file_config, audio_dur
  ):
      default_style_dict = {
          "Name": "Default",
          "Fontname": "Arial",
          "Fontsize": str(ass_file_config.fontsize),
          "PrimaryColour": "&Hffffff",
          "SecondaryColour": "&Hffffff",
          "OutlineColour": "&H0",
          "BackColour": "&H0",
          "Bold": "0",
          "Italic": "0",
          "Underline": "0",
          "StrikeOut": "0",
          "ScaleX": "100",
          "ScaleY": "100",
          "Spacing": "0",
          "Angle": "0",
          "BorderStyle": "1",
          "Outline": "1",
          "Shadow": "0",
          "Alignment": None,  # will specify below
          "MarginL": str(MARGINL),
          "MarginR": str(MARGINR),
          "MarginV": str(MARGINV),
          "Encoding": "0",
      }
  
      if ass_file_config.vertical_alignment == "top":
          default_style_dict[
              "Alignment"
          ] = "8"  # text will be 'center-justified' and in the top of the screen
      elif ass_file_config.vertical_alignment == "center":
          default_style_dict[
              "Alignment"
          ] = "5"  # text will be 'center-justified' and in the middle of the screen
      elif ass_file_config.vertical_alignment == "bottom":
          default_style_dict[
              "Alignment"
          ] = "2"  # text will be 'center-justified' and in the bottom of the screen
      else:
          raise ValueError(
              f"got an unexpected value for ass_file_config.vertical_alignment"
          )
  
      output_dir = os.path.join(output_dir_root, "ass", "words")
      os.makedirs(output_dir, exist_ok=True)
      output_file = os.path.join(output_dir, f"{utt_obj.utt_id}.ass")
  
      already_spoken_color_code = (
          r"{\c&H"
          + rgb_list_to_hex_bgr(ass_file_config.text_already_spoken_rgb)
          + r"&}"
      )
      being_spoken_color_code = (
          r"{\c&H"
          + rgb_list_to_hex_bgr(ass_file_config.text_being_spoken_rgb)
          + r"&}"
      )
      not_yet_spoken_color_code = (
          r"{\c&H"
          + rgb_list_to_hex_bgr(ass_file_config.text_not_yet_spoken_rgb)
          + r"&}"
      )
  
      with open(output_file, "w") as f:
          default_style_top_line = "Format: " + ", ".join(
              default_style_dict.keys()
          )
          default_style_bottom_line = "Style: " + ",".join(
              default_style_dict.values()
          )
  
          f.write(
              (
                  "[Script Info]\n"
                  "ScriptType: v4.00+\n"
                  f"PlayResX: {PLAYERRESX}\n"
                  f"PlayResY: {PLAYERRESY}\n"
                  "\n"
                  "[V4+ Styles]\n"
                  f"{default_style_top_line}\n"
                  f"{default_style_bottom_line}\n"
                  "\n"
                  "[Events]\n"
                  "Format: Layer, Start, End, Style, Name, MarginL, MarginR, MarginV, Effect, Text\n\n"
              )
          )
  
          # write first set of subtitles for text before speech starts to be spoken
          words_in_first_segment = []
          for segment_or_token in utt_obj.segments_and_tokens:
              if type(segment_or_token) is Segment:
                  first_segment = segment_or_token
  
                  for word_or_token in first_segment.words_and_tokens:
                      if type(word_or_token) is Word:
                          words_in_first_segment.append(word_or_token)
                  break
  
          text_before_speech = (
              not_yet_spoken_color_code
              + " ".join([x.text for x in words_in_first_segment])
              + r"{\r}"
          )
          subtitle_text = (
              f"Dialogue: 0,{seconds_to_ass_format(0)},{seconds_to_ass_format(words_in_first_segment[0].t_start)},Default,,0,0,0,,"
              + text_before_speech.rstrip()
          )
  
          f.write(subtitle_text + "\n")
  
          for segment_or_token in utt_obj.segments_and_tokens:
              if type(segment_or_token) is Segment:
                  segment = segment_or_token
  
                  words_in_segment = []
                  for word_or_token in segment.words_and_tokens:
                      if type(word_or_token) is Word:
                          words_in_segment.append(word_or_token)
  
                  for word_i, word in enumerate(words_in_segment):
                      text_before = " ".join(
                          [x.text for x in words_in_segment[:word_i]]
                      )
                      if text_before != "":
                          text_before += " "
                      text_before = (
                          already_spoken_color_code
                          + text_before
                          + r"{\r}"
                      )
  
                      if word_i < len(words_in_segment) - 1:
                          text_after = " " + " ".join(
                              [
                                  x.text
                                  for x in words_in_segment[
                                      word_i + 1 :
                                  ]
                              ]
                          )
                      else:
                          text_after = ""
                      text_after = (
                          not_yet_spoken_color_code
                          + text_after
                          + r"{\r}"
                      )
  
                      aligned_text = (
                          being_spoken_color_code + word.text + r"{\r}"
                      )
                      aligned_text_off = (
                          already_spoken_color_code
                          + word.text
                          + r"{\r}"
                      )
  
                      subtitle_text = (
                          f"Dialogue: 0,{seconds_to_ass_format(word.t_start)},{seconds_to_ass_format(word.t_end)},Default,,0,0,0,,"
                          + text_before
                          + aligned_text
                          + text_after.rstrip()
                      )
                      f.write(subtitle_text + "\n")
  
                      # add subtitles without word-highlighting for when words are not being spoken
                      if word_i < len(words_in_segment) - 1:
                          last_word_end = float(
                              words_in_segment[word_i].t_end
                          )
                          next_word_start = float(
                              words_in_segment[word_i + 1].t_start
                          )
                          if next_word_start - last_word_end > 0.001:
                              subtitle_text = (
                                  f"Dialogue: 0,{seconds_to_ass_format(last_word_end)},{seconds_to_ass_format(next_word_start)},Default,,0,0,0,,"
                                  + text_before
                                  + aligned_text_off
                                  + text_after.rstrip()
                              )
                              f.write(subtitle_text + "\n")
  
          # write final set of subtitles for text after speech has been spoken
          words_in_final_segment = []
          for segment_or_token in utt_obj.segments_and_tokens[::-1]:
              if type(segment_or_token) is Segment:
                  final_segment = segment_or_token
  
                  for word_or_token in final_segment.words_and_tokens:
                      if type(word_or_token) is Word:
                          words_in_final_segment.append(word_or_token)
                  break
  
          text_after_speech = (
              already_spoken_color_code
              + " ".join([x.text for x in words_in_final_segment])
              + r"{\r}"
          )
          # note: for now doing some extra padding with math.ceil(audio_dur)+1) to account for the fact that the video with subtitles can become
          # longer than the original audio during the MP4 creation stage.
          subtitle_text = (
              f"Dialogue: 0,{seconds_to_ass_format(words_in_final_segment[-1].t_end)},{seconds_to_ass_format(math.ceil(audio_dur)+1)},Default,,0,0,0,,"
              + text_after_speech.rstrip()
          )
  
          f.write(subtitle_text + "\n")
  
      utt_obj.saved_output_files[
          f"words_level_ass_filepath"
      ] = output_file
  
      return utt_obj
  
file_path: NeMo/tools/nemo_forced_aligner/utils/make_ass_files.py
imports: import math
  import os
  import soundfile
  from utils.constants import BLANK_TOKEN, SPACE_TOKEN
  from utils.data_prep import Segment, Token, Word
label_desc: Use image node_id 7 for calling a global function with example usage: make_word_level_ass_file(utt_obj, output_dir_root, ass_file_config, audio_dur) and returns: utt_obj