見出し画像

SVG形式の表示をそろえる戦い Kdenlive vs ブラウザ

最近、YouTubeにマイクラのプレイ動画をあげて遊んでます。
動画編集ソフトには無料で使えるKdenliveを使っています。

Kdenliveではsvg形式というXMLで記述された画像を読み込むことができます。svg形式を使うとテロップなどのテキストがキレイに表示できるのでうれしいです。
たとえばこんな感じ。

キレイな文字でこんにちは

いい感じですね。
「こんなんカンタンに表示できるだろ」と思っていたのですが、、この絵を出すまでにけっこう試行錯誤しました。。

初期状態はこんな表示からスタートします。

初期状態

左がKdenliveでの表示、右がブラウザ(Chrome)での表示です。
左のKdenlive側はだいたいOKですが、"に"と"は"に角が生えてるのが気になります。右側のブラウザは文字が画面外(上の方)に表示されています。svgの編集時にはブラウザで確認しながら作りたいのですが、これだともはや論外ですね。
※背景色にも違いがありますが、これは編集ソフトの色なので問題ありません。

今回はKdenliveもブラウザもいい感じに表示にする方法を備忘録として残しておきます。同じことにハマった人のヒントになればうれしいです。

初期状態

まずは初期状態のsvgです。一見よさそうに見えますが先ほどダメな絵の状態になります。

<svg xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080">
  <defs>
    <style type="text/css">
      g#hello {
        transform: translate(400,300);
      }
      g#hello text {
        font-family: "UD Digi Kyokasho NK-B";
        font-size: 200pt;
      }
      .base {
        fill: #a6f;
        stroke-width: 0;
      }
      .waku1 {
        stroke: #000;
        stroke-width: 20;
      }
      .waku2 {
        stroke: #fff;
        stroke-width: 32;
      }
      .waku3 {
        stroke: #000;
        stroke-width: 40;
      }
    </style>
  </defs>
  <g id="hello">
    <text class="hello waku3">
      こんにちは
    </text>
    <text class="hello waku2">
      こんにちは
    </text>
    <text class="hello waku1">
      こんにちは
    </text>
    <text class="hello base">
      こんにちは
    </text>
  </g>
</svg>

ブラウザの表示位置を直す

まずはブラウザの方から直していきます。

原因はcssのtranslate

文字が画面外に表示される原因はcssでtranslateの部分でした。

g#hello {
    transform: translate(400,300);
}

注目してほしいのは単位です。cssのtranslateには"400px"のように単位が必要なようです。なので単位を記述するとブラウザでも正しく表示されました。が、今度はKdenliveがおかしくなり、文字が画面外に表示されてしまいました。

タグに直接記述して回避する

どうにもならにのでcssをあきらめてタグの中に直接記述するようにします。

cssのtranslateを削除したうえで、gタグのattributeに追加します。
タグに書く場合はsvgの仕様に従うので単位は不要です。

<g id="hello" transform="translate(400,300)">
    <text class="hello waku3">
        こんにちは
    </text>
    ....

これで画面外に表示される問題は回避できました。

角をなくす

次に角をなくします。

原因は鋭利な部分の描画方法

角が出てる部分は、いずれも文字のハネの部分です。ハネを丸くする必要があります。

stroke-linejoinを指定して回避する

ハネてる部分を丸くするためにcssにstroke-linejoinを指定します。

g#hello text {
  font-family: "UD Digi Kyokasho NK-B";
  font-size: 200pt;
  stroke-linejoin:round;/* 追加 */
}

ここまでで、画像はこうなりました。

いい感じではありますが、文字の枠の太さが違いますね。KdenliveはChromeよりも太く表示されています。
最後にこれを直します。

枠の太さを統一する

原因はKdenliveのバグ(たぶん)

原因はよくわからないですがたぶんKdenliveのバグです。Kdenlive側の枠が太すぎる。この画像のサイズは1920x1080なので枠の太さに40pxしてもこんなに厚くなるわけがない。

vector-effectを指定して回避する

いろいろ試しましたが最終的には下記を追加したらよくなりました。

* {
  vector-effect: non-scaling-stroke;
}

拡大縮小したときに線の太さをどうするか?という設定らしいです。特に拡大も縮小もしてないのでなぜこれが有効なのか…
わからないけどうまくいったからヨシ!

最終形

最終形のコードです。修正箇所にコメントを入れています。
これで目標にしていた文字が表示されました。

<svg id="main" xmlns="http://www.w3.org/2000/svg" width="1920" height="1080" viewBox="0 0 1920 1080">
  <defs>
    <style type="text/css">
      * {
        vector-effect: non-scaling-stroke; /* 線の太さを統一するため */
      }
      g#hello {
        /* translateを削除 */
      }
      g#hello text {
        font-family: "UD Digi Kyokasho NK-B";
        font-size: 200pt;
        stroke-linejoin:round; /* 角を消すため */
      }
      .base {
        fill: #a6f;
        stroke-width: 0;
      }
      .waku1 {
        stroke: #000;
        stroke-width: 20;
      }
      .waku2 {
        stroke: #fff;
        stroke-width: 32;
      }
      .waku3 {
        stroke: #000;
        stroke-width: 40;
      }
    </style>
  </defs>
  <g id="hello" transform="translate(400,300)"> <!-- ブラウザ互換のためcss化しない -->
    <text class="hello waku3">
      こんにちは
    </text>
    <text class="hello waku2">
      こんにちは
    </text>
    <text class="hello waku1">
      こんにちは
    </text>
    <text class="hello base">
      こんにちは
    </text>
  </g>
</svg>


まとめ

Kdenliveとブラウザでの表示差異をなくす方法を備忘録として残しました。これ以外にも問題点はいっぱいありそうですが…
とはいえsvgが使えると、テロップの自動生成などを自作できるので楽しみです。

この記事が気に入ったらサポートをしてみませんか?