time4tea / gopro-dashboard-overlay

Programs to process GoPro MP4 & Generic GPX/FIT files and create video dashboards & maps
GNU General Public License v3.0
327 stars 48 forks source link

windows access violation loading cairo ToyFontFace #171

Open dyk74 opened 5 months ago

dyk74 commented 5 months ago

Hello, I have some trouble creating video file on win11... here the command (I removed personal information) and the result:

python .\venv\Scripts\gopro-dashboard.py --font trebuc.ttf --layout-xml C:\Users[...]\layout.xml --use-gpx-only --gpx C:\Users[...]\20230706030824-58228-data.gpx --profile overlay --show-ffmpeg --debug-metadata --print-timings --overlay-size 1920x1080 C:\Users[...]\test.mov

Here the result: Starting gopro-dashboard version 0.124.0 Running ['ffmpeg', '-version'] Running ['ffmpeg', '-v', 'quiet', '-codecs'] Running ['ffmpeg', '-version'] ffmpeg version is 6.1.1-essentials_build-www.gyan.dev Using Python version 3.12.1 (tags/v3.12.1:2305ca5, Dec 7 2023, 22:03:25) [MSC v.1937 64 bit (AMD64)] GPX/FIT file: 2023-07-02T11:41:40+00:00 -> 2023-07-02T11:53:02+00:00 Timer(loading timeseries - Called: 1, Total: 8.28410, Avg: 8.28410, Rate: 0.12) Generating overlay at Dimension(x=1920, y=1080) Timeseries has 6821 data points Processing.... Timer(processing - Called: 1, Total: 11.99538, Avg: 11.99538, Rate: 0.08) Using user-defined profile: overlay Timelapse Factor = 1.000 Layout -> Include component 'speed' = True

Where is my mistake (I suppose I made some) Thank you

time4tea commented 5 months ago

Hi. Thanks for your interest in the software!

The output you have posted looks like it might not be complete. Please could you double-check that there isn't any missing.

I dont have a Windows machine, so testing on Windows is a bit tricky, but it is believed to work on Windows, and it gets tested when there are significant changes.

I'll find a Windows machine and see if there is a problem. In the meantime, I'd appreciate it if you could double-check that you posted all the output.

Thanks!

dyk74 commented 5 months ago

I've checked the output and it is complete...that's why I opened the issue

dyk74 commented 5 months ago

Could I send you my layout file? maybe is the file wrong...

time4tea commented 5 months ago

Yes, please do! In theory, the program should report an error parsing the file, but maybe not in this case. Good idea. Please could you send it to gopro-overlay@time4tea.net

Thanks!

time4tea commented 5 months ago

Hi

I had the chance to look at your file. When I run the program I am getting an error - I am surprised that you don't see anything? It would be interesting to know how you are running the program.

Traceback (most recent call last):
  File "/home/richja/dev/gopro-graphics/bin/gopro-dashboard.py", line 362, in <module>
    overlay = Overlay(framemeta=frame_meta, create_widgets=layout_creator)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/gopro_overlay/layout.py", line 96, in __init__
    self.scene = Scene(create_widgets(self.entry))
                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py", line 210, in create
    *[do_element(child, 1) for child in root if want_element(child)]
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py", line 210, in <listcomp>
    *[do_element(child, 1) for child in root if want_element(child)]
      ^^^^^^^^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py", line 203, in do_element
    return elements[element.tag](element, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml_attribute.py", line 32, in wrapper
    return f(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py", line 167, in create_composite
    *[do_element(child, level + 1) for child in element if want_element(child)]
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py", line 167, in <listcomp>
    *[do_element(child, level + 1) for child in element if want_element(child)]
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py", line 203, in do_element
    return elements[element.tag](element, level)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py", line 156, in create_component
    widget=method(child, entry=entry)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml_attribute.py", line 32, in wrapper
    return f(*args, **kwargs)
           ^^^^^^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py", line 455, in create_text
    font=self.font(iattrib(element, "size", d=16)),
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py", line 113, in font_at
    return fonts.setdefault(size, font.font_variant(size=size))
                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/venv/lib/python3.11/site-packages/PIL/ImageFont.py", line 613, in font_variant
    return FreeTypeFont(
           ^^^^^^^^^^^^^
  File "/home/richja/dev/gopro-graphics/venv/lib/python3.11/site-packages/PIL/ImageFont.py", line 226, in __init__
    self.font = core.getfont(
                ^^^^^^^^^^^^^
OSError: invalid ppem value

Anyhow - this isn't a very good error message, but it is caused by the following bit in your layout file:

<component type="text" y="80" size="0" rgb="255,255,255,128">Alt(m)</component>

The font size has been set to zero which is causing a problem. If you set this to a larger value it should work. In the meantime I can add some validation for this value so that the error message is improved.

Thanks for bringing it to my attention.

dyk74 commented 5 months ago

Hello, I've followed your instruction on the website. Set-ExecutionPolicy Unrestricted -Scope Process

.\venv\Scripts\activate.ps1

python .\venv\Scripts\gopro-dashboard.py --font trebuc.ttf --ffmpeg C:\Users\james\Downloads\ffmpeg-6.0-essentials_build\ffmpeg-6.0-essentials_build\bin input.mp4 output.mp4

Of course the last line has been changed with the line I've sent you before. And I did receive back any error. I will check and I'll give you a feedback.

⁣Ottieni BlueMail per Android ​

Il giorno 21 Gen 2024, 16:18, alle ore 16:18, James Richardson @.***> ha scritto:

Hi

I had the chance to look at your file. When I run the program I am getting an error - I am surprised that you don't see anything? It would be interesting to know how you are running the program.

Traceback (most recent call last):
File "/home/richja/dev/gopro-graphics/bin/gopro-dashboard.py", line
362, in <module>
overlay = Overlay(framemeta=frame_meta, create_widgets=layout_creator)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/richja/dev/gopro-graphics/gopro_overlay/layout.py", line
96, in __init__
   self.scene = Scene(create_widgets(self.entry))
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py",
line 210, in create
   *[do_element(child, 1) for child in root if want_element(child)]
    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py",
line 210, in <listcomp>
   *[do_element(child, 1) for child in root if want_element(child)]
     ^^^^^^^^^^^^^^^^^^^^
File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py",
line 203, in do_element
   return elements[element.tag](element, level)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File
"/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml_attribute.py",
line 32, in wrapper
   return f(*args, **kwargs)
          ^^^^^^^^^^^^^^^^^^
File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py",
line 167, in create_composite
*[do_element(child, level + 1) for child in element if
want_element(child)]
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py",
line 167, in <listcomp>
*[do_element(child, level + 1) for child in element if
want_element(child)]
     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py",
line 203, in do_element
   return elements[element.tag](element, level)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py",
line 156, in create_component
   widget=method(child, entry=entry)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^
File
"/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml_attribute.py",
line 32, in wrapper
   return f(*args, **kwargs)
          ^^^^^^^^^^^^^^^^^^
File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py",
line 455, in create_text
   font=self.font(iattrib(element, "size", d=16)),
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/home/richja/dev/gopro-graphics/gopro_overlay/layout_xml.py",
line 113, in font_at
   return fonts.setdefault(size, font.font_variant(size=size))
                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File
"/home/richja/dev/gopro-graphics/venv/lib/python3.11/site-packages/PIL/ImageFont.py",
line 613, in font_variant
   return FreeTypeFont(
          ^^^^^^^^^^^^^
File
"/home/richja/dev/gopro-graphics/venv/lib/python3.11/site-packages/PIL/ImageFont.py",
line 226, in __init__
   self.font = core.getfont(
               ^^^^^^^^^^^^^
OSError: invalid ppem value

Anyhow - this isn't a very good error message, but it is caused by the following bit in your layout file:

<component type="text" y="80" size="0"
rgb="255,255,255,128">Alt(m)</component>

The font size has been set to zero which is causing a problem. If you set this to a larger value it should work. In the meantime I can add some validation for this value so that the error message is improved.

Thanks for bringing it to my attention.

-- Reply to this email directly or view it on GitHub: https://github.com/time4tea/gopro-dashboard-overlay/issues/171#issuecomment-1902668361 You are receiving this because you authored the thread.

Message ID: @.***>

time4tea commented 5 months ago

Error message should be improved in V0.125.0 which is on PyPI.

time4tea commented 5 months ago

I have just tried this on a windows machine - and i agree - you cannot see the output! Even the improved error message. I don't understand this behaviour.

time4tea commented 5 months ago

OK - This is actually a very different error to what it first appeared.... the program is crashing inside PyCairo.

Windows fatal exception: access violation

Current thread 0x000015a0 (most recent call first):
  File "C:\Users\james\PycharmProjects\gopro-dashboard-overlay\gopro_overlay\widgets\cairo\face.py", line 21 in __init__
  File "C:\Users\james\PycharmProjects\gopro-dashboard-overlay\gopro_overlay\widgets\cairo\gauge_round_254.py", line 76 in __init__
  File "C:\Users\james\PycharmProjects\gopro-dashboard-overlay\gopro_overlay\layout_xml_cairo.py", line 131 in create_cairo_gauge_round_annotated
  File "C:\Users\james\PycharmProjects\gopro-dashboard-overlay\gopro_overlay\layout_xml_attribute.py", line 32 in wrapper
  File "C:\Users\james\PycharmProjects\gopro-dashboard-overlay\gopro_overlay\layout_xml.py", line 689 in <lambda>
  File "C:\Users\james\PycharmProjects\gopro-dashboard-overlay\gopro_overlay\layout_xml.py", line 678 in with_cairo
  File "C:\Users\james\PycharmProjects\gopro-dashboard-overlay\gopro_overlay\layout_xml.py", line 689 in create_cairo_gauge_round_annotated

This seems to be that the required font isn't installed, but I wouldn't expect a fatal error. Still investigating...

time4tea commented 5 months ago

This seems to be a problem in pycairo. Using non-cairo libraries will work, or docker images.

https://github.com/pygobject/pycairo/issues/356

dyk74 commented 5 months ago

Hi again, I saw your demo in pycairo and I made some test and (I don't know why) this demo works in Windows 11..Maybe the demo can help you: import faulthandler import cairo import os

faulthandler.enable()

print([x for x in os.listdir('c:/windows/fonts') if "arial" in x]) with cairo.SVGSurface("example.svg", 200, 200) as surface: context = cairo.Context(surface) x, y, x1, y1 = 0.1, 0.5, 0.4, 0.9 x2, y2, x3, y3 = 0.6, 0.1, 0.9, 0.5 context.scale(200, 200) context.set_line_width(0.04) context.move_to(x, y) context.curve_to(x1, y1, x2, y2, x3, y3) context.stroke() context.set_source_rgba(1, 0.2, 0.2, 0.6) context.set_line_width(0.02) context.move_to(x, y) context.line_to(x1, y1) context.move_to(x2, y2) context.line_to(x3, y3) context.stroke()

face = cairo.ToyFontFace("arial.ttf", cairo.FONT_SLANT_NORMAL,  cairo.FONT_WEIGHT_NORMAL)
print(face)

In my point of view when the class is called somehow the surface is missing: I suppose that the "face" doesn't know where should be added

time4tea commented 5 months ago

Hmm. that is interesting. thanks!

dyk74 commented 5 months ago

I found a workaround (not clean but sounds working): I commented this major_annotation = EllipticAnnotation( ellipse=circle_with_radius(text_radius, centre), tick=TickParameters(step * 2.0, 1, 0), colour=major_annotation_colour, # face=ToyFontFace("arial"), mode=AnnotationMode.MovedInside, texts=major_texts, height=0.05, stretch=stretch, start=start + (length / sectors), length=length - (length / sectors) )

and on every file where the "face" is called...sounds working (on win11) ...please check it deeply