<?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>音声認識字幕ちゃん | imakat.com</title>
	<atom:link href="https://imakat.com/tag/%E9%9F%B3%E5%A3%B0%E8%AA%8D%E8%AD%98%E5%AD%97%E5%B9%95%E3%81%A1%E3%82%83%E3%82%93/feed/" rel="self" type="application/rss+xml" />
	<link>https://imakat.com</link>
	<description>工夫と改善で人生をちょっと豊かに</description>
	<lastBuildDate>Fri, 12 Sep 2025 01:06:24 +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>音声認識字幕ちゃん | 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で「音声認識字幕ちゃん」を使いやすくする。</title>
		<link>https://imakat.com/2023/11/17/18463/</link>
		
		<dc:creator><![CDATA[imakat]]></dc:creator>
		<pubDate>Fri, 17 Nov 2023 09:00:00 +0000</pubDate>
				<category><![CDATA[デジタル]]></category>
		<category><![CDATA[ものづくり]]></category>
		<category><![CDATA[Window Resizer]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Mac mini]]></category>
		<category><![CDATA[STREAM DECK]]></category>
		<category><![CDATA[Chrome]]></category>
		<category><![CDATA[OBS]]></category>
		<category><![CDATA[音声認識字幕ちゃん]]></category>
		<guid isPermaLink="false">https://imakat.com/?p=18463</guid>

					<description><![CDATA[「音声認識字幕ちゃん」のサイズ調整 最近、ちまたでもスマホの翻訳アプリ、翻訳機器などを目にすることが多くなってきました。しかも同時翻訳までできてしまうのには驚きです。ただ、いざ使おうと思うと、最初はお試しで無料ですが、有 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<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"/>



<h5 class="wp-block-heading">「音声認識字幕ちゃん」のサイズ調整</h5>


<div class="sc-dynamic-embed">
  <style>
  /* リンクの見た目を整える */
  .sc-dynamic-embed .sc-link-container { 
      display: flex; 
      gap: 12px; 
      margin-bottom: 10px; 
      flex-wrap: wrap; 
      align-items: center; 
  }
  .sc-dynamic-embed .sc-link { margin-bottom: 0; }
  .sc-dynamic-embed .sc-link a {
    font-size: 15px;
    font-weight: normal;
    text-decoration: underline;
    color: #0073aa;
  }
  .sc-dynamic-embed .sc-link a:hover { text-decoration: none; color: #000; }
  
  /* ★変更：ダウンロードボタンの基本サイズを小さくし、文字の折り返しを防止 */
  .sc-dynamic-embed .dl-btn a {
    font-size: 12px !important;
    color: #d9534f;
    font-weight: bold;
    text-decoration: none;
    background: #fdf0ef;
    padding: 4px 6px;
    border-radius: 4px;
    border: 1px solid #d9534f;
    white-space: nowrap; 
  }
  .sc-dynamic-embed .dl-btn a:hover { background: #d9534f; color: #fff; }

  /* ★追加：スマホ画面（幅500px以下）の時は、さらに全体を縮小して1行に収める */
  @media (max-width: 500px) {
    .sc-dynamic-embed .sc-link-container { gap: 6px; }
    .sc-dynamic-embed .sc-link a { font-size: 13px; }
    .sc-dynamic-embed .dl-btn a { font-size: 11px !important; padding: 3px 5px; }
  }

  /* 行梱包時の基本スタイル */
  .sc-dynamic-embed .imk-line {
      display: inline-block;
      width: 100%;
      border-radius: 2px;
      transition: background-color 0.1s;
  }

  /* 古い枠内字幕ボックスを強制消去 */
  .sc-dynamic-embed #subtitleOverlay,
  .sc-dynamic-embed #scSubtitleOverlay,
  .sc-dynamic-embed .overlay-cue,
  .sc-dynamic-embed .band {
      display: none !important;
      opacity: 0 !important;
      visibility: hidden !important;
      pointer-events: none !important;
  }
  </style>

  <div class="sc-link-container">
    <p class="sc-link">
      <a href="https://imakat.com/ds62/?drid=26" target="_blank"
         onclick="return scStopAndGo(event, this);">
        👉低画質・枠外字幕はこちら
      </a>
    </p>
    <p class="sc-link dl-btn">
      <a href="#" id="imk-dynamic-dl-btn" target="_blank" rel="noopener" download style="display: none;">
        📥 動画をダウンロード
      </a>
    </p>
  </div>

  <style>
            :root{ --dr5emd-max: 1920px; }
            .video-wrap{position:relative;width:100%;margin:0 auto}
            figure.wp-block-video.aligncenter{
              width:100%;
              max-width:min(var(--dr5emd-max, 1920px), 98vw);
              margin:0 auto;
            }
            #subtitleOverlay{
              position:absolute; left:0; right:0; bottom:6%;
              padding:0 2%; text-align:center; pointer-events:none; z-index:2;
            }
            #subtitleOverlay .band{
              display:inline-block; background:rgba(0,0,0,0.35);
              padding:6px 10px; border-radius:8px; max-width:96%;
              margin:0 auto; box-shadow:0 1px 2px rgba(0,0,0,0.15);
            }
            #subtitleOverlay .overlay-cue{
              color:#fff; font-weight:600;
              font-size:clamp(16px, 3.6vw, 32px);
              line-height:1.32; white-space:pre-wrap; margin:2px 0;
              -webkit-text-stroke:.6px rgba(0,0,0,.7);
              text-shadow:-1px -1px 0 rgba(0,0,0,.6), 1px -1px 0 rgba(0,0,0,.6),
                          -1px  1px 0 rgba(0,0,0,.6), 1px  1px 0 rgba(0,0,0,.6);
            }
            @media (max-width:430px){
              #subtitleOverlay .overlay-cue{ font-size:clamp(16px, 4.2vw, 22px); }
            }
            .dr5emd-sublist details > p{
              height:200px; overflow:auto; background-color:#EDF7FF;
              padding:2px 6px; margin:0; box-shadow:3px 3px 4px black;
              position: relative;
            }
            .dr5emd-sublist details > summary{
              padding:2px 6px; width:100%;
              background-color:#ddd; border:none;
              box-shadow:3px 3px 4px black; cursor:pointer; list-style:none;
            }
            /* ▼ 自動スクロール時のハイライト（文字の太さを標準へ変更） */
            .active-hl {
                background-color: #ffff00 !important;
                color: #ff0000 !important;
                font-weight: normal; /* 標準の太さ */
                border-bottom: 2px solid red;
                display: inline-block;
                border-radius: 2px;
            }
            </style><div class="dr5emd-container"><figure class="wp-block-video aligncenter"><div class="video-wrap"><video id="myVideo" controls controlsList="nodownload" poster="https://imakat.com/rd.php?id=SZyJ0Iso.png" playsinline preload="metadata" style="width:100%;height:auto;">  <source src="https://imakat.com/rd.php?id=ffhDUfn3.mp4" type="video/mp4">  <track src="https://imakat.com/rd.php?id=uMEIIFOK.vtt" label="日本語" srclang="ja" kind="subtitles"></video><div id="subtitleOverlay" aria-hidden="true"></div></div><script>
document.addEventListener("DOMContentLoaded", function(){
  var video=document.getElementById("myVideo");
  var trackEl=video?video.querySelector("track[kind='subtitles'], track[kind='captions']"):null;
  var overlay=document.getElementById("subtitleOverlay"); if(!video||!overlay) return;
  video.addEventListener("contextmenu", function(e){ e.preventDefault(); return false; }, false);
  function setNative(mode){
    try{
      if(video.textTracks && video.textTracks.length){
        for(var i=0;i<video.textTracks.length;i++){ video.textTracks[i].mode = mode; }
      }
      if(trackEl && trackEl.track) trackEl.track.mode = mode;
    }catch(e){}
  }
  var isOverlay=true,lastSig="";
  function sig(active){if(!active||active.length===0)return"";var a=[];for(var i=0;i<active.length;i++){var c=active[i];a.push([c.startTime,c.endTime,c.text].join("|"));}return a.join("||");}
  function cueLine(c){var d=document.createElement("div");d.className="overlay-cue";d.setAttribute("translate","yes");if(typeof c.getCueAsHTML==="function")d.appendChild(c.getCueAsHTML());else d.textContent=c.text;return d;}
  function render(){
    if(!isOverlay || !trackEl || !trackEl.track) return;
    var ac=trackEl.track.activeCues,s=sig(ac); if(s===lastSig) return; lastSig=s;
    overlay.innerHTML=""; if(!ac || ac.length===0) return;
    var b=document.createElement("div"); b.className="band"; b.setAttribute("translate","yes");
    Array.from(ac).sort(function(a,b){return a.startTime-b.startTime;}).forEach(function(c){b.appendChild(cueLine(c));});
    overlay.appendChild(b);
  }
  function useOverlay(){isOverlay=true;overlay.style.display="";setNative("hidden");lastSig="";render();}
  function useNative(){isOverlay=false;overlay.style.display="none";setNative("showing");lastSig="";}
  useOverlay();
  if(trackEl){
    if(trackEl.track){ try{ trackEl.track.addEventListener("cuechange",render); }catch(e){} }
    trackEl.addEventListener("load", function(){ try{ if(trackEl.track) trackEl.track.addEventListener("cuechange",render); }catch(e){} render(); });
  }
  video.addEventListener("loadedmetadata",render);
  function handleWebkitMode(){ var m = video.webkitPresentationMode || "inline"; (m==="picture-in-picture"||m==="fullscreen") ? useNative() : useOverlay(); }
  if("webkitPresentationMode" in video){ video.addEventListener("webkitpresentationmodechanged",handleWebkitMode); handleWebkitMode(); }
  if("webkitCurrentPlaybackTargetIsWireless" in video){
    video.addEventListener("webkitcurrentplaybacktargetiswirelesschanged", function(){ video.webkitCurrentPlaybackTargetIsWireless ? useNative() : useOverlay(); });
  }
  if("pictureInPictureEnabled" in document){
    video.addEventListener("enterpictureinpicture",useNative);
    video.addEventListener("leavepictureinpicture",useOverlay);
  }
  document.addEventListener("fullscreenchange", function(){
    var fs=document.fullscreenElement;
    if(!fs) return useOverlay();
    (fs===video || (fs && fs.contains && fs.contains(video))) ? useNative() : useOverlay();
  });
});
</script>
                <figcaption></figcaption></figure><div class="dr5emd-sublist"><details><summary>字幕一覧(クリック)</summary> <p>
(<a href="#" class="imk-cue" data-seek="0:01">00:00:01</a>)  今回は「音声認識字幕ちゃん」のですね。<br>
(<a href="#" class="imk-cue" data-seek="0:10">00:00:10</a>)  サイズを調整する、というテーマでやっていきます。<br>
(<a href="#" class="imk-cue" data-seek="0:15">00:00:15</a>)  「音声認識字幕ちゃん」はですね。<br>
(<a href="#" class="imk-cue" data-seek="0:18">00:00:18</a>)  Google Chromeでしか起動できないのです！<br>
(<a href="#" class="imk-cue" data-seek="0:23">00:00:23</a>)  で、このhttps以下ここにある、<br>
(<a href="#" class="imk-cue" data-seek="0:30">00:00:30</a>)  これを入れて立ち上げるのですが、そうすると下のように、<br>
(<a href="#" class="imk-cue" data-seek="0:38">00:00:38</a>)  ホームページが出てくるのですが、<br>
(<a href="#" class="imk-cue" data-seek="0:41">00:00:41</a>)  この中で、Google Script API-KEYがありますが、<br>
(<a href="#" class="imk-cue" data-seek="0:46">00:00:46</a>)  ここに、API KEYを入れるんですね。<br>
(<a href="#" class="imk-cue" data-seek="0:52">00:00:52</a>)  それはちょっとまた別の場面で、ここのURLからですね、<br>
(<a href="#" class="imk-cue" data-seek="0:58">00:00:58</a>)  設定方法を見て、取得して入力してください。<br>
(<a href="#" class="imk-cue" data-seek="1:05">00:01:05</a>)  それは今回は説明しません。<br>
(<a href="#" class="imk-cue" data-seek="1:13">00:01:13</a>)  それで、まず、<br>
(<a href="#" class="imk-cue" data-seek="1:15">00:01:15</a>)  Google Chromeを、表示するのですけれども、<br>
(<a href="#" class="imk-cue" data-seek="1:20">00:01:20</a>)  Google Chromeから、<br>
(<a href="#" class="imk-cue" data-seek="1:22">00:01:22</a>)  「音声認識字幕ちゃん」を表示するのですけれども、<br>
(<a href="#" class="imk-cue" data-seek="1:27">00:01:27</a>)  それが、OBSの画面上のどの位置に配置するか、<br>
(<a href="#" class="imk-cue" data-seek="1:33">00:01:33</a>)  どの大きさで配置するか、というのは、<br>
(<a href="#" class="imk-cue" data-seek="1:36">00:01:36</a>)  人によって様々だと思いますので、<br>
(<a href="#" class="imk-cue" data-seek="1:42">00:01:42</a>)  それに合わせるために、<br>
(<a href="#" class="imk-cue" data-seek="1:45">00:01:45</a>)  ウィンドウサイズを、<br>
(<a href="#" class="imk-cue" data-seek="1:47">00:01:47</a>)  色々変えれるようにしておく必要があるんですね。<br>
(<a href="#" class="imk-cue" data-seek="1:51">00:01:51</a>)  それでこのプラグインを入れます。<br>
(<a href="#" class="imk-cue" data-seek="1:55">00:01:55</a>)  Window Resizerというものです。<br>
(<a href="#" class="imk-cue" data-seek="2:01">00:02:01</a>)  Chromeウェブストアから拡張機能を選んで、<br>
(<a href="#" class="imk-cue" data-seek="2:07">00:02:07</a>)  その中で検索のところに、<br>
(<a href="#" class="imk-cue" data-seek="2:11">00:02:11</a>)  Window Resizerと入れて、このアプリケションを探して、<br>
(<a href="#" class="imk-cue" data-seek="2:19">00:02:19</a>)  それでダウンロードしてください。<br>
(<a href="#" class="imk-cue" data-seek="2:26">00:02:26</a>)  で、次にWindow Resizerの設定をします。<br>
(<a href="#" class="imk-cue" data-seek="2:31">00:02:31</a>)  すでに既定値として、ご覧のように320以下ですね、<br>
(<a href="#" class="imk-cue" data-seek="2:38">00:02:38</a>)  この1920までが既定値としてあるのですけれども、<br>
(<a href="#" class="imk-cue" data-seek="2:43">00:02:43</a>)  サイズのですね、<br>
(<a href="#" class="imk-cue" data-seek="2:44">00:02:44</a>)  ところがやっぱり私としては、<br>
(<a href="#" class="imk-cue" data-seek="2:48">00:02:48</a>)  OBSの画面の右下のところに、翻訳が出るなら出したいので、<br>
(<a href="#" class="imk-cue" data-seek="2:54">00:02:54</a>)  もうちょっと小さいサイズのものを作りたいです。<br>
(<a href="#" class="imk-cue" data-seek="2:58">00:02:58</a>)  そこで819 x 614というものを作りたいと思うので、<br>
(<a href="#" class="imk-cue" data-seek="3:04">00:03:04</a>)  自分で作ります。<br>
(<a href="#" class="imk-cue" data-seek="3:07">00:03:07</a>)  このpresetsのところの、+のところを押して、<br>
(<a href="#" class="imk-cue" data-seek="3:12">00:03:12</a>)  そうすると別の画面に移行して設定ができます。<br>
(<a href="#" class="imk-cue" data-seek="3:16">00:03:16</a>)  で、それの設定が済みますと、<br>
(<a href="#" class="imk-cue" data-seek="3:19">00:03:19</a>)  このpresetsの一番上段のところに、<br>
(<a href="#" class="imk-cue" data-seek="3:23">00:03:23</a>)  今設定した新しいものが出てきます。<br>
(<a href="#" class="imk-cue" data-seek="3:34">00:03:34</a>)  Window Resizer設定のもう一つです。<br>
(<a href="#" class="imk-cue" data-seek="3:39">00:03:39</a>)  それは、hotkeysでpresetを設定します。<br>
(<a href="#" class="imk-cue" data-seek="3:46">00:03:46</a>)  presetの上から、<br>
(<a href="#" class="imk-cue" data-seek="3:49">00:03:49</a>)  presetが1,2,3,4,5...と順番が付いてますけども、<br>
(<a href="#" class="imk-cue" data-seek="3:54">00:03:54</a>)  これが先程のこの順番と対応してます。<br>
(<a href="#" class="imk-cue" data-seek="4:00">00:04:00</a>)  従って、<br>
(<a href="#" class="imk-cue" data-seek="4:01">00:04:01</a>)  今私が作った819 x 614は、<br>
(<a href="#" class="imk-cue" data-seek="4:07">00:04:07</a>)  この下の、Resize to preset 1 に対応しています。<br>
(<a href="#" class="imk-cue" data-seek="4:13">00:04:13</a>)  従って私はここに、登録しました。次に。<br>
(<a href="#" class="imk-cue" data-seek="4:25">00:04:25</a>)  もう一つ準備することがあります。<br>
(<a href="#" class="imk-cue" data-seek="4:29">00:04:29</a>)  Google Chromeで、<br>
(<a href="#" class="imk-cue" data-seek="4:31">00:04:31</a>)  「音声認識字幕ちゃん」を起動させるための、<br>
(<a href="#" class="imk-cue" data-seek="4:35">00:04:35</a>)  Appleスクリプトが必要になることです。<br>
(<a href="#" class="imk-cue" data-seek="4:40">00:04:40</a>)  それは既定ブラウザをChromeにしていない場合も多いためです。<br>
(<a href="#" class="imk-cue" data-seek="4:51">00:04:51</a>)  スクリプトは簡単です。<br>
(<a href="#" class="imk-cue" data-seek="4:54">00:04:54</a>)  tell application "Google Chrome"<br>
(<a href="#" class="imk-cue" data-seek="5:00">00:05:00</a>)  activate open location <br>
(<a href="#" class="imk-cue" data-seek="5:05">00:05:05</a>)  「音声認識字幕ちゃん」のURLを入れます。<br>
(<a href="#" class="imk-cue" data-seek="5:11">00:05:11</a>)  そして、end tell です。<br>
(<a href="#" class="imk-cue" data-seek="5:19">00:05:19</a>)  その設定したものを、Stream Deckへ登録します。<br>
(<a href="#" class="imk-cue" data-seek="5:26">00:05:26</a>)  Stream Deckで、マルチアクションという形で登録します。<br>
(<a href="#" class="imk-cue" data-seek="5:30">00:05:30</a>)  一つ目は、Chromeで、<br>
(<a href="#" class="imk-cue" data-seek="5:33">00:05:33</a>)  「音声認識字幕ちゃん」を開くAppleスクリプトです。<br>
(<a href="#" class="imk-cue" data-seek="5:40">00:05:40</a>)  二つ目は開いたChromeのサイズ合わせをします。<br>
(<a href="#" class="imk-cue" data-seek="5:48">00:05:48</a>)  先ほど設定したホットキーです。<br>
(<a href="#" class="imk-cue" data-seek="5:56">00:05:56</a>)  以上で設定は終わりです。<br>
(<a href="#" class="imk-cue" data-seek="6:00">00:06:00</a>)  で、Stream Deckからそのマルチアクションを起動します。<br>
(<a href="#" class="imk-cue" data-seek="6:05">00:06:05</a>)  そうすると下のようにですね、Chromeが立ち上がります。<br>
(<a href="#" class="imk-cue" data-seek="6:12">00:06:12</a>)  最初に立ち上げた時は、<br>
(<a href="#" class="imk-cue" data-seek="6:14">00:06:14</a>)  マイクの使用がまだ許可されてないと思いますので、<br>
(<a href="#" class="imk-cue" data-seek="6:18">00:06:18</a>)  それを許可します。<br>
(<a href="#" class="imk-cue" data-seek="6:21">00:06:21</a>)  そうすると以下のように表示されます。<br>
(<a href="#" class="imk-cue" data-seek="6:24">00:06:24</a>)  おはようございます<br>
(<a href="#" class="imk-cue" data-seek="6:26">00:06:26</a>)  Good morning、早上好。<br>
(<a href="#" class="imk-cue" data-seek="6:30">00:06:30</a>)  既にですね。第一翻訳語として英語、第二翻訳語として中国語を設定してあります。<br>
(<a href="#" class="imk-cue" data-seek="6:38">00:06:38</a>)  なのでこういうふうに出てきます。以上で準備が終わりまして、<br>
(<a href="#" class="imk-cue" data-seek="6:49">00:06:49</a>)  次のステップはこれをOBSへ取り込む、<br>
(<a href="#" class="imk-cue" data-seek="6:54">00:06:54</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>
(function(){
  var root=document.querySelector(".dr5emd-sublist");
  var video=document.getElementById("myVideo");
  if(!root || !video) return;
  function parseTs(ts){
    if(!ts) return null;
    var p=ts.trim().split(":").map(function(x){return parseInt(x,10)||0;});
    if(p.length===2) return p[0]*60 + p[1];
    if(p.length===3) return p[0]*3600 + p[1]*60 + p[2];
    return null;
  }
  root.addEventListener("click", function(e){
    var a=e.target.closest && e.target.closest("a.imk-cue[data-seek]");
    if(!a || !root.contains(a)) return;
    e.preventDefault();
    var sec = parseTs(a.getAttribute("data-seek"));
    if(sec==null) return;
    try{ video.currentTime = sec; if(video.paused) video.play(); }catch(_){}
  });
  video.addEventListener("timeupdate", function(){
    var listContainer = root.querySelector("details > p");
    if(!listContainer) return;
    var cues = listContainer.querySelectorAll("a.imk-cue");
    if(cues.length === 0) return;
    var cur = video.currentTime;
    var active = null;
    for(var i=0; i<cues.length; i++){
        var t = parseTs(cues[i].getAttribute("data-seek"));
        if(t !== null && cur >= t - 0.5){
            active = cues[i];
        } else if(t > cur){
            break;
        }
    }
    if(active){
        if(active.classList.contains("active-hl")) return;
        var old = listContainer.querySelectorAll(".active-hl");
        for(var k=0; k<old.length; k++) old[k].classList.remove("active-hl");
        active.classList.add("active-hl");
        if(listContainer.offsetParent !== null){
            var containerRect = listContainer.getBoundingClientRect();
            var activeRect = active.getBoundingClientRect();
            var targetScroll = listContainer.scrollTop + (activeRect.top - containerRect.top) - (listContainer.clientHeight / 2) + (active.clientHeight / 2);
            listContainer.scrollTo({ top: targetScroll, behavior: "smooth" });
        }
    }
  });
})();
</script>
                </div>

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

    /* -----------------------------------------------
       1. ダウンロードボタンの自動セットアップ機能
       ----------------------------------------------- */
    function setupDownloadButton() {
      var target = wrapper ? wrapper : document;
      var video = target.querySelector('video');
      var dlBtn = target.querySelector('#imk-dynamic-dl-btn');

      if (video && dlBtn && dlBtn.style.display === 'none') {
        var src = video.currentSrc || video.src;
        if (!src) {
          var source = video.querySelector('source');
          if (source) src = source.src;
        }
        if (src) {
          dlBtn.href = src;
          dlBtn.style.display = 'inline-block';
        }
      }
    }

    /* -----------------------------------------------
       2. 字幕制御＆ハイライト機能（iPhone全画面 完全対応版）
       ----------------------------------------------- */
    function initSubtitles() {
      var target = wrapper ? wrapper : document;
      var video = target.querySelector('video');
      var listContainer = target.querySelector('details > p');
      
      if (!video || !listContainer) return false; 

      if (video.dataset.subInit === 'true') return true; 
      video.dataset.subInit = 'true';

      var oldOverlay = target.querySelector('#subtitleOverlay') || target.querySelector('#scSubtitleOverlay');
      if (oldOverlay) {
          oldOverlay.style.setProperty('display', 'none', 'important');
          oldOverlay.innerHTML = ''; 
      }

      function isSpecialMode() {
        var isFs = !!(document.fullscreenElement || document.webkitFullscreenElement || document.mozFullScreenElement || document.msFullscreenElement);
        var isPiP = !!(document.pictureInPictureElement && document.pictureInPictureElement === video) || (video.webkitPresentationMode === "picture-in-picture");
        var isIOSFs = !!video.webkitDisplayingFullscreen; 
        return isFs || isPiP || isIOSFs;
      }

      try {
        if(video.textTracks && video.textTracks.length > 0){
          for(var i=0; i<video.textTracks.length; i++){
             if(video.textTracks[i].kind === 'subtitles' || video.textTracks[i].kind === 'captions'){
                 video.textTracks[i].mode = "hidden";
             }
          }
        }
      } catch(e){}

      video.addEventListener("webkitbeginfullscreen", function() {
          try {
              if(video.textTracks && video.textTracks.length > 0) {
                  for(var i=0; i<video.textTracks.length; i++){
                      if(video.textTracks[i].kind === 'subtitles' || video.textTracks[i].kind === 'captions') video.textTracks[i].mode = "showing";
                  }
              }
          } catch(e){}
      });
      video.addEventListener("webkitendfullscreen", function() {
          try {
              if(video.textTracks && video.textTracks.length > 0) {
                  for(var i=0; i<video.textTracks.length; i++){
                      if(video.textTracks[i].kind === 'subtitles' || video.textTracks[i].kind === 'captions') video.textTracks[i].mode = "hidden";
                  }
              }
          } catch(e){}
      });

      var detailsEl = target.querySelector("details");
      if (detailsEl) {
          detailsEl.open = true; 
          var summaryEl = detailsEl.querySelector("summary");
          if (summaryEl) summaryEl.textContent = "字幕(シーン)はここをクリック";
      }

      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";
      }

      function parseTs(ts){
        if(!ts) return null;
        var p = ts.trim().split(":").map(function(x){return parseInt(x,10)||0;});
        if(p.length===2) return p[0]*60 + p[1];
        if(p.length===3) return p[0]*3600 + p[1]*60 + p[2];
        return null;
      }

      var rootSublist = target.querySelector(".dr5-sublist") || listContainer.parentElement;
      if (rootSublist) {
        rootSublist.addEventListener("click", function(e){
          var a = e.target.closest && e.target.closest("a.imk-cue[data-seek]");
          if(!a) return;
          e.preventDefault();
          var sec = parseTs(a.getAttribute("data-seek"));
          if(sec==null) return;
          try{ video.currentTime = sec; if(video.paused) video.play(); }catch(_){}
        });
      }

      video.addEventListener("timeupdate", function(){
        var desiredMode = isSpecialMode() ? "showing" : "hidden";
        try {
            if(video.textTracks && video.textTracks.length > 0){
                for(var i=0; i<video.textTracks.length; i++){
                    if((video.textTracks[i].kind === 'subtitles' || video.textTracks[i].kind === 'captions') && video.textTracks[i].mode !== desiredMode) {
                        video.textTracks[i].mode = desiredMode;
                    }
                }
            }
        } catch(e){}

        var cues = listContainer.querySelectorAll("a.imk-cue");
        if(cues.length === 0) return;
        var cur = video.currentTime;
        var activeA = null;

        for(var i=0; i<cues.length; i++){
            var t = parseTs(cues[i].getAttribute("data-seek"));
            if(t !== null && cur >= t - 0.5){ activeA = cues[i]; } 
            else if(t > cur){ 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" });
            }
        }
      });

      return true;
    }

    /* -----------------------------------------------
       監視タイマー（URL抜き出し＆ボタン表示を継続的に実行）
       ----------------------------------------------- */
    var checks = 0;
    var checkTimer = setInterval(function(){
      setupDownloadButton();
      var success = initSubtitles();
      checks++;
      if (success || checks > 20) { 
        clearInterval(checkTimer);
      }
    }, 500); 

    /* -----------------------------------------------
       3. 画面遷移時の停止機能
       ----------------------------------------------- */
    if (!window.scStopAndGo) {
      window.scStopAndGo = function(event, link){
        try{
          var mediaEls = document.querySelectorAll('video, audio');
          mediaEls.forEach(function(m){
            try{
              if (!m.paused) m.pause();
              if (document.pictureInPictureElement === m && document.exitPictureInPicture) {
                document.exitPictureInPicture().catch(function(){});
              }
            }catch(e){}
          });
        }finally{
          event.preventDefault();
          setTimeout(function(){
            if (link.target === '_blank') {
              window.open(link.href, '_blank');
            } else {
              window.location.href = link.href;
            }
          }, 50);
        }
        return false;
      };
    }
  })();
  </script>
</div>



<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-dots"/>



<p>最近、ちまたでもスマホの翻訳アプリ、翻訳機器などを目にすることが多くなってきました。しかも同時翻訳までできてしまうのには驚きです。ただ、いざ使おうと思うと、最初はお試しで無料ですが、有料に誘われます。しかもこの翻訳系のサービスは、サブスクが殆どで、毎月料金が発生する形になります。しかもその提供会社はたいていは海外の会社でUSドルベースが多く、円支払いでは毎月3000~5000円などと高額になり、趣味の域を超えます。</p>



<p>今回紹介する「音声認識字幕ちゃん」は、大学の教員をされている西村良太さんが個人で開発され一般に公開されている、<strong>「Webベースの、文字起こし＋同時翻訳アプリ」です。大変使いやすくしかも無料</strong>です。西村さんには感謝申し上げます。</p>



<p>このサイトで提供されている起動用アプリですが、Windows用のbatファイルは直接に動作するので使いやすいですが、Macはそのままクリックしても動かずシェルスクリプトでアプリ化して動かすようにしました。</p>



<figure class="wp-block-image size-large"><a href="https://imakat.com/rd.php?id=6Tp6Gvsb.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=6Tp6Gvsb.png" alt=""/></a><figcaption class="wp-element-caption">MacのAutomatorを起動→アプリケーションを選択→シェルスクリプトを実行を選択→「音声認識字幕ちゃん」からダウンロードしたmac用起動ファイルjimakuChan_nonStop.commandをテキストエディタで開く→最初の#!/bin/shの部分を除いて、Automatorへペースト→xxxxxx.appを作成。</figcaption></figure>



<p>Macは一手間増える感じもありますが、異なる設定条件の複数の字幕ちゃんを起動できるのは素晴らしいことです。</p>



<p>但し、OBSに組み込んで使う時などは、都度、翻訳なしにしたり、言語を切り替えたりすることもありそうで、そうした自由度は、<strong>Webベースの中で、設定を変更できる方が、都合がいい</strong>と思い、今回は、Webをそのまま使うような流れを考えてみました。</p>



<p>但し、日本語の認識、及び、翻訳のレベルは、それほど高いとは言えず、語学を勉強された方からすれば、不満でしょう。標準語でゆっくり話す必要があります。またネットワークの状況で認識の感度が振れます。補助的な用途としてであれば、使い物になるでしょう。</p>



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



<p>ビデオを補足します。</p>



<h4 class="wp-block-heading">１　「音声認識字幕ちゃん」はGoogle Chromeで起動する。</h4>



<p>同時翻訳を行う場合は、Google Script API-KEYが必要です。その取得については、</p>




<a rel="noopener" target="_blank" href="http://www.sayonari.com/trans_asr/index_asr.html" title="&#12522;&#12480;&#12452;&#12524;&#12463;&#12488;&#20013;... - &#38899;&#22768;&#35469;&#35672;&#23383;&#24149;&#12385;&#12419;&#12435;" class="blogcard-wrap external-blogcard-wrap a-wrap cf"><div class="blogcard external-blogcard eb-left cf"><div class="blogcard-label external-blogcard-label"><span class="fa"></span></div><figure class="blogcard-thumbnail external-blogcard-thumbnail"><img decoding="async" src="https://s.wordpress.com/mshots/v1/http%3A%2F%2Fwww.sayonari.com%2Ftrans_asr%2Findex_asr.html?w=160&#038;h=90" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="160" height="90" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">&#12522;&#12480;&#12452;&#12524;&#12463;&#12488;&#20013;... - &#38899;&#22768;&#35469;&#35672;&#23383;&#24149;&#12385;&#12419;&#12435;</div><div class="blogcard-snippet external-blogcard-snippet"></div></div><div class="blogcard-footer external-blogcard-footer cf"><div class="blogcard-site external-blogcard-site"><div class="blogcard-favicon external-blogcard-favicon"><img decoding="async" src="https://www.google.com/s2/favicons?domain=http://www.sayonari.com/trans_asr/index_asr.html" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">www.sayonari.com</div></div></div></div></a>



<p>の説明に従ってください。</p>



<figure class="wp-block-image size-large"><a href="https://imakat.com/rd.php?id=wta9OmaN.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=wta9OmaN.png" alt=""/></a></figure>



<p></p>



<h4 class="wp-block-heading">２　Google Chromeの起動時のウインドウサイズを固定できるようにする。</h4>



<p>「音声認識字幕ちゃん」の緑色の字幕欄を、OBSでウインドウキャプチャーして、読み込むことを想定していますが、もともとブラウザは、自由にフニャフニャとウインドウサイズを動かすように出来ているため、それを固定させるのが起動用アプリのわけですが、設定変更の自由度が欲しいのとMacの場合の手間の多さから、ブラウザの中の緑色の字幕欄のサイズを固定させて、ブラウザの中で、フォントを変更するようにしたいわけです。</p>



<p>そのために,ウィンドウサイズを自由に追加登録して、それをホットキーで選択できるプラグイン、Window Resizerを使います。</p>



<figure class="wp-block-image size-large"><a href="https://imakat.com/rd.php?id=ym4aFu3U.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=ym4aFu3U.png" alt=""/></a></figure>



<p></p>



<h4 class="wp-block-heading">３　「音声認識字幕ちゃん」を起動させるためのAppleスクリプトを作る。</h4>



<p>私の場合は、既定ブラウザはSafariにしています。確かに、Safariでは、「音声認識字幕ちゃん」の文字起こし翻訳が起動しません。「音声認識字幕ちゃん」のURLはChromeと紐付けする必要があります。</p>



<p>Appleスクリプトは簡単です。</p>



<figure class="wp-block-image size-large"><a href="https://imakat.com/rd.php?id=kmoY8RQO.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=kmoY8RQO.png" alt=""/></a></figure>



<p></p>



<p></p>



<h4 class="wp-block-heading">4　Stream Deckへマルチアクションとして登録する。</h4>



<p>二つのアクションを登録します。一つ目は、Chromeで「音声認識字幕ちゃん」を開く、Appleスクリプトです。二つ目は、そのChromeのサイズを合わせるアクションです。私はStream Deckを使いますが、他にもホットキー、ショートカットを登録できるアプリがありますので、活用ください。</p>



<figure class="wp-block-image size-large"><a href="https://imakat.com/rd.php?id=BUi2Uokj.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=BUi2Uokj.png" alt=""/></a></figure>



<h4 class="wp-block-heading">５　Stream Deckからマルチアクションを起動する。</h4>



<p>Webベースで起動すると、後から簡単に変更ができるので便利です。翻訳言語の変更削除、フォントの変更などがラクです。</p>



<figure class="wp-block-image size-large"><a href="https://imakat.com/rd.php?id=eTAfWvX7.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=eTAfWvX7.png" alt=""/></a></figure>



<p></p>



<figure class="wp-block-image size-large"><a href="https://imakat.com/rd.php?id=oiKYNIrO.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=oiKYNIrO.png" alt=""/></a></figure>



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



<p>器材記録</p>



<p>音声認識字幕ちゃん<br>Google Chrome<br>Window Resizer ( Chromeプラグイン)<br>Mac スクリプトエディタ<br>Stream Deck<br><br>Adobe Character Animator(スターター)<br>Final Cut Pro<br>Vrew(無料)<br>フリーボード<br>Mac mini M2<br>BGM: オリジナル音楽</p>



<p>以上です。</p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">18463</post-id>	</item>
	</channel>
</rss>
