ffmpegrounded-cornerscaptionsrtvideo-subtitles

Text backdrop by ass formatting


I want to add box behind a word using ass subtitles formatting. The box should have border radius. the ass file later will be used by ffmpeg.

I have tried the BorderStyle=3 form stack ansers 1, 2 both of them do not provide a way to get rounded boxes. Also the BorderStyle=4 didn't work for me. In comments of last stack answer I found a possible reason that my libraries can be old, but anyway it doesn't seem that BorderStyle=4 will solve my problem of border radius. There is another way to achieve rounded box link to answer. I didn't figure it out how to install all the libs he explained there. Also the later answer seems to me over complicated. Is there an other way to make the borders of box rounded without suffering and pain? I also tried drawing the box with Drawing commands like

{\p1}m 0 0 s 100 0 100 100 0 100 c{\p0}

But it still doesn't seem to be the best way to achieve rounded borders.


Solution

  • Eventually I made it with drawing commands.

    The dialog looks something like this:

    Dialogue: 0,0:00:00.00,0:00:01.00,Default,,0,0,0,,{\an7\p1\bord0\shad0\1a&HAA&\c&H000000&\pos(100,100)\an7}m 0 10 b 0 0 10 0 20 0 l 70 0 b 80 0 80 10 80 10 l 80 30 b 80 40 70 40 60 40 l 20 40 b 0 40 0 30 0 30 l 0 30{\p0}
    

    The dialog consists of two parts; one is:

    {\an7\p1\bord0\shad0\1a&HAA&\c&H000000&\pos(100,100)\an7}
    

    which includes styling commands.

    The second part is:

    m 0 10 b 0 0 10 0 20 0 l 70 0 b 80 0 80 10 80 10 l 80 30 b 80 40 70 40 60 40 l 20 40 b 0 40 0 30 0 30 l 0 30
    

    These are the coordinates to paint the rounded corner box. To dive deeper into drawing in ass file please check this doc - Drawing commands section. Also, to get the coordinates of a dynamic rounded rectangle, I used this code:

    // Function to calculate points along a cubic Bezier curve
    const calculateBezierPoints = (initialPoints, segments) => {
      const [P0, P1, P2, P3] = initialPoints
      const points = []
      for (let t = 0; t <= 1; t += 1 / segments) {
        const x = (1 - t) ** 3 * P0[0] + 3 * (1 - t) ** 2 * t * P1[0] + 3 * (1 - t) * t ** 2 * P2[0] + t ** 3 * P3[0]
        const y = (1 - t) ** 3 * P0[1] + 3 * (1 - t) ** 2 * t * P1[1] + 3 * (1 - t) * t ** 2 * P2[1] + t ** 3 * P3[1]
        points.push([x, y])
      }
      return points
    }
    
    // Function to generate a rounded rectangle
    const generateRoundedRectangle = ({ width, height, radius, segments }) => {
      const coordinates = []
    
      // Top straight line (from top-left to top-right minus the radius)
      coordinates.push([radius, 0], [width - radius, 0])
    
      // Top-right corner
      const topRightInitialPoints = [[width - radius, 0], [width, 0], [width, radius], [width, radius]]
      const topRightCurve = calculateBezierPoints(topRightInitialPoints, segments)
      coordinates.push(...topRightCurve)
    
      // Right straight line (from top-right to bottom-right minus the radius)
      coordinates.push([width, radius], [width, height - radius])
    
      // Bottom-right corner
      const bottomRightInitialPoints = [[width, height - radius], [width, height], [width - radius, height], [width - radius, height]]
      const bottomRightCurve = calculateBezierPoints(bottomRightInitialPoints, segments)
      coordinates.push(...bottomRightCurve)
    
      // Bottom straight line (from bottom-right to bottom-left minus the radius)
      coordinates.push([width - radius, height], [radius, height])
    
      // Bottom-left corner
      const bottomLeftInitialPoints = [[radius, height], [0, height], [0, height - radius], [0, height - radius]]
      const bottomLeftCurve = calculateBezierPoints(bottomLeftInitialPoints, segments)
      coordinates.push(...bottomLeftCurve)
    
      // Left straight line (from bottom-left to top-left minus the radius)
      coordinates.push([0, height - radius], [0, radius])
    
      // Top-left corner
      const topLeftInitialPoints = [[0, radius], [0, 0], [radius, 0], [radius, 0]]
      const topLeftCurve = calculateBezierPoints(topLeftInitialPoints, segments)
      coordinates.push(...topLeftCurve)
    
      // Return the final coordinates for the rounded rectangle
      return coordinates
    }