Video with Text

Discuss how to use the Ren'Py engine to create visual novels and story-based games. New releases are announced in this section.
Forum rules
This is the right place for Ren'Py help. Please ask one question per thread, use a descriptive subject like 'NotFound error in option.rpy' , and include all the relevant information - especially any relevant code and traceback messages. Use the code tag to format scripts.
Post Reply
Message
Author
galadain
Regular
Posts: 31
Joined: Wed Sep 09, 2020 4:24 pm
Contact:

Video with Text

#1 Post by galadain »

I apologize if this isn't clear. I'm attempting to play a video with text instructions over portions of the video but not the entire thing. The whole process should be 100% automated. Does not require the player to continue clicking. How do I accomplish the part at the # sign below?

Here's what I have so far:

show instruct1 with fade

NARR1 "\"Step 1: Gather the required materials.\"{w=5.0}{nw}"

NARR1 "\"Step 2: Read chapters 1 and 2.\"{w=5.0}{nw}"

# At this point in need the video to continue playing with no text for ten seconds before the last step.

NARR1 "\"Step 3:Finish the assignment.\"{w=5.0}{nw}"

User avatar
hell_oh_world
Miko-Class Veteran
Posts: 777
Joined: Fri Jul 12, 2019 5:21 am
Contact:

Re: Video with Text

#2 Post by hell_oh_world »

Use tags to format your post. For codes, enclose them inside code tags.
Going back on the issue, use screen maybe then some timer.

Code: Select all

screen subtitled_movie(movie, duration, hide_on_finish=True, *subtitles_):
  default subtitles = [
    dict(subtitle=subtitle, show=False) for subtitle in subtitles_
  ]

  add movie

  if hide_on_finish:
    timer duration action Hide("subtitled_movie")

  for index, subtitle in enumerate(subtitles):
    $ sub = subtitle["subtitle"]

    if isinstance(sub, dict):
      $ text, start_time = sub["text"], sub["start_time"]
      $ end_time = sub.get(
          "end_time",
          (subtitles[index + 1]["subtitle"]["start_time"] if
          index != len(subtitles) - 1 else (start_time + (duration - start_time)))
        )

    elif isinstance(sub, (tuple, list)):
      $ text, start_time = sub[:2]
      $ end_time = sub[2] if len(sub) == 3 else (
          subtitles[index + 1]["subtitle"][1] if
          index != len(subtitles) - 1 else (start_time + (duration - start_time))
        )

    timer start_time action SetDict(subtitle, "show", True)
    timer end_time action SetDict(subtitle, "show", False)

    if subtitle["show"]:
      text text:
        align (0.5, 0.90)

image my movie = Movie(play="sample.webm", loop=False)

label start:
    show screen subtitled_movie(
        "my movie", 7, True, # movie and its duration and True for automatically hiding the screen once the duration is met.
        dict(text="Step 1", start_time=1), # shows step 1 at 1 second mark, if end time is not specified the text will hide until the spawn of the next subtitle after this
        dict(text="Step 2", start_time=2, end_time=3), # shows step 2 at 2 second mark up to the 3 second mark of the video
        dict(text="Step 3", start_time=4)) # since this is the last subtitle and end time is not specified, it hides when the duration is met.
        
    pause
You can also pass the subtitles in the screen in this format (text, start_time) or (text, start_time, end_time). So... show screen subtitled_movie(..., ("Step 1", 5)) is also valid.
You can also make use of atl to make a transition for the appearance of the subtitle.

Code: Select all

transform subtitle_animation:
    on show:
        alpha 0.0
        easein 0.25 alpha 1.0

    on hide:
        easeout 0.25 alpha 0.0
then in the part of if subtitle["show"]: you'll just change it to showif and add the atl

Code: Select all

showif subtitle["show"]:
  text text:
    align (0.5, 0.90)

    at subtitle_animation
Note also that it might be better to make a video with the subtitles in it rather than doing it in renpy, but yeah depends on you if you want to force the engine to do the trick.
Not sure if this works, not tried yet. Let me know if this really works. Ill try this later too to see if it works.
EDIT: Just tried it and it works.
Image

galadain
Regular
Posts: 31
Joined: Wed Sep 09, 2020 4:24 pm
Contact:

Re: Video with Text

#3 Post by galadain »

Your example (the spinning globe) looks exactly like what I want. Which set of code did you end up using? The entire thing?

User avatar
hell_oh_world
Miko-Class Veteran
Posts: 777
Joined: Fri Jul 12, 2019 5:21 am
Contact:

Re: Video with Text

#4 Post by hell_oh_world »

My codes would look alien especially if you're a beginner, what I could suggest is first to refer to some tutorials to gain some knowledge about the fundamentals of the engine. You can either use the `the tutorial` game from the launcher or refer to some youtube tutorials. The codes' main focus is on the use of `screen language` so you can search for `screen language renpy` and iir elaine from youtube has a great tutorial about this, or use this doc instead from the official renpy website https://www.renpy.org/dev-doc/html/scre ... n-language. Also, add in to your list to learn at least some basic python as the screen uses python in some parts (well, the engine uses python after all), so searching for python tutorials might help you. And I hope you don't mind these as I'm trying to help you by telling you where you can start to fully understand the code.

So I'm gonna let you understand the code as I've put comments (those starting with # are comments and ignored by the engine) that can guide you in understanding them, and I think it would be pointless to explain the screen code if you have little experience with the screen language, so I'll let you set your own pace, when you're ready then just go back at the code and analyze it line by line.

Okay, all things aside, I'll just combine all of the codes for you to see where they should be placed. Note that you can place the codes anywhere you want, create separate files if that's what you prefer, the engine doesn't mind them, they will be all stitched together during runtime. Kindly observe the indentation level also, make sure that screen, transform and label statements have the same indentations, meaning you can't put transform inside screens, inside labels etc., as those will make transform have more than 0 indentation, if that makes sense.

Code: Select all

transform subtitle_animation():
  # the codes for the transform...

# the screen definition
screen subtitled_movie(movie, duration, hide_on_finish=True, *subtitles_):
  # the codes for the screen...
  
  showif subtitle["show"]:
   text text: # the text that you can style to suit your needs
     align (0.5, 0.9)
     bold True
     
     at subtitle_animation # the transform added to the subtitle
  
image my movie = Movie(play="my_movie.webm", loop=False)

label start:
  # my first example here is kinda hard to understand, so we'll use the simpler approach the (text, start_time, end_time) format.
  # so since the codes make use of the screen language, we'll use the show screen / call screen command to show this, both have different effects and you can refer to official renpy docs.

  show screen subtitled_movie ("my movie", 10.0, True, ("First Sub", 0.0, 2.0), ("Second Sub", 3.0), ("Third Sub", 3.0))
  # so this how you show a screen, so to show it you'll just refer to your screen definition and check the parameters so we'll know on how to show it properly.

  # (movie, duration, hide_on_finish=True, *subtitles_) the screen uses these parameters as signature, so we'll show it in this format.
  # we first pass the movie which is declared as my movie, we pass the name of the movie as string so that's why it's "my movie" instead of plain my movie
  # 10.0 the duration of the movie.
  # True makes the screen hide itself when the video is finished, because just like images, renpy does not hide screens automatically once they're done, so we hide it once finished. but depends, if you want to retain it and just hide it manually at some point, then just make it False.
  # The remaining parts are all considered as subtitles. subtitles should be in the format (text, start_time, end_time) or (text, start_time) where each one should be separated by commas.
 
  pause

  # Now, the code might look messy when there's many subtitles, so I suggest formatting your code like this.
  show screen subtitled_movie (
    "my movie", 10.0, True,
    ("First Sub", 0.0, 2.0),
    ("Second Sub", 3.0),
    ("Third Sub", 3.0)) # just add after this, don't forget to separate each subtitle entry with commas.
    
  pause
PS: I have 0 information on how good you are already with the engine so bear with me if some parts sound pretty repetitive to you as you are familiar with them already.

User avatar
Imperf3kt
Lemma-Class Veteran
Posts: 3794
Joined: Mon Dec 14, 2015 5:05 am
itch: Imperf3kt
Location: Your monitor
Contact:

Re: Video with Text

#5 Post by Imperf3kt »

There's several other ways you could achieve this as well.
You could use ATL or you could use movie sprites and an alpha mask or you could fudge around with the wait text tag, or (least desirable) you could just encode the subtitles into the video.
Warning: May contain trace amounts of gratuitous plot.
pro·gram·mer (noun) An organism capable of converting caffeine into code.

Current project: GGD Mentor

Twitter

galadain
Regular
Posts: 31
Joined: Wed Sep 09, 2020 4:24 pm
Contact:

Re: Video with Text

#6 Post by galadain »

The first set of code you provided works for the most part. Thanks.

Code: Select all

screen subtitled_movie(movie, duration, hide_on_finish=True, *subtitles_):
  default subtitles = [
    dict(subtitle=subtitle, show=False) for subtitle in subtitles_
  ]

  add movie

  if hide_on_finish:
    timer duration action Hide("subtitled_movie")

  for index, subtitle in enumerate(subtitles):
    $ sub = subtitle["subtitle"]

    if isinstance(sub, dict):
      $ text, start_time = sub["text"], sub["start_time"]
      $ end_time = sub.get(
          "end_time",
          (subtitles[index + 1]["subtitle"]["start_time"] if
          index != len(subtitles) - 1 else (start_time + (duration - start_time)))
        )

    elif isinstance(sub, (tuple, list)):
      $ text, start_time = sub[:2]
      $ end_time = sub[2] if len(sub) == 3 else (
          subtitles[index + 1]["subtitle"][1] if
          index != len(subtitles) - 1 else (start_time + (duration - start_time))
        )

    timer start_time action SetDict(subtitle, "show", True)
    timer end_time action SetDict(subtitle, "show", False)

    if subtitle["show"]:
      text text:
        align (0.5, 0.90)

image my movie = Movie(play="sample.webm", loop=False)

label start:
     show screen subtitled_movie(
        "my movie", 7, True, # movie and its duration and True for automatically hiding the screen once the duration is met.
        dict(text="Step 1", start_time=1), # shows step 1 at 1 second mark, if end time is not specified the text will hide until the spawn of the next subtitle after this
        dict(text="Step 2", start_time=2, end_time=3), # shows step 2 at 2 second mark up to the 3 second mark of the video
        dict(text="Step 3", start_time=4)) # since this is the last subtitle and end time is not specified, it hides when the duration is met.
        
    pause
I attempted to change the duration like this to have the steps display "Step 1: from 0 to 10 seconds, "Step 2" from 10 to 20 seconds, and "Step 3" from 30 to 40 seconds.

Code: Select all

show screen subtitled_movie(
        "my movie", 7, True, # movie and its duration and True for automatically hiding the screen once the duration is met.
        dict(text="Step 1", start_time=1,), # shows step 1 at 1 second mark, if end time is not specified the text will hide until the spawn of the next subtitle after this
        dict(text="Step 2", start_time=10, end_time=20), # shows step 2 at 2 second mark up to the 3 second mark of the video
        dict(text="Step 3", start_time=30)) # since this is the last subtitle and end time is not specified, it hides when the duration is met.
"Step 1" displays fine but then the video pauses and no other steps are displayed.

User avatar
hell_oh_world
Miko-Class Veteran
Posts: 777
Joined: Fri Jul 12, 2019 5:21 am
Contact:

Re: Video with Text

#7 Post by hell_oh_world »

you have to take note of the duration. your duration says it's 7 but you have starting time/end times that are larger than it.
Now in my opinion, I think I explained the code pretty well as I even wrote a second post which explains how to use it in the easiest way, so I don't know if you forgot about it or what. It might be better to reread first the instructions that I laid in or triple check the original codes and explanations to see if you're doing it right. This is not to be rude though, so pardon me if that came out offensive, I'm just stating the obvious.
And if you're having a really hard time understanding this or implementing this, then you could always resort to what I suggested in my first post and to what Imperfekt suggested. I think it's better to not push things that you really cant, it's better to have a code that you can maintain because you know how to use it than just relying on some piece of code that you cant implement well. After all of these are just suggestions so you can hear others' solutions as well.

galadain
Regular
Posts: 31
Joined: Wed Sep 09, 2020 4:24 pm
Contact:

Re: Video with Text

#8 Post by galadain »

you have to take note of the duration. your duration says it's 7 but you have starting time/end times that are larger than it.
Now in my opinion, I think I explained the code pretty well as I even wrote a second post which explains how to use it in the easiest way, so I don't know if you forgot about it or what. It might be better to reread first the instructions that I laid in or triple check the original codes and explanations to see if you're doing it right. This is not to be rude though, so pardon me if that came out offensive, I'm just stating the obvious.
And if you're having a really hard time understanding this or implementing this, then you could always resort to what I suggested in my first post and to what Imperfekt suggested. I think it's better to not push things that you really cant, it's better to have a code that you can maintain because you know how to use it than just relying on some piece of code that you cant implement well. After all of these are just suggestions so you can hear others' solutions as well.
You explained everything fine. Thanks. I just couldn't get the code from your second post to work but I'm sure that's on me. Also, I should have double checked the duration thing. I guess that's what I get for just coping and pasting without double checking things. I changed the duration and everything work now.

One more question if you don't mind: in the example video from your original post, the dialog box behind the text is transparent (or removed altogether). How did you accomplish that?

User avatar
hell_oh_world
Miko-Class Veteran
Posts: 777
Joined: Fri Jul 12, 2019 5:21 am
Contact:

Re: Video with Text

#9 Post by hell_oh_world »

there's no dialogue box because we're showing the subtitle as part of the custom screen that we made and not as a say statement like this.

Code: Select all

mc "Sub 1"
so if you want to style the subtitle or maybe add some characters to it (the name of the speaker for the subtitle) or add dialogue boxes then you might need to modify the screen a bit.

Code: Select all

define mc = Character("Nicole")

label start:
  show screen subtitle_movie("my_movie", 10.0, True, ("[mc]\nThis is [mc]'s dialogue.", 0.0))
the example does not modify the screen but instead we're doing a little workaround in passing the dialogue and the speaker's name so that it would appear like...

Code: Select all

	Nicole
This is Nicole's dialogue.
But for the other complicated stuffs (dialogue boxes, etc.) I'm afraid you'll need to tweak the screen a bit, like encapsulate the text inside a frame etc.

galadain
Regular
Posts: 31
Joined: Wed Sep 09, 2020 4:24 pm
Contact:

Re: Video with Text

#10 Post by galadain »

there's no dialogue box because we're showing the subtitle as part of the custom screen that we made and not as a say statement like this.
Weird. I'm seeing a dialogue box on mine. Any idea what I missed because everything else is working?

Code: Select all

show screen subtitled_movie(
        "my movie", 68, True,
        dict(text="Step 1", start_time=1, end_time=10),
        dict(text="Step 2", start_time=11, end_time=21),
        dict(text="Step 3", start_time=40))
This is working perfectly for the timing. How do I change it so different charters are saying different lines during the video? For example, my MC is saying "Step 1" and "Step 2" while NPC1 says "Step 3" while using the same timing listed above.

User avatar
hell_oh_world
Miko-Class Veteran
Posts: 777
Joined: Fri Jul 12, 2019 5:21 am
Contact:

Re: Video with Text

#11 Post by hell_oh_world »

Weird. I'm seeing a dialogue box on mine. Any idea what I missed because everything else is working?
Try hiding the window before showing the movie.

Code: Select all

window hide
show screen subtitled_movie(...)
https://www.renpy.org/doc/html/dialogue ... management

galadain
Regular
Posts: 31
Joined: Wed Sep 09, 2020 4:24 pm
Contact:

Re: Video with Text

#12 Post by galadain »

Perfect! (and surprisingly easy compared to everything else)

What about having the characters say the lines? Preferably using this code:

Code: Select all

show screen subtitled_movie(
        "my movie", 68, True,
        dict(text="Step 1", start_time=1, end_time=10), #main character
        dict(text="Step 2", start_time=11, end_time=21), #main character
        dict(text="Step 3", start_time=40)) #NPC1

User avatar
hell_oh_world
Miko-Class Veteran
Posts: 777
Joined: Fri Jul 12, 2019 5:21 am
Contact:

Re: Video with Text

#13 Post by hell_oh_world »

What about having the characters say the lines?
Please, try to do a backread of my posts, I just literally told a workaround for this. And just as what I said in that post containing that workaround, if it does not fully produce the effect you're aiming then you can only hope for customising the screen I made, specifically in the text part.

Post Reply

Who is online

Users browsing this forum: Bing [Bot], FAST WebCrawler [Crawler]