<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>vtt | imakat.com</title>
	<atom:link href="https://imakat.com/tag/vtt/feed/" rel="self" type="application/rss+xml" />
	<link>https://imakat.com</link>
	<description>工夫と改善で人生をちょっと豊かに</description>
	<lastBuildDate>Sat, 28 Mar 2026 21:09:29 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.9.4</generator>

<image>
	<url>https://i0.wp.com/imakat.com/wp-content/uploads/2023/07/cropped-80d64ecd340db4e2ca3224859b04caed.png?fit=32%2C32&#038;ssl=1</url>
	<title>vtt | imakat.com</title>
	<link>https://imakat.com</link>
	<width>32</width>
	<height>32</height>
</image> 
<site xmlns="com-wordpress:feed-additions:1">160909258</site>	<item>
		<title>【Mac】Geminiで無料でVTT字幕を生成する</title>
		<link>https://imakat.com/2026/03/26/28762/</link>
		
		<dc:creator><![CDATA[imakat]]></dc:creator>
		<pubDate>Thu, 26 Mar 2026 11:59:19 +0000</pubDate>
				<category><![CDATA[字幕作成]]></category>
		<category><![CDATA[デジタル]]></category>
		<category><![CDATA[ものづくり]]></category>
		<category><![CDATA[字幕]]></category>
		<category><![CDATA[Gemini]]></category>
		<category><![CDATA[Gem]]></category>
		<category><![CDATA[vtt]]></category>
		<guid isPermaLink="false">https://imakat.com/?p=28762</guid>

					<description><![CDATA[動画の字幕作成については、これまで何度も試行錯誤を繰り返してきましたが、「これだ！」と思えるおすすめの方法を見つけました 。 今回は、Googleの生成AI（Gemini）の「Gem共有（カスタムAIエージェント）」を活 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large is-resized"><a href="https://imakat.com/rd.php?id=aQFJQPda.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=aQFJQPda.png" alt="" style="aspect-ratio:1.4480358030830434;width:268px;height:auto"/></a></figure>



<p>動画の字幕作成については、これまで何度も試行錯誤を繰り返してきましたが、「これだ！」と思えるおすすめの方法を見つけました 。</p>



<p>今回は、Googleの生成AI（Gemini）の「Gem共有（カスタムAIエージェント）」を活用して、高精度なVTT字幕を生成するプログラムを作成しましたので紹介します 。</p>



<p>最大の特徴は、<strong>サブスクリプション不要（無料）で実践できる</strong>という点です 。（※Googleアカウントは必要です 。）</p>



<p>Geminiの文字起こしはマルチモーダル処理のため、精度は非常に高く、後から手直しする手間が劇的に減ります 。無料枠の制限を賢く回避しつつ、面倒な作業は、Macクイックアクションで自動化する、実践的なワークフローを公開します。</p>



<p>解説動画をご覧ください。</p>


<div class="sc-vimeo-embed">
  <p style="font-size: 14px;" class="sc-link">
    <a href="https://imakat.com/vm5?movid=1177224964" target="_blank" onclick="stopVimeoBeforeNavigate(event, this)">
      動画を別ページで表示(ここをクリック)
    </a>
  </p>

  <div class="iframe-wrapper">
    <iframe
      src="https://player.vimeo.com/video/1177224964?title=0&byline=0&portrait=0&controls=1&speed=1&texttrack=ja&dnt=1&loop=0"
      frameborder="0"
      allow="autoplay; fullscreen; picture-in-picture"
      allowfullscreen></iframe>
  </div>

  <div class="dr-vimeo-sublist">
    <details translate="yes"><summary translate="yes">字幕一覧(クリック)</summary> <p translate="yes">
(<a href="#" class="imk-cue" data-seek="0:00" translate="no">00:00:00</a>)  〜無料でGem共有でvtt字幕生成〜<br>
(<a href="#" class="imk-cue" data-seek="0:14" translate="no">00:00:14</a>)  今回は、えーGem。Gemというのは、GoogleのAIエージェントですけれども、<br>
(<a href="#" class="imk-cue" data-seek="0:24" translate="no">00:00:24</a>)  それを使って、VTT字幕の生成を行うプログラムを作成したので紹介します。<br>
(<a href="#" class="imk-cue" data-seek="0:36" translate="no">00:00:36</a>)  動画の字幕作成については、これまで何度も取り上げてきました。<br>
(<a href="#" class="imk-cue" data-seek="0:43" translate="no">00:00:43</a>)  でもまあ、なかなかここで満足ということにはなりませんが、<br>
(<a href="#" class="imk-cue" data-seek="0:48" translate="no">00:00:48</a>)  最近これが結構おすすめという方法を見つけましたので紹介します。<br>
(<a href="#" class="imk-cue" data-seek="0:56" translate="no">00:00:56</a>)  生成AIを使う方法です。<br>
(<a href="#" class="imk-cue" data-seek="1:00" translate="no">00:01:00</a>)  サブスクなしで、お金を使わないでできる方法ですのでご心配なく。<br>
(<a href="#" class="imk-cue" data-seek="1:11" translate="no">00:01:11</a>)  ただし、Googleアカウントは必要になります。<br>
(<a href="#" class="imk-cue" data-seek="1:16" translate="no">00:01:16</a>)  まず、字幕を作りたい動画を用意します。<br>
(<a href="#" class="imk-cue" data-seek="1:21" translate="no">00:01:21</a>)  今回ですね、一つ10分弱の動画をですね用意しました。<br>
(<a href="#" class="imk-cue" data-seek="1:29" translate="no">00:01:29</a>)  VTT作成用にこの動画を分割します。<br>
(<a href="#" class="imk-cue" data-seek="1:34" translate="no">00:01:34</a>)  その理由はGeminiのGemを使うとき、特に無料アカウントで使うときは、<br>
(<a href="#" class="imk-cue" data-seek="1:42" translate="no">00:01:42</a>)  動画は5分以内という制限があるからです。<br>
(<a href="#" class="imk-cue" data-seek="1:49" translate="no">00:01:49</a>)  この動画をですね、右クリックします。<br>
(<a href="#" class="imk-cue" data-seek="1:52" translate="no">00:01:52</a>)  クイックアクション、このクイックアクションの中から、<br>
(<a href="#" class="imk-cue" data-seek="1:59" translate="no">00:01:59</a>)  あらかじめ自作した「字幕用に動画を分割する」これを選びます。<br>
(<a href="#" class="imk-cue" data-seek="2:20" translate="no">00:02:20</a>)  すると、分割する基本秒数を入れてください、と出てきます。<br>
(<a href="#" class="imk-cue" data-seek="2:28" translate="no">00:02:28</a>)  デフォルトは270秒になっています。つまり4分30秒になっています。<br>
(<a href="#" class="imk-cue" data-seek="2:36" translate="no">00:02:36</a>)  でもこれは4分30秒のところでバサッと分割するのではありません。<br>
(<a href="#" class="imk-cue" data-seek="2:44" translate="no">00:02:44</a>)  4分30秒付近で1秒間の無音になる部分を探して、<br>
(<a href="#" class="imk-cue" data-seek="2:51" translate="no">00:02:51</a>)  その無音が開始する場所で分割するようになっています。<br>
(<a href="#" class="imk-cue" data-seek="2:58" translate="no">00:02:58</a>)  分割ファイルはsplit_01_02...と、いうように分割されていきます。<br>
(<a href="#" class="imk-cue" data-seek="3:31" translate="no">00:03:31</a>)  えー、split_01、02、03と3つのファイルに分割されました。<br>
(<a href="#" class="imk-cue" data-seek="3:39" translate="no">00:03:39</a>)  で、あと一つ、offsets.txtというファイルも出来上がってます。<br>
(<a href="#" class="imk-cue" data-seek="3:46" translate="no">00:03:46</a>)  それではこのoffsets.txtというファイルを開いてみます。<br>
(<a href="#" class="imk-cue" data-seek="3:52" translate="no">00:03:52</a>)  すると、ここにですね、分割したファイルの開始時刻が入っています。<br>
(<a href="#" class="imk-cue" data-seek="4:02" translate="no">00:04:02</a>)  01、02、03、ここにズレ0秒、ズレ245.130秒<br>
(<a href="#" class="imk-cue" data-seek="4:09" translate="no">00:04:09</a>)  ズレ443.475秒となっています。<br>
(<a href="#" class="imk-cue" data-seek="4:19" translate="no">00:04:19</a>)  これは後で使うことになります。まあ、あることだけを覚えておいてください。<br>
(<a href="#" class="imk-cue" data-seek="4:25" translate="no">00:04:25</a>)  一応これを見て、確かにそのそれぞれが5分以内で分割されていることは確認できます。<br>
(<a href="#" class="imk-cue" data-seek="4:35" translate="no">00:04:35</a>)  一つ目が245秒、二つ目が、まあ200秒ぐらい、三つ目はですね、<br>
(<a href="#" class="imk-cue" data-seek="4:44" translate="no">00:04:44</a>)  全体で9分41秒、つまり9分41秒、443秒だから、えー、<br>
(<a href="#" class="imk-cue" data-seek="4:53" translate="no">00:04:53</a>)  7分、7x6=42、7分ちょっとのところで終わりますので、<br>
(<a href="#" class="imk-cue" data-seek="5:04" translate="no">00:05:04</a>)  あと残りが2分ちょっとですかね。その部分が03になるはずです。<br>
(<a href="#" class="imk-cue" data-seek="5:13" translate="no">00:05:13</a>)  確かに3つのファイルがですね、5分以内で分割されています。<br>
(<a href="#" class="imk-cue" data-seek="5:24" translate="no">00:05:24</a>)  えっと、次にですね、Gemで作ったこのVTT形式のコードを作成するプログラムですね、<br>
(<a href="#" class="imk-cue" data-seek="5:37" translate="no">00:05:37</a>)  これを開きます。これがそれです。<br>
(<a href="#" class="imk-cue" data-seek="5:45" translate="no">00:05:45</a>)  えー、このGemはですね、公開してますので、ブログにつけます。<br>
(<a href="#" class="imk-cue" data-seek="5:53" translate="no">00:05:53</a>)  モードはですね、あの、Proモードを選択してください。<br>
(<a href="#" class="imk-cue" data-seek="6:01" translate="no">00:06:01</a>)  で、下のボックス、ここにですね、今作った分割された動画をドロップします。<br>
(<a href="#" class="imk-cue" data-seek="6:11" translate="no">00:06:11</a>)  コピーアンドペーストします。まず一つ目コピー、<br>
(<a href="#" class="imk-cue" data-seek="6:18" translate="no">00:06:18</a>)  ここにペーストします。で、ここに入れるのはただこれだけです。<br>
(<a href="#" class="imk-cue" data-seek="6:30" translate="no">00:06:30</a>)  で、これでこの「Go」、送信の矢印を押してください。<br>
(<a href="#" class="imk-cue" data-seek="6:40" translate="no">00:06:40</a>)  そうすると作業が開始します。しばらく待ちます。<br>
(<a href="#" class="imk-cue" data-seek="7:33" translate="no">00:07:33</a>)  しばらく待ちますと、このようにVTTコードが出力されます。<br>
(<a href="#" class="imk-cue" data-seek="7:41" translate="no">00:07:41</a>)  これをコピーして、拡張子がVTTのファイルにペーストします。<br>
(<a href="#" class="imk-cue" data-seek="7:54" translate="no">00:07:54</a>)  えーと、これをコピーして、拡張子がVTTのファイルにペーストします。<br>
(<a href="#" class="imk-cue" data-seek="8:10" translate="no">00:08:10</a>)  あの、このVTTファイルは、あらかじめ用意しておいてください。<br>
(<a href="#" class="imk-cue" data-seek="8:17" translate="no">00:08:17</a>)  私はあの以前に作ったVTTファイルをですね、コピペして名前を変えて、<br>
(<a href="#" class="imk-cue" data-seek="8:28" translate="no">00:08:28</a>)  中身を削除して作っておきました。この３つですね。<br>
(<a href="#" class="imk-cue" data-seek="8:33" translate="no">00:08:33</a>)  それではこの01にですね、ペーストします。ここのコードをコピー。<br>
(<a href="#" class="imk-cue" data-seek="8:43" translate="no">00:08:43</a>)  えー、そして、ファイルにペースト。という形ですね。<br>
(<a href="#" class="imk-cue" data-seek="8:58" translate="no">00:08:58</a>)  保存。ということで、01番ができました。<br>
(<a href="#" class="imk-cue" data-seek="9:14" translate="no">00:09:14</a>)  同じようにしてですね、02以降も作るんですけども、<br>
(<a href="#" class="imk-cue" data-seek="9:21" translate="no">00:09:21</a>)  この同じセッションの中にですね、複数の動画があると、なかなかうまく受け付けてくれないので、<br>
(<a href="#" class="imk-cue" data-seek="9:30" translate="no">00:09:30</a>)  新しいセッションで同じことを繰り返すようにしてください。<br>
(<a href="#" class="imk-cue" data-seek="9:42" translate="no">00:09:42</a>)  こういう形で新しいセッションを開きます。そしてこの02ですね。これをコピーして、<br>
(<a href="#" class="imk-cue" data-seek="9:57" translate="no">00:09:57</a>)  貼り付けます。Proモードにして、<br>
(<a href="#" class="imk-cue" data-seek="10:12" translate="no">00:10:12</a>)  Proモードにして、送信します。<br>
(<a href="#" class="imk-cue" data-seek="10:38" translate="no">00:10:38</a>)  はい、コードができました。そしたらこれをコピーして、<br>
(<a href="#" class="imk-cue" data-seek="10:47" translate="no">00:10:47</a>)  02番のVTTファイルにペーストします。<br>
(<a href="#" class="imk-cue" data-seek="11:12" translate="no">00:11:12</a>)  同じように03番も作ります。<br>
(<a href="#" class="imk-cue" data-seek="11:39" translate="no">00:11:39</a>)  送信。<br>
(<a href="#" class="imk-cue" data-seek="11:58" translate="no">00:11:58</a>)  えーと、できましたのでコードをコピーして、<br>
(<a href="#" class="imk-cue" data-seek="12:06" translate="no">00:12:06</a>)  03VTTに貼り付けます。<br>
(<a href="#" class="imk-cue" data-seek="12:23" translate="no">00:12:23</a>)  こうして作るとお気づきのように、02以降のですね、動画の時刻は0秒からの開始になってしまっています。<br>
(<a href="#" class="imk-cue" data-seek="12:39" translate="no">00:12:39</a>)  秒ずらしの作業を行います。<br>
(<a href="#" class="imk-cue" data-seek="12:45" translate="no">00:12:45</a>)  この時に先ほど見たoffsets.txtの中の秒がずらし秒になってきます。<br>
(<a href="#" class="imk-cue" data-seek="12:58" translate="no">00:12:58</a>)  vttファイルの上で右クリックしてクイックアクションから「字幕時刻の秒ずらしを行う」を選びます。<br>
(<a href="#" class="imk-cue" data-seek="13:22" translate="no">00:13:22</a>)  ここでさっきの秒数を入れます。245.130秒。これ入れましてOKを押します。<br>
(<a href="#" class="imk-cue" data-seek="13:48" translate="no">00:13:48</a>)  timeshifted.vttができて245.130秒、つまり4分何秒かを加算したファイルができあがってます。<br>
(<a href="#" class="imk-cue" data-seek="14:13" translate="no">00:14:13</a>)  同じように03も秒ずらしを行います。今度は443.475。同じようにファイルができてます。<br>
(<a href="#" class="imk-cue" data-seek="14:51" translate="no">00:14:51</a>)  7分24秒ぐらいのところからのスタートに置き換わっています。<br>
(<a href="#" class="imk-cue" data-seek="15:04" translate="no">00:15:04</a>)  秒ずらしが済んだら結合したvttファイルを作ります。あらかじめbinded.vttを用意します。<br>
(<a href="#" class="imk-cue" data-seek="15:17" translate="no">00:15:17</a>)  この中に3つのvttファイルをコピペします。まず01は時刻ずれなしでそのままペーストします。<br>
(<a href="#" class="imk-cue" data-seek="15:45" translate="no">00:15:45</a>)  次に02_timeshifted.vttです。この連番以降のところをコピーして貼り付けます。<br>
(<a href="#" class="imk-cue" data-seek="16:18" translate="no">00:16:18</a>)  次に03_timeshifted.vtt、これも番号以降のところをコピーして貼り付けます。以上ですね。<br>
(<a href="#" class="imk-cue" data-seek="16:45" translate="no">00:16:45</a>)  全部1つのファイルにバインドされました。保存します。<br>
(<a href="#" class="imk-cue" data-seek="16:54" translate="no">00:16:54</a>)  ところがこれはすでにお気づきのように1からスタートした箇所が3箇所あるわけですね。<br>
(<a href="#" class="imk-cue" data-seek="17:08" translate="no">00:17:08</a>)  ここにもありますし、それから、<br>
(<a href="#" class="imk-cue" data-seek="17:15" translate="no">00:17:15</a>)  あ、ここにもあると。3箇所あります。<br>
(<a href="#" class="imk-cue" data-seek="17:18" translate="no">00:17:18</a>)  これを連番が全部通しで1番から開始するように、番号の振り直しをします。<br>
(<a href="#" class="imk-cue" data-seek="17:37" translate="no">00:17:37</a>)  このbinded.vttの上で右クリックして、<br>
(<a href="#" class="imk-cue" data-seek="17:41" translate="no">00:17:41</a>)  クイックアクションの中から、<br>
(<a href="#" class="imk-cue" data-seek="17:47" translate="no">00:17:47</a>)  この「字幕VTTの連番を付け直す」、これを選びます。<br>
(<a href="#" class="imk-cue" data-seek="17:58" translate="no">00:17:58</a>)  すると、renumbered.vttが出来上がります。<br>
(<a href="#" class="imk-cue" data-seek="18:07" translate="no">00:18:07</a>)  これは1番からですね。ずっと連番で、<br>
(<a href="#" class="imk-cue" data-seek="18:18" translate="no">00:18:18</a>)  67番までですか。ここまで繋がってます。<br>
(<a href="#" class="imk-cue" data-seek="18:26" translate="no">00:18:26</a>)  それで言葉遣いの修正とかテキストの修正は、ここまで形が整った後で行うのがいいと思います。<br>
(<a href="#" class="imk-cue" data-seek="18:38" translate="no">00:18:38</a>)  地味にコツコツとやる方法ではありますが、仕組みとして分かりやすいので作業のストレスは感じません。<br>
(<a href="#" class="imk-cue" data-seek="18:51" translate="no">00:18:51</a>)  この方法が優れているのは、GeminiのGems、これの文字起こしの精度が非常に高いということです。<br>
(<a href="#" class="imk-cue" data-seek="19:03" translate="no">00:19:03</a>)  手直しするところはとても少ないです。満足できると思います。<br>
(<a href="#" class="imk-cue" data-seek="19:10" translate="no">00:19:10</a>)  以上、Gemsを使ったVTTコード作成の紹介でした。<br>
(<a href="#" class="imk-cue" data-seek="19:17" translate="no">00:19:17</a>)  コード類はブログ記事に掲載しますのでご利用ください。<br>
</p> </details>
<style>
details { font: 16px "Open Sans", Calibri, sans-serif; width: 100%; }
details > summary { padding: 2px 6px; width: 100%; background-color: #ddd; border: none; box-shadow: 3px 3px 4px black; cursor: pointer; list-style: none; }
details > p { font: 14px "Open Sans", Calibri, sans-serif; height:150px; overflow: scroll; background-color: #EDF7FF; padding: 2px 6px; margin: 0; box-shadow: 3px 3px 4px black; }
</style>

  </div>

  <script src="https://player.vimeo.com/api/player.js"></script>

  <script>
  (function(){
    var me = document.currentScript;
    var wrapper = me ? me.closest('.sc-vimeo-embed') : null;

    var target = wrapper ? wrapper : document;
    var iframe = target.querySelector('iframe');
    if (!iframe || !window.Vimeo || !Vimeo.Player) return;

    var player = new Vimeo.Player(iframe);

    /* --- 1. 確実に一時停止してから別ページを開く処理 --- */
    window.stopVimeoBeforeNavigate = function(event, link) {
      event.preventDefault(); 
      player.pause().then(function() {
        setTimeout(function() {
           window.open(link.href, link.target);
        }, 50);
      }).catch(function() {
        window.open(link.href, link.target);
      });
    };

    /* --- 2. 字幕のON/OFF制御（Vimeo API仕様） --- */
    var currentMode = "hidden";
    
    function useNormalMode() {
        currentMode = "hidden";
        player.disableTextTrack().catch(function(e){});
    }
    
    function useSpecialMode() {
        currentMode = "showing";
        // 日本語の subtitles が無ければ captions を探す安全設計
        player.enableTextTrack('ja', 'subtitles').catch(function() {
            player.enableTextTrack('ja', 'captions').catch(function() {});
        });
    }

    // ロード直後は枠内字幕を非表示にする
    player.ready().then(function() {
        useNormalMode();
    });

    // Vimeoプレーヤーの全画面・PiPイベントを監視して字幕を切り替え
    player.on('fullscreenchange', function(data) {
        if (data.fullscreen) useSpecialMode();
        else useNormalMode();
    });
    player.on('enterpictureinpicture', function() {
        useSpecialMode();
    });
    player.on('leavepictureinpicture', function() {
        useNormalMode();
    });

    /* --- 3. 字幕リストの初期化（自動梱包とデフォルト展開） --- */
    var checks = 0;
    var initTimer = setInterval(function(){
        var listContainer = target.querySelector('details > p');
        if (listContainer) {
            initSubtitles(listContainer);
            clearInterval(initTimer);
        }
        checks++;
        if (checks > 20) clearInterval(initTimer); // 10秒経ったら監視終了
    }, 500);

    function initSubtitles(listContainer) {
        // デフォルトで開く
        var detailsEl = target.querySelector("details");
        if (detailsEl) {
            detailsEl.open = true; 
            var summaryEl = detailsEl.querySelector("summary");
            if (summaryEl) summaryEl.textContent = "字幕(シーン)はここをクリック";
        }

        // 行ごとに見えない箱(span)で梱包
        if (!listContainer.dataset.formatted) {
            var html = listContainer.innerHTML;
            var lines = html.split(/<br\s*\/?>/i);
            var newHtml = "";
            for(var j=0; j<lines.length; j++) {
                if(lines[j].trim() === "") continue;
                newHtml += "<span class='imk-line'>" + lines[j] + "</span><br>";
            }
            listContainer.innerHTML = newHtml;
            listContainer.dataset.formatted = "true";
        }
    }

    /* --- 4. クリックシーク機能 --- */
    function parseTs(ts) {
      if (!ts) return null;
      var t = ts.trim();
      var parts = t.split(':').map(function(v){ return parseInt(v, 10); });
      if (parts.length === 2 && parts.every(Number.isFinite)) {
        return parts[0] * 60 + parts[1];
      } else if (parts.length === 3 && parts.every(Number.isFinite)) {
        return parts[0] * 3600 + parts[1] * 60 + parts[2];
      }
      return null;
    }

    target.addEventListener('click', function(e) {
      var a = e.target.closest('a.imk-cue');
      if (!a) return;
      e.preventDefault();
      var sec = null;
      if (a.dataset.seconds) {
        sec = Number(a.dataset.seconds);
      } else if (a.dataset.seek) {
        sec = parseTs(a.dataset.seek);
      }
      if (sec !== null && Number.isFinite(sec)) {
        player.setCurrentTime(sec).then(function(){ player.play(); }).catch(function(){});
      }
    });

    /* --- 5. 同期ハイライトと自動スクロール --- */
    player.on('timeupdate', function(data) {
      // Vimeoプレーヤーが勝手に字幕を出していたら隠す（最強ガード）
      player.getTextTracks().then(function(tracks) {
          var activeTrack = tracks.find(function(t){ return t.mode === 'showing'; });
          if (currentMode === "hidden" && activeTrack) {
              useNormalMode();
          }
      }).catch(function(){});

      var currentTime = data.seconds;
      var listContainer = target.querySelector('details > p');
      if (!listContainer) return;

      var cues = listContainer.querySelectorAll('a.imk-cue');
      if (cues.length === 0) return;

      var activeA = null;
      for (var i = 0; i < cues.length; i++) {
        var sec = null;
        if (cues[i].dataset.seconds) {
            sec = Number(cues[i].dataset.seconds);
        } else if (cues[i].dataset.seek) {
            sec = parseTs(cues[i].getAttribute('data-seek'));
        }
        if (sec !== null && currentTime >= sec - 0.5) {
          activeA = cues[i];
        } else if (sec > currentTime) {
          break;
        }
      }

      if (activeA) {
          var activeLine = activeA.closest(".imk-line");
          if (!activeLine) activeLine = activeA;

          if (activeLine.classList.contains("active-hl")) return;

          // 全行の色を徹底的にリセット
          var allLines = listContainer.querySelectorAll(".imk-line");
          for(var k=0; k<allLines.length; k++) {
              allLines[k].classList.remove("active-hl");
              allLines[k].removeAttribute("style");
          }
          var allLinks = listContainer.querySelectorAll("a");
          for(var m=0; m<allLinks.length; m++) {
              allLinks[m].classList.remove("active-hl");
              allLinks[m].removeAttribute("style");
          }

          // 新しい行に赤文字・黄色背景を直接塗る
          activeLine.classList.add("active-hl");
          activeLine.style.setProperty("background-color", "#ffff00", "important");
          activeLine.style.setProperty("color", "red", "important");
          activeLine.style.setProperty("font-weight", "normal", "important");
          
          var newLinks = activeLine.querySelectorAll("a");
          for(var n=0; n<newLinks.length; n++) {
              newLinks[n].style.setProperty("color", "red", "important");
              newLinks[n].style.setProperty("text-decoration", "none", "important");
          }

          // スクロール処理
          if (listContainer.offsetParent !== null) {
              var containerRect = listContainer.getBoundingClientRect();
              var activeRect = activeLine.getBoundingClientRect();
              var targetScroll = listContainer.scrollTop + (activeRect.top - containerRect.top) - (listContainer.clientHeight / 2) + (activeLine.clientHeight / 2);
              listContainer.scrollTo({
                  top: targetScroll,
                  behavior: "smooth"
              });
          }
      }
    });
  })();
  </script>

  <style>
  .sc-vimeo-embed .iframe-wrapper {
    position: relative;
    padding-bottom: 56.25%;
    height: 0;
    overflow: visible;
  }
  .sc-vimeo-embed .iframe-wrapper iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }

  /* 行梱包時の基本スタイル（干渉防止のためクラス内で指定） */
  .sc-vimeo-embed .imk-line {
      display: inline-block;
      width: 100%;
      border-radius: 2px;
      transition: background-color 0.1s;
  }

  /* ▼ 字幕一覧（details）の見た目調整 */
  .sc-vimeo-embed details > p {
    font-size: 14px !important;
    line-height: 1.6;
    height: 200px !important; 
    overflow: auto;
    background-color: #EDF7FF;
    padding: 2px 6px;
    margin: 0;
    box-shadow: 3px 3px 4px black;
    position: relative; 
  }
  .sc-vimeo-embed details > summary {
    font-size: 14px !important;
    padding: 2px 6px;
    width: 100%;
    background-color: #ddd;
    border: none;
    box-shadow: 3px 3px 4px black;
    cursor: pointer;
    list-style: none;
  }
  </style>
</div>



<div class="wp-block-cocoon-blocks-toggle-box-1 toggle-wrap toggle-box block-box not-nested-style cocoon-block-toggle"><input id="toggle-checkbox-202603290607120" class="toggle-checkbox" type="checkbox"/><label class="toggle-button" for="toggle-checkbox-202603290607120"><strong><span class="marker">コードと要約</span><span class="marker">(クリック)</span></strong></label><div class="toggle-content">
<figure class="wp-block-flexible-table-block-table"><table class="has-fixed-layout"><tbody><tr><td>要約：<br><strong>「VTT作成用に動画を分割する」ワークフロー</strong>は、ユーザーが指定した基本秒数を基に、動画を無音区間で自動分割し、VTTの「秒ずらし」に役立つオフセット記録を生成します。<code>ffmpeg</code>とPythonスクリプトを連携させ、再エンコードなしで高速分割します。<br><strong>「字幕時刻の秒ずらしを行う」ワークフロー</strong>は、選択したVTTファイルの全タイムスタンプを、ユーザーが入力した秒数だけシフト（前後にずらす）させ、新しいVTTファイルを出力します。<code>awk</code>を用いて精密な時間計算を行います。<br><strong>「VTTの連番を付け直す」ワークフロー</strong>は、VTTファイル内の古い連番や不要なヘッダを削除し、字幕ブロックに正しい連番を振り直して整理されたVTTファイルを生成します。<br>これらのワークフローは、それぞれ動画の分割、字幕の時間調整、字幕ファイルの整理という異なる課題に対応し、VTT作成・管理作業を自動化・簡素化することを目的としています。</td></tr><tr><td><a href="https://imakat.com/script_list/?pubtxt=無料アカウント向け_動画からVTTを生成する_pub.txt" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=zrU95MiY.png" alt="" style="width:120px; height:auto;"></a></td></tr><tr><td><a rel="noopener" target="_blank" href="https://gemini.google.com/gem/12QYaKlTweyQxeHvd95UIxfLO7y0JOVOw?usp=sharing">添付の動画の音声から字幕用のvtt形式のコードを出力します(Gem共有)。<span class="fa fa-external-link external-icon anchor-icon"></span></a></td></tr><tr><td>公開スクリプトに関するお問い合わせは以下へ↓</td></tr><tr><td><a rel="noopener" target="_blank" href="https://gemini.google.com/gem/1Dp-NLSA5j5OXE3B1Ki2IaBRCvq4CGa6t?usp=sharing"><img decoding="async" src="https://imakat.com/rd.php?id=s7BMZHhB.png" alt="" style="width:120px; height:auto;"></a></td></tr></tbody></table></figure>
</div></div>



<h2 class="wp-block-heading">ポイント解説</h2>



<h3 class="wp-block-heading"><strong>解決すべき課題：Geminiの「5分の壁」</strong></h3>



<p>Geminiに動画を読み込ませて文字起こしをする際、特に無料アカウントでは「動画は5分以内」という制限があります 。 今回紹介するワークフローは、事前の「動画分割」と、事後の「タイムスタンプ調整（秒ずらし）」を組み合わせることで、この壁をストレスなく突破します。<br>有料会員でも使用制限を超えた時で、急いでいる場合などは、この方式は有用です。</p>



<h3 class="wp-block-heading"><strong><strong>長時間の動画からVTT字幕を生成する6つのステップ</strong></strong></h3>



<p>ここでは、例として10分弱の動画に字幕をつける手順を解説します 。</p>



<h4 class="wp-block-heading"><strong><strong>1. 動画の準備</strong></strong></h4>



<p>まずは手元に、字幕を作成したい元の動画ファイルを用意します 。</p>



<h4 class="wp-block-heading"><strong>2. 基本秒数の設定と動画の分割（クイックアクション）</strong></h4>



<p>動画を5分以内のパーツに分けます 。</p>



<ul class="wp-block-list">
<li>用意した動画を右クリックしクイックアクションから自作の「字幕用に動画を分割する」を選択します 。<br></li>



<li>分割する基本秒数を入力します（デフォルトは270秒＝4分30秒です） 。<br></li>



<li><strong>ポイント:</strong> 単純に時間でバサッと切るのではなく、指定時間付近の「1秒間の無音部分」を探し、キリの良いところで自動分割されるように工夫しています 。<br></li>



<li>実行すると、split_01、02…という分割動画と同時に、offsets.txtというファイルが生成されます 。このテキストには「245.130秒」といった分割時のズレ（累計秒数）が記録されており、後で使います 。<br></li>
</ul>



<h4 class="wp-block-heading"><strong><strong>3. Gemini（Gem）によるVTT字幕作成（手動）</strong></strong></h4>



<p>いよいよAIに文字起こしを依頼します。公開している専用のGemを使用します（※リンクは「コードと要約」に掲載します） 。</p>



<ul class="wp-block-list">
<li>Gemを開き、「Proモード」を選択します 。<br></li>



<li>下部のメッセージボックスに、分割した最初の動画（01）をドロップ（またはコピペ）して送信します 。<br></li>



<li>しばらく待つと、タイムスタンプ付きのVTTコードが出力されます 。<br></li>



<li>出力されたコードをコピーし、あらかじめ用意しておいた空のVTTファイル（例：01.vtt）にペーストして保存します 。<br></li>



<li><strong>注意点:</strong> 02以降の動画を処理する際は、AIが混乱するのを防ぐため、必ず「新しいセッション（チャット）」を開いてから同じ手順を繰り返してください 。<br></li>
</ul>



<h4 class="wp-block-heading"><strong>4. VTTの秒ずらし（クイックアクション）</strong></h4>



<p>出力された02番以降のVTTファイルは、動画の開始時刻が「0秒」にリセットされてしまっています 。これを元の時間軸に戻します。</p>



<ul class="wp-block-list">
<li>対象のVTTファイル（02など）を右クリックし、クイックアクションから「字幕時刻の秒ずらしを行う」を選びます 。<br></li>



<li>手順2で生成されたoffsets.txtに記載されている秒数（例：245.130）を入力し、OKを押します 。<br></li>



<li>正しい時間にシフトされた _timeshifted.vtt というファイルが新しく作成されます 。<br></li>
</ul>



<h4 class="wp-block-heading"><strong>5. VTTファイルの結合（手動）</strong></h4>



<p>それぞれの時間軸が整ったら、1つのファイルにまとめます。</p>



<ul class="wp-block-list">
<li>結合用の空ファイル（binded.vtt(※1)）を用意します 。<br></li>



<li>01.vttの中身をそのままペーストします 。<br></li>



<li>続けて、02_timeshifted.vtt、03_timeshifted.vtt の連番以降のテキスト部分を順番にコピーして下に追加し、保存します 。<br></li>
</ul>



<p>※1:あとで気付きました。bindedは間違った英語です。boundあるいはconbinedというのが適切です。</p>



<h4 class="wp-block-heading"><strong><strong><strong>6. 連番の振り直しと整理（クイックアクション）</strong></strong></strong></h4>



<p>結合したファイルは、字幕の通し番号（連番）が「1」から始まる箇所が複数混在してしまっています 。これを綺麗に整えます。</p>



<ul class="wp-block-list">
<li>binded.vtt を右クリックし、クイックアクションから「字幕VTTの連番を付け直す」を選択します 。<br></li>



<li>これにより、最初から最後まで番号が正しく振り直された完成版 renumbered.vtt が出来上がります 。<br></li>
</ul>



<h3 class="wp-block-heading">まとめ</h3>



<p>言葉遣いやテキストの微修正は、このように全体の形が綺麗に整った最後に行うのがおすすめです 。</p>



<p>地味にコツコツと進める手作業の部分もありますが、仕組みが非常に分かりやすいため、作業中のストレスはほとんど感じません 。<strong>Gem(ChatGPTもそう)の文字起こし精度が抜群に高いのは、単なる音声からの文字起こしだけでなく、動画内の視覚情報（映像）例えば、動画に登場する文字、人物の動きなどを認識するという、マルチモーダル処理を行っているため</strong>です。26年3月現在、CapCut、Vrew、Premiere Pro、Davinci Resolve、Filmoraの文字起こしは「映像情報」を加味せず、純粋に「音声データ」のみに依存しています。おかげで、Gemの場合は、手直しが非常に少なくて済むのが最大のメリットです 。</p>



<p>以上</p>



<p></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">28762</post-id>	</item>
		<item>
		<title>「字幕かんたん作成」〜無音声動画に解説字幕をサクッと付ける方法(Automator+AppleScript)</title>
		<link>https://imakat.com/2025/08/28/27063/</link>
		
		<dc:creator><![CDATA[imakat]]></dc:creator>
		<pubDate>Thu, 28 Aug 2025 09:32:54 +0000</pubDate>
				<category><![CDATA[字幕作成]]></category>
		<category><![CDATA[デジタル]]></category>
		<category><![CDATA[ものづくり]]></category>
		<category><![CDATA[vtt]]></category>
		<category><![CDATA[QuickTimePlayer]]></category>
		<category><![CDATA[TextEdit]]></category>
		<category><![CDATA[HUD]]></category>
		<guid isPermaLink="false">https://imakat.com/?p=27063</guid>

					<description><![CDATA[これまで動画の字幕作成については、何度か記事を投稿してきましたが、その中で感じた課題のいくつかを克服するアプリを、自作しましたので紹介します。 別の投稿で紹介したいと思いますが、字幕起こしを伴う字幕作成サービスについては [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p>これまで動画の字幕作成については、何度か記事を投稿してきましたが、その中で感じた課題のいくつかを克服するアプリを、自作しましたので紹介します。</p>



<p>別の投稿で紹介したいと思いますが、字幕起こしを伴う字幕作成サービスについては日進月歩でして、どんどん高品質になっています。大きく分けると、ローカルで処理する方法（大抵は無料でできる）と外部サーバーで処理する方法（大抵は使用料課金かサブスク提供)がありまして、外部サーバー利用の方については激しい競争下にあるためかなり高品質で、生成AI系企業のサービスが群を抜いています。</p>



<p>最近、AIの進展で、動画をアップロードするだけで音声を取り出しその内容をAIに理解させることができるようになってはきましたが、やはり字幕ファイルによる文字情報で内容を理解させる方が圧倒的に迅速で正確です。しかも動画からの読み込みは多大なリソースを消費するので、追加料金も発生するかも知れません。そんな意味で、ブログ投稿をAIに学習させる場合も、動画には字幕ファイルを別添して貼り付けるようにして、字幕ファイルからの情報吸い上げを重視すべきだと私は思います。</p>



<p>そんな中で、ここで紹介する方法は、<strong>無音声の動画に解説用の字幕をサクッと付ける</strong>場合、に役立つものです。</p>


<div class="sc-vimeo-embed">
  <p style="font-size: 14px;" class="sc-link">
    <a href="https://imakat.com/vm5?movid=1176379255" target="_blank" onclick="stopVimeoBeforeNavigate(event, this)">
      動画を別ページで表示(ここをクリック)
    </a>
  </p>

  <div class="iframe-wrapper">
    <iframe
      src="https://player.vimeo.com/video/1176379255?title=0&byline=0&portrait=0&controls=1&speed=1&texttrack=ja&dnt=1&loop=0"
      frameborder="0"
      allow="autoplay; fullscreen; picture-in-picture"
      allowfullscreen></iframe>
  </div>

  <div class="dr-vimeo-sublist">
    <details translate="yes"><summary translate="yes">字幕一覧(クリック)</summary> <p translate="yes">
(<a href="#" class="imk-cue" data-seek="0:00" translate="no">00:00:00</a>) 1) 〜字幕かんたん作成〜<br>
(<a href="#" class="imk-cue" data-seek="0:20" translate="no">00:00:20</a>) 2) 今回は、Macで簡単に、動画の字幕ファイルを作成できる『字幕かんたん作成』これを紹介します。<br>
(<a href="#" class="imk-cue" data-seek="0:35" translate="no">00:00:35</a>) 3) 動画に字幕を付けるのに、編集ソフトで、コツコツと、タイムスタンプを入れるのは、とても大変ですよね。<br>
(<a href="#" class="imk-cue" data-seek="0:51" translate="no">00:00:51</a>) 4) このアプリを使えば、QuickTimePlayerで動画を再生しながら、簡単に、字幕を打ち込んでいけます。<br>
(<a href="#" class="imk-cue" data-seek="1:00" translate="no">00:01:00</a>) 5) お金は掛かりません。<br>
(<a href="#" class="imk-cue" data-seek="1:03" translate="no">00:01:03</a>) 6) Macに備わった標準アプリだけで動きます。<br>
(<a href="#" class="imk-cue" data-seek="1:12" translate="no">00:01:12</a>) 7) 通常の字幕作成では、動画の再生時間を確認して、開始時刻と終了時刻を、VTTファイルへ入力します。<br>
(<a href="#" class="imk-cue" data-seek="1:27" translate="no">00:01:27</a>) 8) サンプルをお見せします。<br>
(<a href="#" class="imk-cue" data-seek="1:33" translate="no">00:01:33</a>) 9) 例えば、このような文字列があります。<br>
(<a href="#" class="imk-cue" data-seek="1:37" translate="no">00:01:37</a>) 10) これはVTTファイルです。<br>
(<a href="#" class="imk-cue" data-seek="1:41" translate="no">00:01:41</a>) 11) 最初に、順番が入ります。　　<br>
(<a href="#" class="imk-cue" data-seek="1:46" translate="no">00:01:46</a>) 12) 次に、時　分　秒　ミリ秒、この基準に従った開始時刻<br>
(<a href="#" class="imk-cue" data-seek="1:54" translate="no">00:01:54</a>) 13) それと、同じくその基準の終了時刻を入れます。<br>
(<a href="#" class="imk-cue" data-seek="2:01" translate="no">00:02:01</a>) 14) 真ん中のところに、スペース１つ、--不等号 またひとつスペースを入れます。<br>
(<a href="#" class="imk-cue" data-seek="2:13" translate="no">00:02:13</a>) 15) その下にこうしたテキスト行を入れます。<br>
(<a href="#" class="imk-cue" data-seek="2:19" translate="no">00:02:19</a>) 16) これがVTT記述の基本形です。<br>
(<a href="#" class="imk-cue" data-seek="2:25" translate="no">00:02:25</a>) 17) このように自分でTextEditに打てば、正確にできるのですが、　　<br>
(<a href="#" class="imk-cue" data-seek="2:34" translate="no">00:02:34</a>) 18) 手間が多く、時間もかかってしまいます。<br>
(<a href="#" class="imk-cue" data-seek="2:43" translate="no">00:02:43</a>) 19) そこで開発したのが、この『字幕かんたん作成』です。<br>
(<a href="#" class="imk-cue" data-seek="2:50" translate="no">00:02:50</a>) 20) AutomatorとAppleScript_Objective-Cを組み合わせて、<br>
(<a href="#" class="imk-cue" data-seek="2:57" translate="no">00:02:57</a>) 21) QuickTimePlayerとTextEditを連携させる、<br>
(<a href="#" class="imk-cue" data-seek="3:03" translate="no">00:03:03</a>) 22) そのことで、シンプルに、効率よく、字幕ファイルを作ることができます。<br>
(<a href="#" class="imk-cue" data-seek="3:14" translate="no">00:03:14</a>) 23) その仕組みをフロー図によって説明します。<br>
(<a href="#" class="imk-cue" data-seek="3:29" translate="no">00:03:29</a>) 24) まず、FinderでVTTファイルを右クリックします。<br>
(<a href="#" class="imk-cue" data-seek="3:41" translate="no">00:03:41</a>) 25) するとクイックアクションの中にある、今回のアプリ 「字幕かんたん作成」が起動します。<br>
(<a href="#" class="imk-cue" data-seek="3:51" translate="no">00:03:51</a>) 26) スクリプトが動作し、黄色の字幕表示画面(HUDと呼びますが)それと、　<br>
(<a href="#" class="imk-cue" data-seek="4:00" translate="no">00:04:00</a>) 27) 入力Boxが表示されます。<br>
(<a href="#" class="imk-cue" data-seek="4:09" translate="no">00:04:09</a>) 28) 字幕の入力先は、macOS標準のTextEditを使います。 <br>
(<a href="#" class="imk-cue" data-seek="4:17" translate="no">00:04:17</a>) 29) 入力したテキストは、QuickTimePlayerの再生位置の時刻、タイムスタンプ、それらと一緒にVTTファイルに記入されます。<br>
(<a href="#" class="imk-cue" data-seek="4:33" translate="no">00:04:33</a>) 30) QuickTimePlayerは再生位置を提供し、NSTimerが、それに対応する時刻を、定期的にゲットします。　<br>
(<a href="#" class="imk-cue" data-seek="4:48" translate="no">00:04:48</a>) 31) 終了する場合は、終了ボタンを押すと、タイマーが止まり、HUDが閉じ、メモリーが解放されて、処理が終了します。<br>
(<a href="#" class="imk-cue" data-seek="5:08" translate="no">00:05:08</a>) 32) それでは、実際の動きをご覧ください。 <br>
(<a href="#" class="imk-cue" data-seek="5:13" translate="no">00:05:13</a>) 33) 動画の例として、「ガラポンTVの故障」を取り上げます。<br>
(<a href="#" class="imk-cue" data-seek="5:21" translate="no">00:05:21</a>) 34) 一度、動画だけをみてください。（約1分） <br>
(<a href="#" class="imk-cue" data-seek="6:28" translate="no">00:06:28</a>) 35) 動画を見ただけでは、何を伝えたいのか、さっぱりわかりませんね。<br>
(<a href="#" class="imk-cue" data-seek="6:36" translate="no">00:06:36</a>) 36) そこで、字幕を、作成していきます。<br>
(<a href="#" class="imk-cue" data-seek="6:43" translate="no">00:06:43</a>) 37) それでは、作業をやってみます。<br>
(<a href="#" class="imk-cue" data-seek="6:49" translate="no">00:06:49</a>) 38) まず、動画を右上の方に置いておきます。<br>
(<a href="#" class="imk-cue" data-seek="6:57" translate="no">00:06:57</a>) 39) すでにvttファイル名は付けてありますが、中身をクリアして作業をしてみます。<br>
(<a href="#" class="imk-cue" data-seek="7:05" translate="no">00:07:05</a>) 40) このvttファイルの上で、右クリックして、クイックアクションで、「字幕かんたん作成」を立ち上げます。<br>
(<a href="#" class="imk-cue" data-seek="7:32" translate="no">00:07:32</a>) 41) こんなように立ち上がります。<br>
(<a href="#" class="imk-cue" data-seek="7:36" translate="no">00:07:36</a>) 42) このHUDをQuickTimePlayerの下に置いて、　<br>
(<a href="#" class="imk-cue" data-seek="7:42" translate="no">00:07:42</a>) 43) 実際に、テキストを入れていきます。<br>
(<a href="#" class="imk-cue" data-seek="8:03" translate="no">00:08:03</a>) 44) ガラポンTVが異常です。全ランプが点滅を繰り返しています。<br>
(<a href="#" class="imk-cue" data-seek="8:18" translate="no">00:08:18</a>) 45) このように打ってOKを押します。<br>
(<a href="#" class="imk-cue" data-seek="8:26" translate="no">00:08:26</a>) 46) 継続秒数を入れます。<br>
(<a href="#" class="imk-cue" data-seek="8:41" translate="no">00:08:41</a>) 47) 1番目が出来上がります。<br>
(<a href="#" class="imk-cue" data-seek="8:55" translate="no">00:08:55</a>) 48) 背面の電源をOFFにしました。<br>
(<a href="#" class="imk-cue" data-seek="9:11" translate="no">00:09:11</a>) 49) OK<br>
(<a href="#" class="imk-cue" data-seek="9:13" translate="no">00:09:13</a>) 50) 4秒<br>
(<a href="#" class="imk-cue" data-seek="9:17" translate="no">00:09:17</a>) 51) 2番目が入ります。<br>
(<a href="#" class="imk-cue" data-seek="9:20" translate="no">00:09:20</a>) 52) HUDにも表示されます。<br>
(<a href="#" class="imk-cue" data-seek="9:40" translate="no">00:09:40</a>) 53) 外付けHDDを外しました。<br>
(<a href="#" class="imk-cue" data-seek="10:02" translate="no">00:10:02</a>) 54) 前の部分で、説明を入れるのを忘れたとしても、戻ることができます。<br>
(<a href="#" class="imk-cue" data-seek="10:16" translate="no">00:10:16</a>) 55) この場所で、ランプは消えました、と入れます。<br>
(<a href="#" class="imk-cue" data-seek="10:35" translate="no">00:10:35</a>) 56) 3番目として、ランプが消えた、が飛び込みます。<br>
(<a href="#" class="imk-cue" data-seek="10:46" translate="no">00:10:46</a>) 57) このような形で、入力が終了し、再生した時に、字幕がタイミングよく表示されることを確認する必要があります。その後で実際は終了します。<br>
(<a href="#" class="imk-cue" data-seek="11:02" translate="no">00:11:02</a>) 58) それでは、動画と、完成した字幕を、同時に表示してみましょう。<br>
(<a href="#" class="imk-cue" data-seek="11:17" translate="no">00:11:17</a>) 59) 字幕があることによって、その、ガラポンTVが故障している、そのように判断した理由が、より明確に、伝わるようになります。<br>
(<a href="#" class="imk-cue" data-seek="12:10" translate="no">00:12:10</a>) 60) この後、ガラポンTV社に報告して、迅速に、交換が完了しました。<br>
(<a href="#" class="imk-cue" data-seek="12:24" translate="no">00:12:24</a>) 61) このように『字幕かんたん作成』は、AutomatorとAppleScript_Objective-Cを使って、<br>
(<a href="#" class="imk-cue" data-seek="12:33" translate="no">00:12:33</a>) 62) QuickTimePlayerとTextEditを組み合わせることによって、 　<br>
(<a href="#" class="imk-cue" data-seek="12:40" translate="no">00:12:40</a>) 63) 面倒な字幕作成を、シンプルに、効率的に、してくれます。 <br>
(<a href="#" class="imk-cue" data-seek="12:46" translate="no">00:12:46</a>) 64) このスクリプトは、ブログ内で公開します。<br>
(<a href="#" class="imk-cue" data-seek="12:50" translate="no">00:12:50</a>) 65) 字幕を、できるだけ手軽に付けたい、そう思う方は、ぜひ活用してみてください。<br>
</p> </details>
<style>
details { font: 16px "Open Sans", Calibri, sans-serif; width: 100%; }
details > summary { padding: 2px 6px; width: 100%; background-color: #ddd; border: none; box-shadow: 3px 3px 4px black; cursor: pointer; list-style: none; }
details > p { font: 14px "Open Sans", Calibri, sans-serif; height:150px; overflow: scroll; background-color: #EDF7FF; padding: 2px 6px; margin: 0; box-shadow: 3px 3px 4px black; }
</style>

  </div>

  <script src="https://player.vimeo.com/api/player.js"></script>

  <script>
  (function(){
    var me = document.currentScript;
    var wrapper = me ? me.closest('.sc-vimeo-embed') : null;

    var target = wrapper ? wrapper : document;
    var iframe = target.querySelector('iframe');
    if (!iframe || !window.Vimeo || !Vimeo.Player) return;

    var player = new Vimeo.Player(iframe);

    /* --- 1. 確実に一時停止してから別ページを開く処理 --- */
    window.stopVimeoBeforeNavigate = function(event, link) {
      event.preventDefault(); 
      player.pause().then(function() {
        setTimeout(function() {
           window.open(link.href, link.target);
        }, 50);
      }).catch(function() {
        window.open(link.href, link.target);
      });
    };

    /* --- 2. 字幕のON/OFF制御（Vimeo API仕様） --- */
    var currentMode = "hidden";
    
    function useNormalMode() {
        currentMode = "hidden";
        player.disableTextTrack().catch(function(e){});
    }
    
    function useSpecialMode() {
        currentMode = "showing";
        // 日本語の subtitles が無ければ captions を探す安全設計
        player.enableTextTrack('ja', 'subtitles').catch(function() {
            player.enableTextTrack('ja', 'captions').catch(function() {});
        });
    }

    // ロード直後は枠内字幕を非表示にする
    player.ready().then(function() {
        useNormalMode();
    });

    // Vimeoプレーヤーの全画面・PiPイベントを監視して字幕を切り替え
    player.on('fullscreenchange', function(data) {
        if (data.fullscreen) useSpecialMode();
        else useNormalMode();
    });
    player.on('enterpictureinpicture', function() {
        useSpecialMode();
    });
    player.on('leavepictureinpicture', function() {
        useNormalMode();
    });

    /* --- 3. 字幕リストの初期化（自動梱包とデフォルト展開） --- */
    var checks = 0;
    var initTimer = setInterval(function(){
        var listContainer = target.querySelector('details > p');
        if (listContainer) {
            initSubtitles(listContainer);
            clearInterval(initTimer);
        }
        checks++;
        if (checks > 20) clearInterval(initTimer); // 10秒経ったら監視終了
    }, 500);

    function initSubtitles(listContainer) {
        // デフォルトで開く
        var detailsEl = target.querySelector("details");
        if (detailsEl) {
            detailsEl.open = true; 
            var summaryEl = detailsEl.querySelector("summary");
            if (summaryEl) summaryEl.textContent = "字幕(シーン)はここをクリック";
        }

        // 行ごとに見えない箱(span)で梱包
        if (!listContainer.dataset.formatted) {
            var html = listContainer.innerHTML;
            var lines = html.split(/<br\s*\/?>/i);
            var newHtml = "";
            for(var j=0; j<lines.length; j++) {
                if(lines[j].trim() === "") continue;
                newHtml += "<span class='imk-line'>" + lines[j] + "</span><br>";
            }
            listContainer.innerHTML = newHtml;
            listContainer.dataset.formatted = "true";
        }
    }

    /* --- 4. クリックシーク機能 --- */
    function parseTs(ts) {
      if (!ts) return null;
      var t = ts.trim();
      var parts = t.split(':').map(function(v){ return parseInt(v, 10); });
      if (parts.length === 2 && parts.every(Number.isFinite)) {
        return parts[0] * 60 + parts[1];
      } else if (parts.length === 3 && parts.every(Number.isFinite)) {
        return parts[0] * 3600 + parts[1] * 60 + parts[2];
      }
      return null;
    }

    target.addEventListener('click', function(e) {
      var a = e.target.closest('a.imk-cue');
      if (!a) return;
      e.preventDefault();
      var sec = null;
      if (a.dataset.seconds) {
        sec = Number(a.dataset.seconds);
      } else if (a.dataset.seek) {
        sec = parseTs(a.dataset.seek);
      }
      if (sec !== null && Number.isFinite(sec)) {
        player.setCurrentTime(sec).then(function(){ player.play(); }).catch(function(){});
      }
    });

    /* --- 5. 同期ハイライトと自動スクロール --- */
    player.on('timeupdate', function(data) {
      // Vimeoプレーヤーが勝手に字幕を出していたら隠す（最強ガード）
      player.getTextTracks().then(function(tracks) {
          var activeTrack = tracks.find(function(t){ return t.mode === 'showing'; });
          if (currentMode === "hidden" && activeTrack) {
              useNormalMode();
          }
      }).catch(function(){});

      var currentTime = data.seconds;
      var listContainer = target.querySelector('details > p');
      if (!listContainer) return;

      var cues = listContainer.querySelectorAll('a.imk-cue');
      if (cues.length === 0) return;

      var activeA = null;
      for (var i = 0; i < cues.length; i++) {
        var sec = null;
        if (cues[i].dataset.seconds) {
            sec = Number(cues[i].dataset.seconds);
        } else if (cues[i].dataset.seek) {
            sec = parseTs(cues[i].getAttribute('data-seek'));
        }
        if (sec !== null && currentTime >= sec - 0.5) {
          activeA = cues[i];
        } else if (sec > currentTime) {
          break;
        }
      }

      if (activeA) {
          var activeLine = activeA.closest(".imk-line");
          if (!activeLine) activeLine = activeA;

          if (activeLine.classList.contains("active-hl")) return;

          // 全行の色を徹底的にリセット
          var allLines = listContainer.querySelectorAll(".imk-line");
          for(var k=0; k<allLines.length; k++) {
              allLines[k].classList.remove("active-hl");
              allLines[k].removeAttribute("style");
          }
          var allLinks = listContainer.querySelectorAll("a");
          for(var m=0; m<allLinks.length; m++) {
              allLinks[m].classList.remove("active-hl");
              allLinks[m].removeAttribute("style");
          }

          // 新しい行に赤文字・黄色背景を直接塗る
          activeLine.classList.add("active-hl");
          activeLine.style.setProperty("background-color", "#ffff00", "important");
          activeLine.style.setProperty("color", "red", "important");
          activeLine.style.setProperty("font-weight", "normal", "important");
          
          var newLinks = activeLine.querySelectorAll("a");
          for(var n=0; n<newLinks.length; n++) {
              newLinks[n].style.setProperty("color", "red", "important");
              newLinks[n].style.setProperty("text-decoration", "none", "important");
          }

          // スクロール処理
          if (listContainer.offsetParent !== null) {
              var containerRect = listContainer.getBoundingClientRect();
              var activeRect = activeLine.getBoundingClientRect();
              var targetScroll = listContainer.scrollTop + (activeRect.top - containerRect.top) - (listContainer.clientHeight / 2) + (activeLine.clientHeight / 2);
              listContainer.scrollTo({
                  top: targetScroll,
                  behavior: "smooth"
              });
          }
      }
    });
  })();
  </script>

  <style>
  .sc-vimeo-embed .iframe-wrapper {
    position: relative;
    padding-bottom: 56.25%;
    height: 0;
    overflow: visible;
  }
  .sc-vimeo-embed .iframe-wrapper iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
  }

  /* 行梱包時の基本スタイル（干渉防止のためクラス内で指定） */
  .sc-vimeo-embed .imk-line {
      display: inline-block;
      width: 100%;
      border-radius: 2px;
      transition: background-color 0.1s;
  }

  /* ▼ 字幕一覧（details）の見た目調整 */
  .sc-vimeo-embed details > p {
    font-size: 14px !important;
    line-height: 1.6;
    height: 200px !important; 
    overflow: auto;
    background-color: #EDF7FF;
    padding: 2px 6px;
    margin: 0;
    box-shadow: 3px 3px 4px black;
    position: relative; 
  }
  .sc-vimeo-embed details > summary {
    font-size: 14px !important;
    padding: 2px 6px;
    width: 100%;
    background-color: #ddd;
    border: none;
    box-shadow: 3px 3px 4px black;
    cursor: pointer;
    list-style: none;
  }
  </style>
</div>



<h3 class="wp-block-heading">ポイント解説</h3>



<p><strong>１　VTTで編集ができます</strong>：<br>簡易な字幕作成ツールとしては、「字幕工房」が優秀であるという見方は変わりませんが、SRTファイルでの書き出しです。私はWordPressブログに掲載する動画が殆どですので、毎回VTTファイルへ変換することになり面倒です。「字幕工房」に限らず、動画作成アプリで出力される字幕は、殆どがSRTファイルなのですね。</p>



<p><strong>２　ローカルファイルの更新をそのまま反映します</strong>：<br>動画共有サービスに共通することですが、字幕もそのほかのメディアアセットもローカルからアップロードした時点で切り離されてしまうので、ローカルファイルを更新しても反映されません。図の下段は、今運用しているマイ・メディアライブラリの機能ですが、ここでもその威力が発揮されます。ローカルでVTTファイルをTextEditで開いて手直しすれば、そのまま、ブログの表示が変更されます（数分のタイムラグはあり）。</p>



<a rel="noopener" target="_blank" href="https://docs.google.com/drawings/d/1GXuQ_5Vtufv7YH8_SwkfyAMHxzctFyzNb4J4dmJ-MDc/edit?usp=sharing" 
>
<img decoding="async" src="https://docs.google.com/drawings/d/e/2PACX-1vSpM7uCAK9FehOqeogKeJoeCMs1929xNU45hsx1tk_CUlhO9S8CH30BgcnNMx4URJ6nH83dm9uGP2lS/pub?w=1440&#038;h=1080"
></a>



<p><strong>３　停止位置の時刻を自動で取得します</strong>：<br>QuickTimePlayerで動画を停止した場所の時刻(時点)を自動で取得して、テキストとともに、VTTファイルへ書き込みます。さらに、書き込んだ情報を読み込んで、HUD(ディスプレイ)に即座に表示します。</p>



<p>主な特徴点は以上ですが、かんたんな点では、「字幕工房」を上回っています。</p>



<p><strong>４　わずか2ステップ</strong>：</p>



<p><strong>①対象の動画をクリックして開く</strong>(デフォルトはQuickTimePlayer)。</p>



<p><strong>②フォルダの上で右クリックして、「字幕かんたん作成」を立ち上げ、VTTファイルを作る</strong>。</p>



<p><strong>だけ</strong>です。</p>



<p><strong>５　キビキビと動きます：</strong><br>字幕作成アプリを探すと、ブラウザアプリが主流になっています。その<strong>ブラウザアプリですが、欠点は、「もったりヌルヌルした動作</strong>」にあります。iPad iPhoneでは仕方ないにしても、Macでも感じるところがあるので、それはなんか疲れるわけですね。QuickTimePlayer、TextEdit、標準スクリプト、そういった標準搭載ツールは、実にキビキビと動きます。</p>



<h3 class="wp-block-heading">実装の手順</h3>



<figure class="wp-block-flexible-table-block-table"><table class="has-fixed-layout"><tbody><tr><td style="width:10%">(1)</td><td>下の青色のボタンから、スクリプト(txtファイル)をダウンロードします。</td></tr><tr><td style="width:10%">(2)</td><td>生成AI( Gemini、ChatGPTなど)を利用すると簡単です。AIのプロンプト欄に、<br>①ダウンロードしたスクリプトをアップロードします。<br>②以下を記述します。<br>「私のMacに、添付したスクリプトを実装する手順を作ってください。それをtxt形式で提供ください。<br>私のMacは、[機種名][OSバージョン]です。よろしくお願いします。」</td></tr><tr><td style="width:10%">(3)</td><td>提供された、実装手順を記載したtxtファイルに基づき、生成AIとやりとりしながら、実装してください。<br>※txtファイルを開いたまま生成AIとやり取りし、修正後のtxtを再度送って「これで大丈夫ですか」と確認する方法を取れば、更新内容を逐一手元に残せるため、作業の履歴管理として便利で安心です。</td></tr><tr><td colspan="2"><a href="https://imakat.com/?pubtxt=字幕かんたん作成workflow_pub.txt" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=zrU95MiY.png" alt="" style="width:120px; height:auto;"></a></td></tr></tbody></table></figure>



<p>以上です。<br><br></p>



<p></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">27063</post-id>	</item>
		<item>
		<title>字幕一覧(字幕リスト)は、古いようで一番先進の動画構成方法！</title>
		<link>https://imakat.com/2024/02/11/20002/</link>
		
		<dc:creator><![CDATA[imakat]]></dc:creator>
		<pubDate>Sat, 10 Feb 2024 19:42:46 +0000</pubDate>
				<category><![CDATA[字幕作成]]></category>
		<category><![CDATA[デジタル]]></category>
		<category><![CDATA[ものづくり]]></category>
		<category><![CDATA[Dropbox]]></category>
		<category><![CDATA[vimeo]]></category>
		<category><![CDATA[Appleスクリプト]]></category>
		<category><![CDATA[srt]]></category>
		<category><![CDATA[vtt]]></category>
		<category><![CDATA[タイムコード]]></category>
		<category><![CDATA[Apple翻訳]]></category>
		<category><![CDATA[Windows翻訳]]></category>
		<category><![CDATA[Google翻訳]]></category>
		<guid isPermaLink="false">https://imakat.com/?p=20002</guid>

					<description><![CDATA[現状では、世界のどこかの人が何かのデバイスで、このブログを見て、その中の動画を視聴した時に、言葉がわからないという問題にぶつかります。ですから、そのブログの中に、言葉をわかるようにする「手掛かり」を配置しておきたいと思い [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large is-resized"><a href="https://imakat.com/rd.php?id=GjFF2Rw0.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=GjFF2Rw0.png" alt="" style="width:222px;height:auto"/></a><figcaption class="wp-element-caption">「字幕一覧」は本屋の立ち読み</figcaption></figure>



<p>現状では、世界のどこかの人が何かのデバイスで、このブログを見て、その中の動画を視聴した時に、言葉がわからないという問題にぶつかります。ですから、そのブログの中に、<strong>言葉をわかるようにする「手掛かり」を配置</strong>しておきたいと思います。</p>



<p>ただその「手掛かり」と言っても、なかなか簡単ではありません。<br>条件が複雑過ぎるからです。</p>



<p>現在、条件がどうマチマチであるか眺めてみます。まず、デバイスとしてポピュラーなものをピックアップすると、WindowsPC,Mac,iPhone,iPad,Android携帯、Androidタブレット、以上になるでしょうし、OSでポピュラーなものは、Windows,Mac,iPad/iPhone,Androidになるでしょうし、ブラウザでポピュラーなものは、Chrome,Edge,Safariになるでしょうし、さらに動画の配信側は、YouTube,Vimeo,WordPress,Dropboxなどクラウドサービス、自宅サーバーなど。。<br>こんな複雑な条件の中で、今、こうしたブログさらにその中の動画などが配信されているわけですね。ですから、全てのユーザーに、「言葉がわかるようにする」のは無理と言っていいでしょう。</p>



<p>結論が遅れました。</p>



<p>それほど、手の込んだ工夫ではありません。</p>



<p><strong><span class="fz-18px"><span class="marker">動画の下に、タイムコードあるいは番号が付いた「字幕一覧」を配置すべし。<br>具体的には以下です。</span></span></strong><br></p>



<details>
  <summary>字幕情報を表示します。</summary>
  <p>
<!-- 以下から書き出し -->
〜「Final Cut Proの起動時のGPU確認入力を省略する方法」〜<br>
1. Final Cut Proを起動した時、毎回、警告が出るようになりました。<br>
2. 「新しいGPUに切り替わりますが、いいですか？」と毎回聞かれるようになりました。<br>
3. これを自動的にOKになるようにしたいと思います。<br>
4. 症状を再現します。Final Cut Proを起動します。<br>
5. 選択したGPUは使用できません。選択したGPUは電源が入っていないか、使用できなくなりました。デフォルトのGPUが使用されます。<br>
6. 私としては、その通りOKで何ら問題ありません。<br>
7. Final Cut Proを起動する時、毎回、OKを押さなければなりません。<br>
8. 以前私は、Intel Mac miniを使っていました。その時、動画編集のために、外付けのeGPUを使っていました。最近、新たに、M2 Mac miniへ移行しました。<br>
9. その時に、Time Machineを使って、そのまま移行しました。<br>
10. eGPUがあるものとして引き継がれました。そのためこの現象が生じています。これをリセットする方法がなかなか見当たらず、仕方なく。。。<br>
11. それでは、対処をしていきます。<br>
12. STREAM DECKを使ってみます。<br>
13. 「マルチアクション」を使います。<br>
14. 「開く」を挿入します。<br>
15. 開くアプリケーションにFinal Cut Proを選択します。<br>
16. Final Cut Proが起動したあと、OKにするのは、Enterキーを入力します。<br>
17. 「ホットキー」を挿入します。<br>
18. ホットキーの項目をクリックすると、キーストロークを監視中になります。→enterを押します。<br>
19. 実行してみます。<br>
20. 反応が早すぎるので、OKの手前で止まってしまいます。<br>
21. ゆっくり動作するように遅延させるようにします。<br>
22. 「遅延」を、「開く」と「ホットキー」の間に挟み込みます。<br>
23. 再度、実行を試してみます。<br>
24. 正常に動作しました。<br>
25. 一応、完成しましたが、アイコンを作っておきます。<br>
26. Final Cut Proのアイコンを挿入します。<br>
27. タイトルを、Final Cutとして上段に表示するようにします。<br>
28. こんな感じに出来上がりました。<br>
29E. 「STREAM DECKを利用して、Final Cut Proをスムーズに起動させよう！」でした。<br>
<!-- 以上まで書き出し -->
</p>
</details>

<style>
details {
  font: 16px "Open Sans", Calibri, sans-serif;
  width: 100%;
}

details > summary {
  padding: 2px 6px;
 width: 100%; 
 border-radius: 5px 5px 5px 5px;
  background-color: #ddd;
  border: none;
  box-shadow: 3px 3px 4px black;
  cursor: pointer;
  list-style: none;
}

details > p {
  font: 14px "Open Sans", Calibri, sans-serif;
  height:200px;
  overflow: scroll;
 border-radius: 5px 5px 5px 5px;
  background-color: #EDF7FF;
  padding: 2px 6px;
  margin: 0;
  box-shadow: 3px 3px 4px black;
}
</style>






<p>このような折りたたみの字幕一覧を用意しておくと、ブログの翻訳をすれば、この部分も翻訳されます。(1)(2)などの番号でもいいですが、動画の中の位置が分かりません。タイムコードなら動画のバーを近くに持っていけます。YouTubeなどで字幕の自動翻訳もありますが、<strong>速く進み過ぎて目が追いつけません</strong>。だから、自分のペースで追いたいです。逆に、<strong>急いでいるので動画の要点をサラッと知りたい</strong>ということもあります。<strong>いわば「本屋の立ち読み」です。音声の早送りより、はるかに生産性は高いです。10分の動画でも字幕一覧をみれば30秒で概略がわかります</strong>。</p>



<p>AIの解読力ですが、動画を理解することもできるようになってきてはいます。しかし多大なリソース消費の問題もあり正確性も今一歩のところがあります。Geminiに質問してみましたが、動画に字幕ファイルが別添されている形が、AIとすると一番ありがたい形式、と言う返答でした。</p>



<p>いずれにせよ字幕一覧形式は非常に優れています。翻訳した字幕一覧を自分のメモに貼り付けることも出来ます。字幕が邪魔なら、動画の字幕を非表示にして、この字幕一覧を折り畳めばいいです。</p>



<p><br>ちなみに、<strong>上の折りたたみ字幕一覧を、左上のGoogle翻訳で試してみてください。翻訳の途中から改行がされない現象が生ずる場合があります。これはChromeからChromeの翻訳機能を使っても同じ現象になるでしょう。<br>次に、AppleやWindowsの翻訳を試してみてください。ブラウザから利用できると思います。それを使うと、正しく改行されるはずです</strong>。</p>



<p>Macで使う場合、Vimeoの動画に表示される字幕の翻訳は、Google翻訳では翻訳不可ですが、Apple翻訳ではVimeoの動画に表示される字幕を翻訳してくれます(<a href="https://imakat.com/vm/?movid=913935684">動画無音</a>)。iPad,iPhoneではそれが難しいのでWordPress固定ページに字幕一覧を読み込んで工夫することにします(<a href="https://imakat.com/vm/?movid=914144217">動画有音</a>)。</p>



<p>Apple翻訳で気づいた欠点の一つは、WordPress動画プレーヤーで表示される字幕について翻訳しようとする時パカパカと点滅状態になるため(<a href="https://imakat.com/ds5/?drid=1">動画無音</a>)字幕は非表示にせざるを得ない点があります（2024.2月現在)。</p>



<p>なお、WindowsのEdgeにより、vimeoのプレーヤーを直接に呼び出す、つまりhttps://player.vimeo.com/video/xxxxxxxxxを入力する場合ですが、AppleのSafariと同じく、字幕は直接に翻訳されます(<a href="https://imakat.com/vm?movid=914067338">動画無音</a>)。</p>



<p>総じて、各社の字幕や翻訳の対応は、まだまだバラバラな状況と言っていいです。そこへ群がるように、各社がAI生成画像、音楽などのサービスをくっつけてきているというのが現状です。</p>



<p>そこで、<strong><span class="marker">振り回されないように、字幕一覧を配置して、Apple/Windows翻訳とGoogle翻訳の両方を使い分けるようにしよう</span></strong>。というのが、この投稿の主張です。</p>



<figure class="wp-block-image size-large is-resized"><a href="https://imakat.com/rd.php?id=bKOzGEon.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=bKOzGEon.png" alt="" style="aspect-ratio:0.5021524788223858;width:130px;height:auto"/></a></figure>



<hr class="wp-block-separator has-text-color has-key-color-color has-alpha-channel-opacity has-key-color-background-color has-background is-style-wide"/>



<p></p>



<p><strong><span class="fz-16px"><span class="fz-18px"><span class="marker">＜字幕作成に関するオリジナルスクリプト一覧表＞</span></span></span></strong></p>



<figure class="wp-block-flexible-table-block-table is-scroll-on-pc is-scroll-on-mobile"><table class="" style="width:740px;max-width:740px"><tbody><tr><td style="background-color:#f3fafe"><strong>スクリプト名</strong></td><td style="background-color:#f3fafe"><strong>説明</strong></td><td style="background-color:#f3fafe"><strong>補足</strong></td></tr><tr><td><a href="https://imakat.com/wp-content/pmedia/scripts_pub/srtからvttを生成するworkflow_pub.txt" target="_blank">srtからvttを生成する</a></td><td><a href="https://imakat.com/ds5/?drid=2">動画(無音)</a><br>新たに作ったVTTファイルに対して、 <br> (1) 先頭行に文字列&#8221;WEBVTT&#8221;を含む行を挿入する。 <br>(2) 2行目に空白の行を挿入する。 <br>(3) 3行目以降から、読み込んだデータを書き込む。 <br> (4) &#8220;&#8211;&gt;&#8221; がある行は、行の中の&#8221;,&#8221;を&#8221;.&#8221;に置き換える。<br>※元のファイルを残します。</td><td>AppleScriptクイックアクション</td></tr><tr><td><a href="https://imakat.com/wp-content/pmedia/scripts_pub/vttからsrtを生成する兼srtの連番を付け直すworkflow_pub.txt" target="_blank">vttからsrtを生成する兼srtの連番を付け直す</a>(renumbered.srt)</td><td><a href="https://imakat.com/ds5?drid=3">動画(無音</a>)<br>新たに作ったSRTファイルに対して、<br>(1) 文字列”WEBVTT”のある行は削除する。<br>(2) &#8220;&#8211;&gt;&#8221; がある行は、行の中の&#8221;.&#8221;を&#8221;,&#8221;に置き換える。<br>(3)連番を1から振り直す。<br>※元のファイルを残します。新しいファイル名は、&#8221;元のファイル名_renumbered.srt&#8221;となります。</td><td>AppleScriptクイックアクション</td></tr><tr><td><a href="https://imakat.com/wp-content/pmedia/scripts_pub/字幕文章に時刻を挿入するworkflow_pub.txt" target="_blank">字幕文章に時刻を挿入する</a>(timeadded.vtt)</td><td><a href="https://imakat.com/ds5?drid=4">動画(無音</a><a href="https://imakat.com/ds?drid=4">)</a><br>文字列の先頭に、開始時刻(00:01:23)を追記する。私はカモメ→(00:01:23)私はカモメ※元のファイルを残します。_timeadded.vttが新しく作られます。この字幕文章の先頭に時刻情報を入れる目的は、翻訳された外国語の示す動画の位置を分かりやすくするためです。</td><td>AppleScriptクイックアクション</td></tr><tr><td><a href="https://imakat.com/wp-content/pmedia/scripts_pub/字幕文章の時刻を削除するworkflow_pub.txt" target="_blank">字幕文章の時刻を削除する</a>(timeremoved.vtt)</td><td>上の「vttからタイムありvttを生成する」を取り消しにします。※元のファイル_timeadded.vttは残します。新しいファイルは、_timeadded_timeremoved .vttになります。</td><td>AppleScriptクイックアクション</td></tr><tr><td><a href="https://imakat.com/wp-content/pmedia/scripts_pub/vttから字幕一覧用txtを生成workflow_pub.txt" target="_blank">字幕vttから字幕一覧txtを生成する</a></td><td>動画内の字幕は、多くの場合、翻訳されないか動作不安定になるが、字幕一覧txtが動画の下にあれば、翻訳が可能になります。タイムコードの位置にジャンプする_listJ.txtおよびジャンプしない_list.txtを生成します。※元のファイルは残します。新しいファイルは、_list.txtになります。なお既存の場合は上書きします。</td><td>AppleScriptクイックアクション</td></tr><tr><td><a href="#link2"><s>vttから字幕一覧用txtを生成する</s></a></td><td><a href="https://imakat.com/ds5?drid=5">動画(無音)</a><br>字幕一覧用txtは、動画の外側に配置するので、Google翻訳される。<strong>→「字幕vttから字幕一覧txtを生成する」へ集約</strong>。</td><td>AppleScriptクイックアクション</td></tr><tr><td><a href="https://imakat.com/2024/01/22/18942#link1"><s>DropboxリンクをWordPress用に変換する(クリップボード保存)</s></a></td><td><a href="https://imakat.com/ds5?drid=6">動画(無音)</a><br>Dropboxのメディアを外部リンクするために、URLに指定された変更を加える。URLの記述の中の &#8220;www.dropbox.com&#8221;は、そのまま使うようにとりあえず判断した。</td><td>AppleScriptクイックアクション</td></tr><tr><td><a href="https://imakat.com/2024/01/22/18942/#link2"><s>★WordPress動画貼り付けコード生成(クリップボード保存)</s></a></td><td><a href="https://imakat.com/ds5?drid=7">動画(無音)</a><br>WordPressのカスタムhtmlへ貼り付ける。初期画面用画像、動画本体、字幕のファイルを予め用意。→マイライブラリの運用に切り替え。</td><td><span class="red">AppleScriptアプリケーション</span></td></tr><tr><td><a href="#link1">★<s>字幕一覧用txtからカスタムhtmlを生成(クリップボード保存)</s></a></td><td><a href="https://imakat.com/ds5?drid=8">動画(無音</a><a href="https://imakat.com/ds?drid=8">)</a> <a href="https://imakat.com/ds5/?drid=9">動画(無音</a><a href="https://imakat.com/ds/?drid=9">)</a><br>字幕一覧用txtを表示するボックスレイアウトを作る。Google翻訳の表示にて改行がうまくいかない状態がある<strong>。→「字幕vttから字幕一覧txtを生成する」へ集約</strong>。</td><td>AppleScriptクイックアクション</td></tr><tr><td><a href="https://imakat.com/wp-content/pmedia/scripts_pub/字幕空白詰め_vimeo_auto_generated_captions_vttの修正_pub.txt" target="_blank">vimeo_auto_generated_captions.vttの修正をする</a></td><td>Vimeoの字幕自動生成からダウンロードしたファイルの、文字列の空白を削除する。vttのまま。※直接上書きします。何度でもダウンロードできるため。</td><td>AppleScriptクイックアクション</td></tr><tr><td><a href="https://imakat.com/2019/12/14/8731/"><s>★Vimeo登録用htmlコード生成</s></a></td><td>方法１：WordPressで、カスタムhtmlブロックへ登録して、パターンを作成しておく。<br>方法２：Stream deckなどで文字列として登録しておく。<br>方法３：Appleクイックアクションで登録しておく。など。→マイライブラリの運用に切り替え。</td><td>字幕作成とは直接に関係ありませんが、迷子にならないように。</td></tr><tr><td><a href="https://imakat.com/wp-content/pmedia/scripts_pub/字幕時刻の秒ずらしを行うworkflow_pub.txt" target="_blank">vttの字幕時刻の秒ずらしを行う。</a>(timeshifted.vtt)</td><td><a href="https://imakat.com/ds5?drid=25" target="_blank">動画(無音)</a><br>動画の途中で、挿入や削除を行うと、字幕ファイルの時刻にズレが生じます。挿入や削除を行った以降の動画をコピーして、その分の秒ずらしを行うことができます。<span class="bold-red">但し、文章の頭に時刻情報を入れてある(_timeadded.vtt)については、エラーになります。一度、上の「字幕文章の時刻を削除する」を実行した後で、ここを実行してください</span>。<br>※元のファイルを残します。新しいファイル名は&#8221;元のファイル名_timeshited.vtt&#8221;となります。</td><td>AppleScriptクイックアクション</td></tr></tbody></table></figure>



<h3 class="wp-block-heading">ポイント解説</h3>



<h4 class="wp-block-heading">１　その他</h4>



<p>WindowsPCでのこのブログにリンクした動画の再生についてです。Dropboxの動画についてですが、Dropboxの動画は、ブログに貼り付けた場合は、そのまま素直にストリーミング再生されます。しかし、URLをリンクで再生しようとした場合、ダウンロードしてからの再生を求められます。それはとても面倒なこと。その点も勘案して、Google翻訳アイコン、動画、字幕一覧の各場所をテンプレートにして、動画については、Vimeo、Dropbox、WordPressサーバー、YouTubeなどを貼り付けられるようにして、WordPressの固定ページで動画ライブラリーとしてひとまとめにするように改善中です。</p>



<p>以上</p>



<figure class="wp-block-image size-large is-resized"><a href="https://imakat.com/rd.php?id=ZrH7yK6Q.jpeg" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=ZrH7yK6Q.jpeg" alt="" style="width:146px;height:auto"/></a></figure>



<p></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">20002</post-id>	</item>
	</channel>
</rss>
