<?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>GAS | imakat.com</title>
	<atom:link href="https://imakat.com/tag/gas/feed/" rel="self" type="application/rss+xml" />
	<link>https://imakat.com</link>
	<description>工夫と改善で人生をちょっと豊かに</description>
	<lastBuildDate>Tue, 10 Mar 2026 06:34:35 +0000</lastBuildDate>
	<language>ja</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=7.0</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>GAS | 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>【WordPress】「画像ライブラリ」を作ってみた。〜動画画像ライブラリ3〜</title>
		<link>https://imakat.com/2025/01/08/24997/</link>
		
		<dc:creator><![CDATA[imakat]]></dc:creator>
		<pubDate>Wed, 08 Jan 2025 05:24:47 +0000</pubDate>
				<category><![CDATA[マイライブラリ]]></category>
		<category><![CDATA[デジタル]]></category>
		<category><![CDATA[ものづくり]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[JSON]]></category>
		<category><![CDATA[GAS]]></category>
		<category><![CDATA[AppleScript]]></category>
		<category><![CDATA[WordPress]]></category>
		<guid isPermaLink="false">https://imakat.com/?p=24997</guid>

					<description><![CDATA[動画画像ライブラリー第３弾です。 Dropboxリンクは目立たないようにしたい。 これまで画像のURLリンクもDropboxを使えばいいと考えていて、Finderで右クリックして「Dropboxリンクをコピー」で得られた [&#8230;]]]></description>
										<content:encoded><![CDATA[
<figure class="wp-block-image size-large is-resized"><a href="https://imakat.com/rd.php?id=DUFdyZAj.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=DUFdyZAj.png" alt="" style="width:171px;height:auto"/></a></figure>



<p class="wp-block-paragraph">動画画像ライブラリー第３弾です。</p>



<h5 class="wp-block-heading">Dropboxリンクは目立たないようにしたい。</h5>



<p class="wp-block-paragraph">これまで画像のURLリンクもDropboxを使えばいいと考えていて、Finderで右クリックして「Dropboxリンクをコピー」で得られたリンクを、そのリンクの末尾のdl=0をraw=1に置き換えて使えば、それだけでいい。そのように思ってきました。</p>



<p class="wp-block-paragraph">Dropboxリンクの例は、下のようになります。</p>



<p class="wp-block-paragraph">(A)</p>



<figure class="wp-block-flexible-table-block-table"><table class="has-fixed-layout"><tbody><tr><td style="background-color:#fff7cc">https://www.dropbox.com/scl/fi/xxxxxxxxxx/v3_imakat.png?rlkey=xxxxxxxxxx&amp;raw=1</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">このDropboxリンクが安全性に優れている点は、クリックしてから実際に再生する時は更に<strong>ワンタイムトークンリンクに変換されてからブラウザで再生されます</strong>。(B)のように形を変えます。ブラウザへURLをコピペするとこうなります。しかもこのURLは一定の時間が経過すると無効になります。</p>



<p class="wp-block-paragraph">(B)</p>



<figure class="wp-block-flexible-table-block-table"><table class="has-fixed-layout"><tbody><tr><td style="background-color:#fff7cc">https://uce9dafc269d365818926846419f.dl.dropboxusercontent.com/cd/0/inline/Chthco4Tzn_2sCYS-ARStjz7FpZwTL9NkufD8Tw7M9-_bhwZ_g2zr2Qpz438qIwJbXdcAGwNaCcLlodnarQYoFRBZ9CrxJbNUHldMJX15qcEWuIQ1oz_T3QPgWrfmc-gB74/file#</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">WordPressの画像ブロック→URLから挿入→(A)を挿入→HTMLとして編集を選ぶと、以下のコードが記述されています。</p>



<p class="wp-block-paragraph">(C)</p>



<figure class="wp-block-flexible-table-block-table"><table class="has-fixed-layout"><tbody><tr><td style="background-color:#fff7cc">&lt;figure class=&#8221;wp-block-image size-large&#8221;&gt;&lt;img src=&#8221;https://www.dropbox.com/scl/fi/xxxxxxxxxx/v3_imakat.png?rlkey=xxxxxxxxxx&amp;raw=1&#8243; alt=&#8221;&#8221;/&gt;&lt;/figure&gt;</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">これで構わないとすれば、それまでのことですが、ブラウザからページのソースを読めば、上のコードは丸見えになります。Dropboxとすれば、(A)の情報が知れ渡るのは、あまり嬉しくないでしょう。「頭隠して尻隠さず」状態ということですからね。</p>



<p class="wp-block-paragraph">そこで、以下のように、AppSheetで、動的な画像サイトを作ることにしました。</p>



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



<p class="wp-block-paragraph">(D)</p>



<figure class="wp-block-flexible-table-block-table"><table class="has-fixed-layout"><tbody><tr><td style="background-color:#fff7cc">https://imakat.com/rd.php?id=57fYUfLE.png</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">これを、画像ブロック→「URLから挿入」に入れます。こうすると、(A)の部分は、WordPressに表示されなくなります。(C)から分かるように、メディアはDropboxから読み込んでいるのですが、読者からは、どこから読み込まれているのか分かりません（そのようにしたいわけです)。</p>



<h5 class="wp-block-heading" id="alternative-url">簡単に代替URLへ移行したい。</h5>



<p class="wp-block-paragraph">画像ライブラリ(D)を作るもう一つの目的が、 メディアのソースを、DropboxリンクからXserver、pCloudなど他のサーバーへ、簡単に、切り替えられるようにすることです。</p>



<p class="wp-block-paragraph">なぜって？やはりDropboxにもトラブルは起こりうるからです。</p>



<p class="wp-block-paragraph">こうした移行は、一般的には、プラグインを使って、WordPressのソースに書き込まれているURLを、直接に、置き換える方法が取られると思います。</p>



<p class="wp-block-paragraph">しかし、ソースにDropboxリンクを使っている場合はそうはいきません。Dropboxリンクはファイル名やローカルパスが外から分からないようにランダム文字列に置き換えられていますので、ローカルパスだけをサクッと置き換えることは出来ないのです。</p>



<p class="wp-block-paragraph">1点1点、Dropboxリンクと自宅サーバーURLを対応させた、マッピングファイルを作成する必要があります。丁寧にいうと、DropboxリンクとローカルパスとXserverサーバーURLの3つをマッピングさせたレコードを作成する、それをファイル上で右クリックしてあといくつかのクリック操作だけで済むようにしているところが、ポイント解説にて紹介するAppleScriptの特徴です。</p>



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



<p class="wp-block-paragraph">そしてこのマッピングファイル(Google spreadsheet)をJSONファイルとして、WordPressに送り込むようにします。マッピングファイルの更新は1日一回夜中に行います。</p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1FfdLcASztqVWOvbtehhBqTKn300ae0-SbJmNPa9CrlI/edit?usp=sharing">link_mapping.csvの重複レコードの整理について&#x1f4c4;<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph">ここまで書いてきて、私が、動的サイトの使いやすさにこだわる理由が分かっていただけたでしょうか。</p>



<p class="wp-block-paragraph">それでは次は、ポイント解説です。</p>



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



<p class="wp-block-paragraph">すみません。説明で使う素材を2024-11-28_15.50.35.pngに変更します。</p>



<h4 class="wp-block-heading">1 画像ライブラリ作成AppleScript</h4>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1dvudjxR_FGNqNm4XmaA0M4ohwWtO7ovHtxn5GFKFre4/edit?usp=sharing">画像ライブラリ作成 AppleScript&#x1f4c4;<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph">Dropboxリンクをコピーした後に、クイックアクションの中から「画像ライブラリー作成」を選びます。</p>



<p class="wp-block-paragraph">ポイントは、必ず「Dropboxリンクのコピー」を行った後で、クイックアクションに入り、「画像ライブラリ作成」を選ぶことです。いきなりクイックアクションに入ると、その段階では、古いクリップボードが残ったままになっています。</p>



<p class="wp-block-paragraph">そこで、一応、ポカよけとして、以下をメッセージ表示します。</p>



<figure class="wp-block-flexible-table-block-table"><table class="has-fixed-layout"><tbody><tr><td style="background-color:#fff7cc">cutjp_fileName: 2024-11-28_15.50.35.png<br>【注意】Dropboxリンクのコピーが行われていない可能性があります。再度Dropboxリンクのコピーを実行してください。</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">ここはひとまずOKを押して終了します。</p>



<p class="wp-block-paragraph">改めて、Dropboxリンクのコピーを実行した後で、クイックアクションの「画像ライブラリ作成」を選ぶと、<br></p>



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



<figure class="wp-block-flexible-table-block-table"><table class="has-fixed-layout"><tbody><tr><td style="background-color:#fff7cc">https://www.dropbox.com/scl/fi/xxxxxxxxxx/_2024-11-28_15.50.35.png?rlkey=xxxxxxxxxx&amp;dl=0<br>に関するデータを、csvファイルの1行として追加します。</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">と表示されます。</p>



<p class="wp-block-paragraph">ここでOKを押せば行追加が実行されます。</p>



<h5 class="wp-block-heading">日本語のファイル名の時の注意喚起</h5>



<p class="wp-block-paragraph">ファイル名に日本が混じる時、Dropboxリンクは日本語は削除されます。リンクはランダム文字列で作られますので、日本語が削除されてもユニークなリンクにはなりますが、日本語だけで出来たファイル名ですと、リンクを見ても、どのファイルか、想像すら出来ません。特に、複数の日本語だけのファイルが続きますと、どこまで処理したか、分からなくなります。そこで、日本語だけのファイル名を扱う時は、必ず、Dropboxリンクの取得が済んでいるか注意喚起をします。</p>



<p class="wp-block-paragraph"><a href="https://imakat.com/rd.php?id=CrEUQkyo.png" target="_blank">日本語のファイル名の時の注意喚起&#x1f4f7;</a></p>



<figure class="wp-block-flexible-table-block-table"><table class="has-fixed-layout"><tbody><tr><td style="background-color:#fff7cc">https://www.dropbox.com/scl/fi/xxxxxxxxxx/.png?rlkey=xxxxxxxxxx&amp;dl=0は、ファイル名が全て日本語のため、Dropboxリンクのコピーが済んでいるか否かが判別できません。自信がない場合は、キャンセルを押して、リンクのコピーを再実行ください。自信があればOKを押してcsvを追加ください。</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">ただ、出来れば日本語だけのファイル名は避けるのがいいです。</p>



<p class="wp-block-paragraph">AppleScriptの中では、wp_photo_library.csvへ行を追加しています。更に、link_mapping.csvにも行を追加します。</p>



<h4 class="wp-block-heading">2 追加したデータをWordPressで扱えるようにする</h4>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/17xQcuavGDB4SXsbn0ygwQcRk46JnLohn3M6fXp37LzE/edit?usp=sharing">importAndBackupCSV GAS&#x1f4c4;<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1odAmk9t8fq3GX1q0ZPwLyzWtv3kGiZcO8n3IRRxeKhw/edit?usp=sharing">createPhotoJson GAS&#x1f4c4;<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1VeQ6Hl6mzJeh5sdHU2v7FTdeYAqBGrCS2JyUE98Cums/edit?usp=sharing">im.php JSONから画像を表示　php&#x1f4c4;<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph">画像ライブラリ用のデータは、クイックアクションでwp_photo_library.csvに追記されます。このデータを動画画像idのシート3に書き込みます。ファイルURLおよび画像idはユニークです。シート3へ書き込んだ後、wp_photo_library.csvにあったデータは、backup_wp_photo_library.csvへ追記した後、wp_photo_library.csvはクリアします。新たに作った画像サイトは、今作業中のブログにすぐに使いたいので、１分おきの更新にします。</p>



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



<p class="wp-block-paragraph">少し待ちますが、新たに登録された場合は、AppSheetの動画画像ライブラリの画像メンテの先頭に、情報が表示されます。この中から、再生URLを取得して、WordPressの画像ブロック→URLから挿入するなど、利用します。</p>



<p class="wp-block-paragraph"></p>



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



<p class="wp-block-paragraph">このシリーズは、３回までで動画および画像を外部から読み込んで表示する方法、動的サイトの構築について説明してきました。次のシリーズでは、Dropboxリンクから複数のサーバーへ切り替える方法について、紹介します。</p>



<p class="wp-block-paragraph">以上です。<br><br></p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">24997</post-id>	</item>
		<item>
		<title>【WordPress】「動画ショートコード」を作ってみた。〜動画画像ライブラリ2〜</title>
		<link>https://imakat.com/2024/12/22/24182/</link>
		
		<dc:creator><![CDATA[imakat]]></dc:creator>
		<pubDate>Sat, 21 Dec 2024 23:39:00 +0000</pubDate>
				<category><![CDATA[マイライブラリ]]></category>
		<category><![CDATA[デジタル]]></category>
		<category><![CDATA[ものづくり]]></category>
		<category><![CDATA[GAS]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[ショートコード]]></category>
		<category><![CDATA[JSON]]></category>
		<guid isPermaLink="false">https://imakat.com/?p=24182</guid>

					<description><![CDATA[今回の投稿ですが、以前投稿した、「動画用の動的サイトを作ってみた」の続編の位置付けです。以前作った動的サイトは、&#8221;https://imakat.com/ds5?drid=38&#8220;の形式になっており、 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">今回の投稿ですが、以前投稿した、「<a href="https://imakat.com/2024/03/23/20191/" target="_blank">動画用の動的サイトを作ってみた</a>」の続編の位置付けです。以前作った動的サイトは、&#8221;<a href="https://imakat.com/ds5?drid=38" target="_blank">https://imakat.com/ds5?drid=38</a>&#8220;の形式になっており、どこにでもリンクができる便利モノです。この&#8221;ds5&#8243;の部分は、再生方法の違いの意味を持たせ、&#8221;drid&#8221;の部分は、再生サーバーの違いの意味を持たせました。</p>



<p class="wp-block-paragraph">しかしもっと簡単に考えて、まず、&#8221;38&#8243;の部分は自分で自由に設定できる動画idです。その動画idにどのサーバーにあるメディアをくっつけるかを決めます。ただし、VimeoやYouTubeの場合は、VimeoやYouTube側でidを発行するので、私がそれと別のidをさらに付けるのも管理を複雑にするだけなので、やめます。その結果、例えば、&#8221;38&#8243;はDropbox、&#8221;alt_38&#8243;は自宅サーバー、”885196700”はVimeo、&#8221;SRpWDu7gFC4&#8243;はYouTubeと動画idを決めることができます。重要なのは、動画idはユニークなキーであることです。</p>



<p class="wp-block-paragraph">以下のようにショートコードブロックに、ショートコードを埋め込むようにして、&#8221;&#8221;のvideoid(動画id)=の部分を書き換えれば、動画がサクッと置き換わるようになります。</p>



<p class="wp-block-paragraph">以下が実際のショートコード貼り付けによる動画です。</p>



<pre class="wp-block-code plaintext"><code>&#091;videoembed videoid="40"]</code></pre>


<div class="sc-dynamic-embed">
  <style>
  /* リンクの見た目を整える */
  .sc-dynamic-embed .sc-link-container { 
      display: flex; 
      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; }
  
  @media (max-width: 500px) {
    .sc-dynamic-embed .sc-link a { font-size: 13px; }
  }

  .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=40" target="_blank"
         onclick="return scStopAndGo(event, this);">
        👉低画質・枠外字幕はこちら
      </a>
    </p>
  </div>

  <style>
            :root{ --dr5emd-max: 1920px; }
            #subtitleOverlay, #scSubtitleOverlay, .overlay-cue, .band { display: none !important; opacity: 0 !important; }
            .imk-line { display: inline-block; width: 100%; border-radius: 2px; transition: background-color 0.1s; }
            .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; }
            
                .video-wrap{position:relative;width:100%;margin:0 auto}
                #myVideo{width:100%;height:auto;min-height:200px;display:block;background:#000;}</style><div class="dr5emd-container"><div class="video-wrap"><video id="myVideo" controls poster="https://imakat.com/rd.php?id=8vXz9WrK.png" playsinline preload="none" style="width:100%;height:auto;">  <source src="https://imakat.com/rd.php?id=6yncKhFV.mov" type="video/mp4">  <track src="https://imakat.com/rd.php?id=RvB8qB84.vtt" label="日本語" srclang="ja" kind="subtitles"></video></div><div class="dr5emd-sublist"><details><summary>字幕一覧(クリック)</summary> <p>
(<a href="#" class="imk-cue" data-seek="0:19">00:00:19</a>) 1) それでは今日は動画webという動画のライブラリーですね。<br>
(<a href="#" class="imk-cue" data-seek="0:30">00:00:30</a>) 2) それを手作りしましたのでそれを紹介していきます。<br>
(<a href="#" class="imk-cue" data-seek="0:36">00:00:36</a>) 3) まず基礎情報としてですね。<br>
(<a href="#" class="imk-cue" data-seek="0:38">00:00:38</a>) 4) ご覧のように有名な配信サーバーの名前がありますけど、<br>
(<a href="#" class="imk-cue" data-seek="0:45">00:00:45</a>) 5) 動画をですね。まず分類しておきます。<br>
(<a href="#" class="imk-cue" data-seek="0:50">00:00:50</a>) 6) 私としてはですね。<br>
(<a href="#" class="imk-cue" data-seek="0:52">00:00:52</a>) 7) Vimeo Dropbox YouTube あと 自宅サーバーですね、<br>
(<a href="#" class="imk-cue" data-seek="1:01">00:01:01</a>) 8) この自宅サーバーというのは自宅WordPressサーバーです。<br>
(<a href="#" class="imk-cue" data-seek="1:08">00:01:08</a>) 9) 以上Vimeo Dropbox YouTube<br>
(<a href="#" class="imk-cue" data-seek="1:14">00:01:14</a>) 10) 自宅サーバーと、この四つを主にですね、使っています。<br>
(<a href="#" class="imk-cue" data-seek="1:23">00:01:23</a>) 11) 次に、それに基づいて作成した動画が、<br>
(<a href="#" class="imk-cue" data-seek="1:31">00:01:31</a>) 12) 例えばこんな形でライブラリーになってます。<br>
(<a href="#" class="imk-cue" data-seek="1:37">00:01:37</a>) 13) この動画idっていうのが、IDコードですね。<br>
(<a href="#" class="imk-cue" data-seek="1:41">00:01:41</a>) 14) 個別の動画に対して振ったナンバー記号です。<br>
(<a href="#" class="imk-cue" data-seek="1:49">00:01:49</a>) 15) この39というのを例えば見てみますと<br>
(<a href="#" class="imk-cue" data-seek="1:52">00:01:52</a>) 16) これはDropbox、<br>
(<a href="#" class="imk-cue" data-seek="1:55">00:01:55</a>) 17) それと次にalt_38というのがこれが自宅サーバー、<br>
(<a href="#" class="imk-cue" data-seek="2:03">00:02:03</a>) 18) それからこの辺に、数字で長い、<br>
(<a href="#" class="imk-cue" data-seek="2:08">00:02:08</a>) 19) 長い数字になってるものが、Vimeo<br>
(<a href="#" class="imk-cue" data-seek="2:16">00:02:16</a>) 20) それからこの辺にあるランダム文字列ですね。<br>
(<a href="#" class="imk-cue" data-seek="2:21">00:02:21</a>) 21) 英数字のランダム文字列のものは、<br>
(<a href="#" class="imk-cue" data-seek="2:24">00:02:24</a>) 22) YouTube、というような形で動画idを振っております。<br>
(<a href="#" class="imk-cue" data-seek="2:35">00:02:35</a>) 23) それで例えばこの最初のですね、39を見てみますけども<br>
(<a href="#" class="imk-cue" data-seek="2:44">00:02:44</a>) 24) Editでどういう情報を登録しているかと言いますと、<br>
(<a href="#" class="imk-cue" data-seek="2:48">00:02:48</a>) 25) まず初めに動画idを振ります。<br>
(<a href="#" class="imk-cue" data-seek="2:51">00:02:51</a>) 26) それから題名をつける、動画の所在場所を選択します。<br>
(<a href="#" class="imk-cue" data-seek="3:01">00:03:01</a>) 27) ついにその動画の初期画像ファイルですね、それを入れます。<br>
(<a href="#" class="imk-cue" data-seek="3:05">00:03:05</a>) 28) 基本的にその動画サーバーと同じ位置になります。<br>
(<a href="#" class="imk-cue" data-seek="3:12">00:03:12</a>) 29) この場合はDropboxの、<br>
(<a href="#" class="imk-cue" data-seek="3:14">00:03:14</a>) 30) Dropboxリンクを入れてあります。<br>
(<a href="#" class="imk-cue" data-seek="3:19">00:03:19</a>) 31) あとそのファイルの物理的な所在位置を記録しておきます→後日、自動登録に改善→字幕一覧にリンク。<br>
(<a href="#" class="imk-cue" data-seek="3:26">00:03:26</a>) 32) あとそれとサムネイルとしての初期画像、<br>
(<a href="#" class="imk-cue" data-seek="3:30">00:03:30</a>) 33) 次に、これがメインである動画ファイルURL、<br>
(<a href="#" class="imk-cue" data-seek="3:38">00:03:38</a>) 34) これもこの場合はdropboxリンクです。<br>
(<a href="#" class="imk-cue" data-seek="3:43">00:03:43</a>) 35) その動画のファイルパス、次に字幕ファイルです<br>
(<a href="#" class="imk-cue" data-seek="3:52">00:03:52</a>) 36) ただしこの字幕ファイルにおいてはですね、<br>
(<a href="#" class="imk-cue" data-seek="3:56">00:03:56</a>) 37) WordPressの制約で、<br>
(<a href="#" class="imk-cue" data-seek="3:59">00:03:59</a>) 38) 配信するWordPressサーバーの中に置くということが、<br>
(<a href="#" class="imk-cue" data-seek="4:04">00:04:04</a>) 39) 条件になってますので、自分の外部配信サーバーの中にですね、<br>
(<a href="#" class="imk-cue" data-seek="4:14">00:04:14</a>) 40) vttファイルを置いているという例です。<br>
(<a href="#" class="imk-cue" data-seek="4:20">00:04:20</a>) 41) それから次にこれは字幕ファイルのパスです。<br>
(<a href="#" class="imk-cue" data-seek="4:25">00:04:25</a>) 42) ローカルパスです。次がその字幕一覧ファイルですね。<br>
(<a href="#" class="imk-cue" data-seek="4:30">00:04:30</a>) 43) 字幕を外側に一覧表として掲示するものです。<br>
(<a href="#" class="imk-cue" data-seek="4:35">00:04:35</a>) 44) これはDropboxリンクです。<br>
(<a href="#" class="imk-cue" data-seek="4:39">00:04:39</a>) 45) 次はそのパスですね、<br>
(<a href="#" class="imk-cue" data-seek="4:43">00:04:43</a>) 46) あとそれから必要ならば、説明のための文章、<br>
(<a href="#" class="imk-cue" data-seek="4:47">00:04:47</a>) 47) テキストファイルでくっつけるという形になっています。<br>
(<a href="#" class="imk-cue" data-seek="4:52">00:04:52</a>) 48) 普通はその公開しますので、公開を選びます。<br>
(<a href="#" class="imk-cue" data-seek="4:59">00:04:59</a>) 49) こうして作った情報をsaveしますと、<br>
(<a href="#" class="imk-cue" data-seek="5:02">00:05:02</a>) 50) キャンセルしますけども、既にあるので、そうすると<br>
(<a href="#" class="imk-cue" data-seek="5:10">00:05:10</a>) 51) そうするとこのようにですね、出来上がるわけですね。<br>
(<a href="#" class="imk-cue" data-seek="5:14">00:05:14</a>) 52) このJSON更新というのを押しますと<br>
(<a href="#" class="imk-cue" data-seek="5:17">00:05:17</a>) 53) そのファイルが外部のWordPressサーバーの方に飛んでいきます。<br>
(<a href="#" class="imk-cue" data-seek="5:32">00:05:32</a>) 54) これを具体的に再生してみたいと思います。<br>
(<a href="#" class="imk-cue" data-seek="6:03">00:06:03</a>) 55) このように出来上がっています。<br>
(<a href="#" class="imk-cue" data-seek="6:09">00:06:09</a>) 56) それから再生URLと合わせてですね、<br>
(<a href="#" class="imk-cue" data-seek="6:13">00:06:13</a>) 57) 投稿の中でも紹介していますが<br>
(<a href="#" class="imk-cue" data-seek="6:16">00:06:16</a>) 58) WordPressのショートコード、<br>
(<a href="#" class="imk-cue" data-seek="6:19">00:06:19</a>) 59) WordPressのショートコードブロックへ記入するものですけれども、<br>
(<a href="#" class="imk-cue" data-seek="6:25">00:06:25</a>) 60) このようにここに掲載してあります。以上です。<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></div>            <script>
            document.addEventListener("DOMContentLoaded", function(){
                var video = document.getElementById("myVideo");
                if(!video) return;

                            });
            </script>
            

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

    function protectVideo() {
      var target = wrapper ? wrapper : document;
      var mediaEls = target.querySelectorAll('video, audio');
      mediaEls.forEach(function(v){
        if(v.dataset.protected === 'true') return;
        v.dataset.protected = 'true';
        v.setAttribute('controlsList', 'nodownload');
        v.oncontextmenu = function() { return false; };
        v.addEventListener('contextmenu', function(e){ e.preventDefault(); return false; }, false);
      });
    }

    function initSubtitles() {
      var target = wrapper ? wrapper : document;
      var video = target.querySelector('video, audio');
      var listContainer = target.querySelector('details > p');
      
      if (!video) 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;
      }

      // 初期状態のセット（リストがなければ最初から showing に）
      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 = (!listContainer) ? "showing" : "hidden";
             }
          }
        }
      } catch(e){}

      // 字幕一覧が存在する場合のみ、リストのフォーマット処理を行う
      if (listContainer) {
          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";
          }

          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 ts = a.getAttribute("data-seek");
              if(!ts) return;
              var p = ts.trim().split(":").map(function(x){return parseInt(x,10)||0;});
              var sec = (p.length===2) ? p[0]*60+p[1] : (p.length===3 ? p[0]*3600+p[1]*60+p[2] : null);
              if(sec==null) return;
              try{ video.currentTime = sec; if(video.paused) video.play(); }catch(_){}
            });
          }
      }

      // ★ dr52.php と全く同じ「常時監視」のロジック
      // これにより、Safariが読み込み遅延を起こしても確実にONになります
      video.addEventListener("timeupdate", function(){
        var hasList = (listContainer !== null);
        var desiredMode = (isSpecialMode() || !hasList) ? "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){}

        // リストがない場合はこれ以降のハイライト処理をスキップ
        if (!hasList) return;

        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 ts = cues[i].getAttribute("data-seek");
            if(!ts) continue;
            var p = ts.trim().split(":").map(function(x){return parseInt(x,10)||0;});
            var t = (p.length===2) ? p[0]*60+p[1] : (p.length===3 ? p[0]*3600+p[1]*60+p[2] : null);
            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;
    }

    var checks = 0;
    var checkTimer = setInterval(function(){
      protectVideo();
      var success = initSubtitles();
      checks++;
      if (success || checks > 20) { 
        clearInterval(checkTimer);
      }
    }, 500); 

    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>



<p class="wp-block-paragraph">自分が作成した動画、YouTubeから探し出した動画などにidをつけて、動画ライブラリに登録しておけば、あとは利用が簡単です。</p>



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



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



<p class="wp-block-paragraph">それでは、この動画ショートコードの作成について、手順を説明します。下に全体図を掲載します。全部で４ステップになります。</p>



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



<h4 class="wp-block-heading"><span class="bold-red">❶</span>　サーバーごとに埋め込みコードテンプレートを作成する。</h4>



<p class="wp-block-paragraph">現在、用意しているのは、Dropbox、Vimeo、YouTube、自宅サーバーの４つになりますが、埋め込みコードの書き方は、それぞれ違いがあります。Dropboxと自宅サーバーは、WordPress動画プレーヤーの使用方法に従って記述し、Vimeo、YouTubeはサイトで提供される貼り付け、埋め込みコードを参考にして記述して、それらのテンプレートを作成します。</p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1BR-YsIQKI1zPJ_ASNPveT9bWyjHvi4ZSWqETW-IwPw4/edit?usp=sharing">Dropbox 埋め込みテンプレートの生成&#x1f4c4;<span class="fa fa-external-link external-icon anchor-icon"></span></a><br><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1zt39qvh0IpxxzjEiN8eHfbxkBpPSJ2lp-iOpY8OHtDM/edit?usp=sharing">Vimeo 埋め込みテンプレートの生成&#x1f4c4;<span class="fa fa-external-link external-icon anchor-icon"></span></a><br><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1YEnUd5ofUD_kwRVy1WE0Ga0RwsaaK7jSTz096_uuEcs/edit?usp=sharing">YouTube 埋め込みテンプレートの生成&#x1f4c4;<span class="fa fa-external-link external-icon anchor-icon"></span></a><br><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1xWKvYvja8jY5gHNHDq8E0MAa-VegQaOp1F6o1Q3T8tY/edit?usp=sharing">自宅サーバー 埋め込みテンプレートの生成&#x1f4c4;<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<h4 class="wp-block-heading"><span class="bold-red">❷</span>　動画idごとに埋め込みコードを生成する。</h4>



<p class="wp-block-paragraph">動画idファイル(spreadsheet)のS列(19列)に埋め込みコードを追記します。この埋め込みコードは、そのままWordPressのカスタムhtmlブロックへコピペすれば使えます。まず、その状態を作ります。</p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1eQqf0Ug8M_jeCAU4vFz4mfj1HQD-RE6wKaPMSyM09sw/edit?usp=sharing">動画idごとに埋め込みコードを生成GAS&#x1f4c4;<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<h4 class="wp-block-heading"><span class="bold-red">❸</span>　埋め込みコードをJSONに書き込み、WordPressサーバーへ送る。</h4>



<p class="wp-block-paragraph">埋め込みコードをコピペするだけでも便利ではありますが、欠点もあります。ソースコードは見る人が見れば外から丸わかりなのでURLをコピーできます。巡回ロボットを使えばもっと簡単です。それを拡散できるわけですが、やたら拡散されてしまうことは非常に迷惑なことですので避けたいです。「漠然とした拡散は迷惑である」とするこの感覚が、SNSとの決定的な違いになります。</p>



<p class="wp-block-paragraph">その意味で、「動的サイト」や「動画ショートコード」には、動画のURLまでは表記しませんので、やや、安全になります。埋め込みコードの欠点のあと一つは、複数箇所に書き込んでいて、もし動画他のURLを差し替えようとした時、複数箇所の修正をする必要があること、当たり前のことではありますが、これが結構ストレスになります。この点、元となる動画webサイトをメンテナンスすれば全部変更されます。</p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1yM4xRPzqiLS7Q-GdzeVRqRE3RSSxboIErOHssiX3V-k/edit?usp=sharing">埋め込みコードJSON生成GAS&#x1f4c4;<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph">videoembed.jsonファイルは、gd_wp_dataに書き出されます。gd_wp_dataフォルダはHazelによって監視されており変化した場合はTransmit5のFTPにより数分以内にXserverにあるWordPressサーバーへ更新されます。</p>



<h4 class="wp-block-heading"><span class="bold-red">❹</span>　動画ショートコードphpを作成する。</h4>



<p class="wp-block-paragraph">WordPressサーバー側では、投稿で記述されたショートコードとマッチするvideoembed.jsonファイル内の埋め込みコードに基づき、動画を再生します。</p>



<p class="wp-block-paragraph">その処理を行うphpを、Cocoon childのfunctions.phpに追記します。<br><br><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1cBKsLnwutNZZVO32spPKdBYV1hP5HCwQJlp-C2tj_fw/edit?usp=sharing">動画ショートコード起動php&#x1f4c4;<span class="fa fa-external-link external-icon anchor-icon"></span></a><br><br></p>



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



<p class="wp-block-paragraph">まとめになりますが、この動画ショートコードは、以前に投稿した、動的サイトの運用とセットになります。ぜひ、そちらもご一読ください→「<a href="https://imakat.com/2024/03/23/20191/" target="_blank">動画用の動的サイトを作ってみた</a>」。</p>



<p class="wp-block-paragraph">以上です。<br><br></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">24182</post-id>	</item>
		<item>
		<title>【WordPress】「動的サイト」を作ってみた。 〜動画画像ライブラリ1〜AppSheet GAS phpの利用〜</title>
		<link>https://imakat.com/2024/03/23/20191/</link>
		
		<dc:creator><![CDATA[imakat]]></dc:creator>
		<pubDate>Sat, 23 Mar 2024 01:40:00 +0000</pubDate>
				<category><![CDATA[マイライブラリ]]></category>
		<category><![CDATA[デジタル]]></category>
		<category><![CDATA[ものづくり]]></category>
		<category><![CDATA[GAS]]></category>
		<category><![CDATA[AppSheet]]></category>
		<category><![CDATA[動的サイト]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[電器屋]]></category>
		<category><![CDATA[パラメータ]]></category>
		<category><![CDATA[モジュール]]></category>
		<category><![CDATA[PHP]]></category>
		<guid isPermaLink="false">https://imakat.com/?p=20191</guid>

					<description><![CDATA[以前は、もう少し左脳右脳のバランス良く、ITをやったり音楽を作ったりしていたのですが、最近は、ITや動画関係に偏っています。そろそろもとのバランスに戻したいとは思っていますが。どうなることか。 動的サイトとは 今回は、動 [&#8230;]]]></description>
										<content:encoded><![CDATA[
<p class="wp-block-paragraph">以前は、もう少し左脳右脳のバランス良く、ITをやったり音楽を作ったりしていたのですが、最近は、ITや動画関係に偏っています。そろそろもとのバランスに戻したいとは思っていますが。どうなることか。</p>



<h4 class="wp-block-heading">動的サイトとは</h4>



<p class="wp-block-paragraph">今回は、動画用に、動的サイトなるものを作ってみました。</p>


<div class="sc-dynamic-embed">
  <style>
  /* リンクの見た目を整える */
  .sc-dynamic-embed .sc-link-container { 
      display: flex; 
      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; }
  
  @media (max-width: 500px) {
    .sc-dynamic-embed .sc-link a { font-size: 13px; }
  }

  .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=40" target="_blank"
         onclick="return scStopAndGo(event, this);">
        👉低画質・枠外字幕はこちら
      </a>
    </p>
  </div>

  <style>
            :root{ --dr5emd-max: 1920px; }
            #subtitleOverlay, #scSubtitleOverlay, .overlay-cue, .band { display: none !important; opacity: 0 !important; }
            .imk-line { display: inline-block; width: 100%; border-radius: 2px; transition: background-color 0.1s; }
            .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; }
            
                .video-wrap{position:relative;width:100%;margin:0 auto}
                #myVideo{width:100%;height:auto;min-height:200px;display:block;background:#000;}</style><div class="dr5emd-container"><div class="video-wrap"><video id="myVideo" controls poster="https://imakat.com/rd.php?id=8vXz9WrK.png" playsinline preload="none" style="width:100%;height:auto;">  <source src="https://imakat.com/rd.php?id=6yncKhFV.mov" type="video/mp4">  <track src="https://imakat.com/rd.php?id=RvB8qB84.vtt" label="日本語" srclang="ja" kind="subtitles"></video></div><div class="dr5emd-sublist"><details><summary>字幕一覧(クリック)</summary> <p>
(<a href="#" class="imk-cue" data-seek="0:19">00:00:19</a>) 1) それでは今日は動画webという動画のライブラリーですね。<br>
(<a href="#" class="imk-cue" data-seek="0:30">00:00:30</a>) 2) それを手作りしましたのでそれを紹介していきます。<br>
(<a href="#" class="imk-cue" data-seek="0:36">00:00:36</a>) 3) まず基礎情報としてですね。<br>
(<a href="#" class="imk-cue" data-seek="0:38">00:00:38</a>) 4) ご覧のように有名な配信サーバーの名前がありますけど、<br>
(<a href="#" class="imk-cue" data-seek="0:45">00:00:45</a>) 5) 動画をですね。まず分類しておきます。<br>
(<a href="#" class="imk-cue" data-seek="0:50">00:00:50</a>) 6) 私としてはですね。<br>
(<a href="#" class="imk-cue" data-seek="0:52">00:00:52</a>) 7) Vimeo Dropbox YouTube あと 自宅サーバーですね、<br>
(<a href="#" class="imk-cue" data-seek="1:01">00:01:01</a>) 8) この自宅サーバーというのは自宅WordPressサーバーです。<br>
(<a href="#" class="imk-cue" data-seek="1:08">00:01:08</a>) 9) 以上Vimeo Dropbox YouTube<br>
(<a href="#" class="imk-cue" data-seek="1:14">00:01:14</a>) 10) 自宅サーバーと、この四つを主にですね、使っています。<br>
(<a href="#" class="imk-cue" data-seek="1:23">00:01:23</a>) 11) 次に、それに基づいて作成した動画が、<br>
(<a href="#" class="imk-cue" data-seek="1:31">00:01:31</a>) 12) 例えばこんな形でライブラリーになってます。<br>
(<a href="#" class="imk-cue" data-seek="1:37">00:01:37</a>) 13) この動画idっていうのが、IDコードですね。<br>
(<a href="#" class="imk-cue" data-seek="1:41">00:01:41</a>) 14) 個別の動画に対して振ったナンバー記号です。<br>
(<a href="#" class="imk-cue" data-seek="1:49">00:01:49</a>) 15) この39というのを例えば見てみますと<br>
(<a href="#" class="imk-cue" data-seek="1:52">00:01:52</a>) 16) これはDropbox、<br>
(<a href="#" class="imk-cue" data-seek="1:55">00:01:55</a>) 17) それと次にalt_38というのがこれが自宅サーバー、<br>
(<a href="#" class="imk-cue" data-seek="2:03">00:02:03</a>) 18) それからこの辺に、数字で長い、<br>
(<a href="#" class="imk-cue" data-seek="2:08">00:02:08</a>) 19) 長い数字になってるものが、Vimeo<br>
(<a href="#" class="imk-cue" data-seek="2:16">00:02:16</a>) 20) それからこの辺にあるランダム文字列ですね。<br>
(<a href="#" class="imk-cue" data-seek="2:21">00:02:21</a>) 21) 英数字のランダム文字列のものは、<br>
(<a href="#" class="imk-cue" data-seek="2:24">00:02:24</a>) 22) YouTube、というような形で動画idを振っております。<br>
(<a href="#" class="imk-cue" data-seek="2:35">00:02:35</a>) 23) それで例えばこの最初のですね、39を見てみますけども<br>
(<a href="#" class="imk-cue" data-seek="2:44">00:02:44</a>) 24) Editでどういう情報を登録しているかと言いますと、<br>
(<a href="#" class="imk-cue" data-seek="2:48">00:02:48</a>) 25) まず初めに動画idを振ります。<br>
(<a href="#" class="imk-cue" data-seek="2:51">00:02:51</a>) 26) それから題名をつける、動画の所在場所を選択します。<br>
(<a href="#" class="imk-cue" data-seek="3:01">00:03:01</a>) 27) ついにその動画の初期画像ファイルですね、それを入れます。<br>
(<a href="#" class="imk-cue" data-seek="3:05">00:03:05</a>) 28) 基本的にその動画サーバーと同じ位置になります。<br>
(<a href="#" class="imk-cue" data-seek="3:12">00:03:12</a>) 29) この場合はDropboxの、<br>
(<a href="#" class="imk-cue" data-seek="3:14">00:03:14</a>) 30) Dropboxリンクを入れてあります。<br>
(<a href="#" class="imk-cue" data-seek="3:19">00:03:19</a>) 31) あとそのファイルの物理的な所在位置を記録しておきます→後日、自動登録に改善→字幕一覧にリンク。<br>
(<a href="#" class="imk-cue" data-seek="3:26">00:03:26</a>) 32) あとそれとサムネイルとしての初期画像、<br>
(<a href="#" class="imk-cue" data-seek="3:30">00:03:30</a>) 33) 次に、これがメインである動画ファイルURL、<br>
(<a href="#" class="imk-cue" data-seek="3:38">00:03:38</a>) 34) これもこの場合はdropboxリンクです。<br>
(<a href="#" class="imk-cue" data-seek="3:43">00:03:43</a>) 35) その動画のファイルパス、次に字幕ファイルです<br>
(<a href="#" class="imk-cue" data-seek="3:52">00:03:52</a>) 36) ただしこの字幕ファイルにおいてはですね、<br>
(<a href="#" class="imk-cue" data-seek="3:56">00:03:56</a>) 37) WordPressの制約で、<br>
(<a href="#" class="imk-cue" data-seek="3:59">00:03:59</a>) 38) 配信するWordPressサーバーの中に置くということが、<br>
(<a href="#" class="imk-cue" data-seek="4:04">00:04:04</a>) 39) 条件になってますので、自分の外部配信サーバーの中にですね、<br>
(<a href="#" class="imk-cue" data-seek="4:14">00:04:14</a>) 40) vttファイルを置いているという例です。<br>
(<a href="#" class="imk-cue" data-seek="4:20">00:04:20</a>) 41) それから次にこれは字幕ファイルのパスです。<br>
(<a href="#" class="imk-cue" data-seek="4:25">00:04:25</a>) 42) ローカルパスです。次がその字幕一覧ファイルですね。<br>
(<a href="#" class="imk-cue" data-seek="4:30">00:04:30</a>) 43) 字幕を外側に一覧表として掲示するものです。<br>
(<a href="#" class="imk-cue" data-seek="4:35">00:04:35</a>) 44) これはDropboxリンクです。<br>
(<a href="#" class="imk-cue" data-seek="4:39">00:04:39</a>) 45) 次はそのパスですね、<br>
(<a href="#" class="imk-cue" data-seek="4:43">00:04:43</a>) 46) あとそれから必要ならば、説明のための文章、<br>
(<a href="#" class="imk-cue" data-seek="4:47">00:04:47</a>) 47) テキストファイルでくっつけるという形になっています。<br>
(<a href="#" class="imk-cue" data-seek="4:52">00:04:52</a>) 48) 普通はその公開しますので、公開を選びます。<br>
(<a href="#" class="imk-cue" data-seek="4:59">00:04:59</a>) 49) こうして作った情報をsaveしますと、<br>
(<a href="#" class="imk-cue" data-seek="5:02">00:05:02</a>) 50) キャンセルしますけども、既にあるので、そうすると<br>
(<a href="#" class="imk-cue" data-seek="5:10">00:05:10</a>) 51) そうするとこのようにですね、出来上がるわけですね。<br>
(<a href="#" class="imk-cue" data-seek="5:14">00:05:14</a>) 52) このJSON更新というのを押しますと<br>
(<a href="#" class="imk-cue" data-seek="5:17">00:05:17</a>) 53) そのファイルが外部のWordPressサーバーの方に飛んでいきます。<br>
(<a href="#" class="imk-cue" data-seek="5:32">00:05:32</a>) 54) これを具体的に再生してみたいと思います。<br>
(<a href="#" class="imk-cue" data-seek="6:03">00:06:03</a>) 55) このように出来上がっています。<br>
(<a href="#" class="imk-cue" data-seek="6:09">00:06:09</a>) 56) それから再生URLと合わせてですね、<br>
(<a href="#" class="imk-cue" data-seek="6:13">00:06:13</a>) 57) 投稿の中でも紹介していますが<br>
(<a href="#" class="imk-cue" data-seek="6:16">00:06:16</a>) 58) WordPressのショートコード、<br>
(<a href="#" class="imk-cue" data-seek="6:19">00:06:19</a>) 59) WordPressのショートコードブロックへ記入するものですけれども、<br>
(<a href="#" class="imk-cue" data-seek="6:25">00:06:25</a>) 60) このようにここに掲載してあります。以上です。<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></div>            <script>
            document.addEventListener("DOMContentLoaded", function(){
                var video = document.getElementById("myVideo");
                if(!video) return;

                            });
            </script>
            

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

    function protectVideo() {
      var target = wrapper ? wrapper : document;
      var mediaEls = target.querySelectorAll('video, audio');
      mediaEls.forEach(function(v){
        if(v.dataset.protected === 'true') return;
        v.dataset.protected = 'true';
        v.setAttribute('controlsList', 'nodownload');
        v.oncontextmenu = function() { return false; };
        v.addEventListener('contextmenu', function(e){ e.preventDefault(); return false; }, false);
      });
    }

    function initSubtitles() {
      var target = wrapper ? wrapper : document;
      var video = target.querySelector('video, audio');
      var listContainer = target.querySelector('details > p');
      
      if (!video) 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;
      }

      // 初期状態のセット（リストがなければ最初から showing に）
      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 = (!listContainer) ? "showing" : "hidden";
             }
          }
        }
      } catch(e){}

      // 字幕一覧が存在する場合のみ、リストのフォーマット処理を行う
      if (listContainer) {
          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";
          }

          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 ts = a.getAttribute("data-seek");
              if(!ts) return;
              var p = ts.trim().split(":").map(function(x){return parseInt(x,10)||0;});
              var sec = (p.length===2) ? p[0]*60+p[1] : (p.length===3 ? p[0]*3600+p[1]*60+p[2] : null);
              if(sec==null) return;
              try{ video.currentTime = sec; if(video.paused) video.play(); }catch(_){}
            });
          }
      }

      // ★ dr52.php と全く同じ「常時監視」のロジック
      // これにより、Safariが読み込み遅延を起こしても確実にONになります
      video.addEventListener("timeupdate", function(){
        var hasList = (listContainer !== null);
        var desiredMode = (isSpecialMode() || !hasList) ? "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){}

        // リストがない場合はこれ以降のハイライト処理をスキップ
        if (!hasList) return;

        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 ts = cues[i].getAttribute("data-seek");
            if(!ts) continue;
            var p = ts.trim().split(":").map(function(x){return parseInt(x,10)||0;});
            var t = (p.length===2) ? p[0]*60+p[1] : (p.length===3 ? p[0]*3600+p[1]*60+p[2] : null);
            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;
    }

    var checks = 0;
    var checkTimer = setInterval(function(){
      protectVideo();
      var success = initSubtitles();
      checks++;
      if (success || checks > 20) { 
        clearInterval(checkTimer);
      }
    }, 500); 

    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>



<p class="wp-block-paragraph">具体的に構造で示すと以下です。</p>



<a rel="noopener" target="_blank" href="https://docs.google.com/drawings/d/10vn0mzfQbofDQvyMVfZhH-OIuvfyDUPRO3yFFOiK1dw/edit?usp=sharing">
<img decoding="async" src="https://docs.google.com/drawings/d/e/2PACX-1vQLJiJNTazFryMxHmIN_GEHlIHKa4sL7fh38mm6YYFFPrVhJpGprwg37IL5CegAjJrKol9DdeoeuA84/pub?w=960&amp;h=720" alt="Google図形描画">
</a>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">静的サイトと呼ばれるものは、こうした動画ページを構成するための情報を、一つのhtmlの中に、直接書き込んでガチガチに固めてしまいます。動画ファイルもhtmlと同じサーバーにアップロードします。それは高速に処理ができて安定しているわけです。しかし、何度も修正したい、差し替えたい、そうなると面倒でたまらない、そういうことになるわけです。</p>



<p class="wp-block-paragraph">そこで、コンテンツは、出来る限り外に置く。それを差し替えて使う。つまり、昔からみんなやっていることで、CDやDVD、カセットをプレーヤーに差し込む。そういうやり方です。こういうのをモジュール化する、と言います。</p>



<p class="wp-block-paragraph">動的サイトとは、こうしたモジュール化をすることにより、<strong>WordPressのダッシュボードを開くことなく</strong>、外側からデータ、パラメータを送り込むことによって、<strong>動画サイトを生成するやり方</strong>、そういうことになります。下が全体の流れです。</p>



<a rel="noopener" target="_blank" href="https://docs.google.com/drawings/d/1-_dKUc-8ZJBkDjKQuF0iF1lKmMB3D8piwEy_J8P_keY/edit">
<img decoding="async" src="https://docs.google.com/drawings/d/e/2PACX-1vTn1pqtRq5tsbBBXrHBjrN0IoR0p2yxLdPXcaBm5cptqRGp4QqFektl67RsG5Aj4qLft70HFFaOWswh/pub?w=960&amp;h=720" alt="Google図形描画">
</a>



<p class="wp-block-paragraph">この上の図表も、投稿の中の一種の動的パーツと言ってもいいかも知れません。この図表は、Google図形描画です。Google図形描画の公開埋め込みが表示されています。クリックすると、そこにGoogle図形描画の編集ページがリンクしています。読者は別画面で表示して拡大して閲覧できるわけですが、私にとっては直接に編集できるわけで、それが非常に便利です。</p>



<p class="wp-block-paragraph">さて、全部を細かく説明するのは、ちょっと骨が折れるので、赤丸で示した５つのポイントの説明と、サンプルのファイル、スクリプトをリンクします。</p>



<p class="wp-block-paragraph"></p>



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



<h4 class="wp-block-heading"><span class="red"><span class="fz-18px"><span class="fz-20px"><span class="fz-22px"><span class="fz-24px"><span class="fz-28px">❶</span></span></span></span></span></span>　GoogleSシートで、ファイルのレイアウトを決める。</h4>



<p class="wp-block-paragraph" id="link1">こういったミニシステムを作るとき、決め手となるのは、ファイルのレイアウト、つまり、Sシートでの列の決め方、になります。今回の場合は、２つのファイルを用意します。１つのトランザクションファイル（動画idファイル)と、１つのマスターファイル（動画関係付けファイル）です。</p>



<h6 class="wp-block-heading">（１）動画idファイルのレイアウト</h6>



<p class="wp-block-paragraph">下の表(クリックしてください)は、説明上、タテ書きにしてありますが、Sシートでは、項目名は、列の名前です。</p>



<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-202603101534150" class="toggle-checkbox" type="checkbox"/><label class="toggle-button" for="toggle-checkbox-202603101534150">シート1：</label><div class="toggle-content">
<figure class="wp-block-flexible-table-block-table is-scroll-on-pc is-scroll-on-mobile is-style-default"><table class="is-stacked-on-mobile"><tbody><tr><td style="width:25%;background-color:#fff7cc">項目名（列の名前）</td><td style="background-color:#fdf2f2">説明</td></tr><tr><td style="background-color:#fff7cc">(A)公開状況</td><td>選択肢は、公開、非公開だけにします。初期設定は公開。公開である行だけ、JSONファイルへ書き込みます。</td></tr><tr><td style="background-color:#fff7cc">(B)更新状況</td><td>TRUEとFALSEのみが入るようにします。JSONファイルの更新を実行するときは、TRUEにします。具体的にはAppSheetで更新ボタンを押します。JSONファイルの更新が済んだら、全行をFALSEにします。</td></tr><tr><td style="background-color:#fff7cc">(C)動画id</td><td>重複を避けて、自由に英数文字で設定します。但し、vimeoの場合は、vimeoが採番したidになります。動画所在場所に基づきidの範囲を割り付けることはありません。表示タイプによりphpを切り替えます。</td></tr><tr><td style="background-color:#fff7cc">(D)題名</td><td>自由に記入。</td></tr><tr><td style="background-color:#fff7cc">(E)動画所在場所</td><td>今のところ、vimeo dropbox youtube wordpressサーバー　自宅サーバー　その他。動画関係付けファイルからリンクします。</td></tr><tr><td style="background-color:#fff7cc">(F)初期画像ファイルURL</td><td>(*1)所在場所は、共有リンクが取得できる場所で、ブラウザからダウンロード操作なしで読み込み可能なリンクかチェックすること。</td></tr><tr><td style="background-color:#fff7cc">(G)初期画像ファイルパス</td><td>(*2)Macの場合は、ファイルパスを選択して右クリック→サービス→Finderに表示、により直接ファイルの修正可能。Windowsの場合は、ファイルパスをコピー→エクスプローラーへコピーして移動。</td></tr><tr><td style="background-color:#fff7cc">(H)動画ファイルURL</td><td>(*1)と同じ。</td></tr><tr><td style="background-color:#fff7cc">(I)動画ファイルパス</td><td>(*2)と同じ。<br></td></tr><tr><td style="background-color:#fff7cc">(J)字幕ファイルURL_vtt</td><td>(*1)と同じ。<span class="bold-red">字幕ファイルについては、WordPressサーバー内のwp-contentフォルダ以下に置く必要があります(Windowsで必要になる)。下記❺のFTP自動更新はWordPressサーバーへの更新なので、この対象フォルダの中に、字幕ファイルを入れておくようにします。従って、URLは例えば、</span><br><span class="bold-red">&#8220;https://xxxxx.com/wp-content/uploads/gd_wp_data/vttdata/yyyyy.vtt&#8221;という記述になります。</span></td></tr><tr><td style="background-color:#fff7cc">(K)字幕ファイルパス</td><td>(*2)と同じ。</td></tr><tr><td style="background-color:#fff7cc">(L)字幕一覧ファイルURL_txt</td><td>(*1)と同じ。</td></tr><tr><td style="background-color:#fff7cc">(M)字幕一覧ファイルパス</td><td>(*2)と同じ。</td></tr><tr><td style="background-color:#fff7cc">(N)説明ファイルURL_txt</td><td>(*1)と同じ。</td></tr><tr><td style="background-color:#fff7cc">(O)説明ファイルパス</td><td>(*2)と同じ。</td></tr><tr><td style="background-color:#fff7cc">(P)更新日時</td><td>AppSheetでEditされたとき、=now()で更新されるように設定。</td></tr><tr><td style="background-color:#fff7cc">(Q)補足説明</td><td>任意に記入。備忘欄。</td></tr><tr><td style="background-color:#fff7cc">(R)再生URL</td><td>[動画所在場所].[再生URLの形式]&amp;[動画id]</td></tr><tr><td style="background-color:#fff7cc">(S)完成埋め込みコード</td><td>動画作成の順番として、先に、「動的サイト」を作って、その次にWordPressへの埋め込みコードを、ここに集約される各項目をもとに、<a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1eQqf0Ug8M_jeCAU4vFz4mfj1HQD-RE6wKaPMSyM09sw/edit?usp=sharing">この「完成埋め込みコード」を作るためのGASを作る<span class="fa fa-external-link external-icon anchor-icon"></span></a>。</td></tr><tr><td style="background-color:#fff7cc">(T)初期画像サムネイル</td><td>動画webアプリから動画を探しやすいように、初期画像ファイルをここへドラッグ＆ドロップする。</td></tr></tbody></table></figure>
</div></div>



<p class="wp-block-paragraph"></p>



<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-202603101534151" class="toggle-checkbox" type="checkbox"/><label class="toggle-button" for="toggle-checkbox-202603101534151">シート2：</label><div class="toggle-content">
<figure class="wp-block-flexible-table-block-table is-scroll-on-pc is-scroll-on-mobile"><table class="is-stacked-on-mobile"><tbody><tr><td style="background-color:#fff7cc">項目名（列の名前）</td><td style="background-color:#fdf2f2">説明</td></tr><tr><td style="background-color:#fff7cc">(A)JSONファイル生成日時</td><td>GASにより記述します。JSONファイルの生成が終了したら、その日時を下行に追加します。</td></tr></tbody></table></figure>
</div></div>



<p class="wp-block-paragraph"></p>



<h6 class="wp-block-heading">（２）動画関係付けファイルのレイアウト</h6>



<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-202603101534152" class="toggle-checkbox" type="checkbox"/><label class="toggle-button" for="toggle-checkbox-202603101534152">名前関係付け：</label><div class="toggle-content">
<figure class="wp-block-flexible-table-block-table is-scroll-on-pc is-scroll-on-mobile"><table class="is-stacked-on-mobile"><tbody><tr><td style="background-color:#fff7cc">項目名（列の名前）</td><td style="background-color:#fdf2f2">説明</td></tr><tr><td style="background-color:#fff7cc">動画所在場所</td><td>キー項目です。今のところ、vimeo dropbox youtube wordpressサーバー　自宅サーバー　その他。動画idファイルへリンクします。</td></tr><tr><td style="background-color:#fff7cc">再生パス</td><td>再生URLの一部となり、https://xxxxxx.com/yy?id=zzzzzzz、のyyに当たる部分です。このyyは固定ページのパーマリンクです。phpテンプレートと１対１対応します。</td></tr><tr><td style="background-color:#fff7cc">idパラメータ</td><td>再生URLの一部となり、https://xxxxxx.com/yy?id=zzzzzzz、のidに当たる部分です。これを変更するとphpテンプレートの記述も変更が必要です。</td></tr><tr><td style="background-color:#fff7cc">再生URLの形式</td><td>https://xxxxxx.com/yy?id=、までの部分を確認の意味で生成しています。</td></tr><tr><td style="background-color:#fff7cc">補足説明</td><td>任意に記入。</td></tr><tr><td style="background-color:#fff7cc">埋め込みコード</td><td>WordPressへカスタムhtmlで埋め込むための埋め込みコード。パラメータ化。</td></tr><tr><td style="background-color:#fff7cc">対応条件</td><td>例えば&#8221;eee&#8221;の文字列を動画ipファイルの[シート1]の3列目にある文字列と置き換える場合は{&#8220;eee&#8221;:&#8221;3&#8243;}と表現します。</td></tr></tbody></table></figure>
</div></div>



<p class="wp-block-paragraph" id="link3"></p>



<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-202603101534153" class="toggle-checkbox" type="checkbox"/><label class="toggle-button" for="toggle-checkbox-202603101534153">マニュアル：</label><div class="toggle-content">
<figure class="wp-block-flexible-table-block-table is-scroll-on-pc is-scroll-on-mobile"><table class="is-stacked-on-mobile"><tbody><tr><td style="background-color:#fff7cc">項目名（列の名前）</td><td>説明</td></tr><tr><td style="background-color:#fff7cc">ID記事</td><td>自動的にランダムな文字列が入ります。キーに指定します。</td></tr><tr><td style="background-color:#fff7cc">タイトル</td><td> マニュアルの見出しです。</td></tr><tr><td style="background-color:#fff7cc">URL</td><td>Googleドキュメントなどを共有設定、閲覧者、にして、URLを貼り付けておきます。</td></tr><tr><td style="background-color:#fff7cc">表示順</td><td>数字を記入。</td></tr></tbody></table></figure>
</div></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-202603101534154" class="toggle-checkbox" type="checkbox"/><label class="toggle-button" for="toggle-checkbox-202603101534154">パス紐付け更新フラグ：</label><div class="toggle-content">
<figure class="wp-block-flexible-table-block-table is-scroll-on-pc is-scroll-on-mobile"><table class="is-stacked-on-mobile"><tbody><tr><td style="background-color:#fff7cc">項目名（列の名前）</td><td>説明</td></tr><tr><td style="background-color:#fff7cc">更新フラグ</td><td>更新後の状態はTRUE、更新を指示するときはFALSEに変えます。</td></tr><tr><td style="background-color:#fff7cc">更新日時</td><td> パス一覧表の更新が終了した日時となります。</td></tr></tbody></table></figure>
</div></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-202603101534155" class="toggle-checkbox" type="checkbox"/><label class="toggle-button" for="toggle-checkbox-202603101534155">パスURL紐付け：</label><div class="toggle-content">
<figure class="wp-block-flexible-table-block-table is-scroll-on-pc is-scroll-on-mobile"><table class="is-stacked-on-mobile"><tbody><tr><td style="background-color:#fff7cc">項目名（列の名前）</td><td>説明（ここは一覧表の表示のみです。編集はできません。)</td></tr><tr><td style="background-color:#fff7cc">動画id</td><td>動画idです。</td></tr><tr><td style="background-color:#fff7cc">題名</td><td> 動画の題名です。</td></tr><tr><td style="background-color:#fff7cc">動画保存場所</td><td>動画の保存場所です。</td></tr><tr><td style="background-color:#fff7cc">コンテンツURL</td><td>WordPress他で表示する初期画面、動画、字幕、説明のURLです。</td></tr><tr><td style="background-color:#fff7cc">パス</td><td>ローカルにあるパスです。</td></tr></tbody></table></figure>
</div></div>



<h6 class="wp-block-heading">（３）リンク</h6>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/spreadsheets/d/1rM0iO_s0zcO1VlIE29Fy72GBiSDG05hil8rCX31rDZw/edit?usp=sharing">GoogleSシート　参考　動画idファイル<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/spreadsheets/d/13D3v8FKCkFIySbYUFviYuFtN4UqiibhSqnhUKWdf9l0/edit?usp=sharing">GoogleSシート　参考　動画関係付けファイル<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<h4 class="wp-block-heading"><span class="red"><span class="fz-28px">❷</span></span>　AppSheetの設定を行う。</h4>



<p class="wp-block-paragraph"><span class="red">❶</span>のファイルレイアウトを、今一度、お目通ししていただくとして、AppSheetの設定に入っていきます。あちこち設定する場所が移るので、動画で解説します。動画内では参考2としていますが、参考、と読み替えてください。</p>



<p class="wp-block-paragraph"><a href="https://imakat.com/dr5?drid=11" target="_blank">動画用動的webサイトのためのAppSheetの作成 25分 (動画&#x1f3a5;)</a></p>



<p class="wp-block-paragraph"><a href="https://imakat.com/dr5/?drid=12" target="_blank">「AppSheetの作成」補足〜動画所在場所refについて2分(動画&#x1f3a5;)</a></p>



<h4 class="wp-block-heading"><span class="red"><span class="fz-28px">❸</span></span>　GASを作成する。</h4>



<p class="wp-block-paragraph">GoogleSシートの列については、以下のように、GASの中で、列名を直接に指定しているため、基本的には、列の追加変更削除は行わないようにしてください。<br>それでは次に、GASを使って、JSONファイルを生成するプログラムを作成します。</p>



<p class="wp-block-paragraph">はじめてのGAS約10分動画</p>


<div class="sc-dynamic-embed">
  <style>
  /* リンクの見た目を整える */
  .sc-dynamic-embed .sc-link-container { 
      display: flex; 
      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; }
  
  @media (max-width: 500px) {
    .sc-dynamic-embed .sc-link a { font-size: 13px; }
  }

  .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=17_2" target="_blank"
         onclick="return scStopAndGo(event, this);">
        👉低画質・枠外字幕はこちら
      </a>
    </p>
  </div>

  <style>
            :root{ --dr5emd-max: 1920px; }
            #subtitleOverlay, #scSubtitleOverlay, .overlay-cue, .band { display: none !important; opacity: 0 !important; }
            .imk-line { display: inline-block; width: 100%; border-radius: 2px; transition: background-color 0.1s; }
            .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; }
            
                .video-wrap{position:relative;width:100%;margin:0 auto}
                #myVideo{width:100%;height:auto;min-height:200px;display:block;background:#000;}</style><div class="dr5emd-container"><div class="video-wrap"><video id="myVideo" controls poster="https://imakat.com/rd.php?id=YXXibLZK.png" playsinline preload="none" style="width:100%;height:auto;">  <source src="https://imakat.com/rd.php?id=ysVoSInR.mp4" type="video/mp4">  <track src="https://imakat.com/rd.php?id=I4xhpTaJ.vtt" label="日本語" srclang="ja" kind="subtitles"></video></div><div class="dr5emd-sublist"><details translate="yes"><summary translate="yes">字幕一覧(クリック)</summary> <p translate="yes">
(<a href="#" class="imk-cue" data-seek="0:04" translate="no">00:00:04</a>)  今回ちょっと思い立ったことがありまして<br>
(<a href="#" class="imk-cue" data-seek="0:08" translate="no">00:00:08</a>)  色々 ITの世界 どんどん進展してますけども<br>
(<a href="#" class="imk-cue" data-seek="0:13" translate="no">00:00:13</a>)  だんだん歳をとってくると追いつけなくなることばかりですけども<br>
(<a href="#" class="imk-cue" data-seek="0:19" translate="no">00:00:19</a>)  ここは思い切って 自分として原点に戻って<br>
(<a href="#" class="imk-cue" data-seek="0:24" translate="no">00:00:24</a>)  すごく基礎というか そういうところから<br>
(<a href="#" class="imk-cue" data-seek="0:29" translate="no">00:00:29</a>)  もう一回スキルを 積み上げてみれるかどうか挑戦したいと思います<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:45" translate="no">00:00:45</a>)  Javascriptの中のひとつである<br>
(<a href="#" class="imk-cue" data-seek="0:50" translate="no">00:00:50</a>)  Google Apps Script<br>
(<a href="#" class="imk-cue" data-seek="0:55" translate="no">00:00:55</a>)  通称ガス、GASと呼ばれてるものなんですけども それについて勉強してみようかなと思ってます<br>
(<a href="#" class="imk-cue" data-seek="1:06" translate="no">00:01:06</a>)  実際はですね こういう書籍ですね<br>
(<a href="#" class="imk-cue" data-seek="1:13" translate="no">00:01:13</a>)  「Google Apps Script 完全入門」なんていう立派な本がありまして<br>
(<a href="#" class="imk-cue" data-seek="1:21" translate="no">00:01:21</a>)  これに基づいて コツコツと勉強していきたいと思います<br>
(<a href="#" class="imk-cue" data-seek="1:35" translate="no">00:01:35</a>)  そんな形でですね 進めていきたいと思います<br>
(<a href="#" class="imk-cue" data-seek="1:40" translate="no">00:01:40</a>)  まずですね このGoogle ガス、GASというのはですね どこに書き込むのかというと<br>
(<a href="#" class="imk-cue" data-seek="1:52" translate="no">00:01:52</a>)  スプレッドシートを使うんですね スプレッドシートの中のひとつの<br>
(<a href="#" class="imk-cue" data-seek="2:00" translate="no">00:02:00</a>)  拡張する機能の中にGASが入ってますので まずそれを使い出そうと思います<br>
(<a href="#" class="imk-cue" data-seek="2:08" translate="no">00:02:08</a>)  新規ですね この新規のファイルを作るんですけども Googleスプレッドシートを選びます<br>
(<a href="#" class="imk-cue" data-seek="2:19" translate="no">00:02:19</a>)  この中の空白のスプレッドシートを選びます<br>
(<a href="#" class="imk-cue" data-seek="2:26" translate="no">00:02:26</a>)  こんな感じですね<br>
(<a href="#" class="imk-cue" data-seek="2:30" translate="no">00:02:30</a>)  ちょっと角度広くしようか 全部めいっぱい<br>
(<a href="#" class="imk-cue" data-seek="2:36" translate="no">00:02:36</a>)  それで この中に ここに「拡張機能」ってあるんですね<br>
(<a href="#" class="imk-cue" data-seek="2:41" translate="no">00:02:41</a>)  これをクリックしますと その中に<br>
(<a href="#" class="imk-cue" data-seek="2:46" translate="no">00:02:46</a>)  Apps Script（アップス スクリプト）ってのがあります<br>
(<a href="#" class="imk-cue" data-seek="2:51" translate="no">00:02:51</a>)  この下にAppSheetってのがありますが これもまた素晴らしいアプリなんですけども<br>
(<a href="#" class="imk-cue" data-seek="2:56" translate="no">00:02:56</a>)  これはまた別の場面で勉強したいと思います<br>
(<a href="#" class="imk-cue" data-seek="3:00" translate="no">00:03:00</a>)  Apps Script これを選びます<br>
(<a href="#" class="imk-cue" data-seek="3:05" translate="no">00:03:05</a>)  はい そうすると あれ？Apps Scriptを選んでるのにそこに行かない？<br>
(<a href="#" class="imk-cue" data-seek="3:13" translate="no">00:03:13</a>)  あ、いった いった 読み込んでいます<br>
(<a href="#" class="imk-cue" data-seek="3:19" translate="no">00:03:19</a>)  はい それで Apps Script 無題のプロジェクトっていうのが出てきましたので<br>
(<a href="#" class="imk-cue" data-seek="3:26" translate="no">00:03:26</a>)  ここで最初に名前だけ付けておきましょうか<br>
(<a href="#" class="imk-cue" data-seek="3:31" translate="no">00:03:31</a>)  教科書通りに「はじめてのGAS」<br>
(<a href="#" class="imk-cue" data-seek="3:40" translate="no">00:03:40</a>)  「はじめてのGAS」とします<br>
(<a href="#" class="imk-cue" data-seek="3:49" translate="no">00:03:49</a>)  それで最初の宿題がですね<br>
(<a href="#" class="imk-cue" data-seek="3:55" translate="no">00:03:55</a>)  文字をちょっと実際 まず表示をしてみようという それをやってみたいと思います<br>
(<a href="#" class="imk-cue" data-seek="4:05" translate="no">00:04:05</a>)  まずここには最初 初期の段階では この<br>
(<a href="#" class="imk-cue" data-seek="4:12" translate="no">00:04:12</a>)  function myFunction カッコカッコ<br>
(<a href="#" class="imk-cue" data-seek="4:16" translate="no">00:04:16</a>)  こんなん入ってるんですけども いつもこれが出てくるということになります<br>
(<a href="#" class="imk-cue" data-seek="4:22" translate="no">00:04:22</a>)  この真ん中の2っていうところが 2行目が空いてますね ここに書き込みます<br>
(<a href="#" class="imk-cue" data-seek="4:31" translate="no">00:04:31</a>)  Browser（ブラウザ）と入れたいんですが もうすでに<br>
(<a href="#" class="imk-cue" data-seek="276:00" translate="no">04:36.00</a>)  選択肢 候補が出てきてますのでそれを選びます<br>
(<a href="#" class="imk-cue" data-seek="4:41" translate="no">00:04:41</a>)  ドット msgBox（メッセージボックス）入れたいんですが もうすでに候補が出てきてますね<br>
(<a href="#" class="imk-cue" data-seek="4:48" translate="no">00:04:48</a>)  これを選びます でそれで カッコ<br>
(<a href="#" class="imk-cue" data-seek="4:54" translate="no">00:04:54</a>)  カッコを入れると カッコ閉じるの方も自動的に出てくるんですね<br>
(<a href="#" class="imk-cue" data-seek="5:01" translate="no">00:05:01</a>)  上チョン 上チョンやると 閉める方の上チョンも出てくるんですね<br>
(<a href="#" class="imk-cue" data-seek="5:07" translate="no">00:05:07</a>)  ここに文字を入れます<br>
(<a href="#" class="imk-cue" data-seek="313:00" translate="no">05:13.00</a>)  「おはようございます」と入れたとします<br>
(<a href="#" class="imk-cue" data-seek="5:18" translate="no">00:05:18</a>)  はい これを表示したいので<br>
(<a href="#" class="imk-cue" data-seek="5:24" translate="no">00:05:24</a>)  まず一旦これを保存します<br>
(<a href="#" class="imk-cue" data-seek="5:28" translate="no">00:05:28</a>)  保存した後 実行をします<br>
(<a href="#" class="imk-cue" data-seek="5:35" translate="no">00:05:35</a>)  ところがこれ 実行 すぐできないんですね<br>
(<a href="#" class="imk-cue" data-seek="340:00" translate="no">05:40.00</a>)  それは 承認が必要ですということで出てきますので<br>
(<a href="#" class="imk-cue" data-seek="5:52" translate="no">00:05:52</a>)  これを進めます 権限を承認<br>
(<a href="#" class="imk-cue" data-seek="5:57" translate="no">00:05:57</a>)  これはまず私のアカウントですね Googleアカウントを選びます<br>
(<a href="#" class="imk-cue" data-seek="6:05" translate="no">00:06:05</a>)  そうすると そこで<br>
(<a href="#" class="imk-cue" data-seek="6:10" translate="no">00:06:10</a>)  「このアプリはGoogleで確認されていません」と びっくりするようなコメントが出てくるんですけども<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:25" translate="no">00:06:25</a>)  そして 見てみまして そうすると下の方に<br>
(<a href="#" class="imk-cue" data-seek="6:36" translate="no">00:06:36</a>)  「リスクを理解しディベロッパーを信頼できる場合のみ続行してください」って出ます<br>
(<a href="#" class="imk-cue" data-seek="6:46" translate="no">00:06:46</a>)  で「はじめてのGASに移動」と出てますので<br>
(<a href="#" class="imk-cue" data-seek="6:51" translate="no">00:06:51</a>)  これでいいもんですから これをクリックします<br>
(<a href="#" class="imk-cue" data-seek="6:56" translate="no">00:06:56</a>)  そうすると 「はじめてのGASがGoogleアカウントへのアクセスをリクエストしています」と書いてあって<br>
(<a href="#" class="imk-cue" data-seek="7:08" translate="no">00:07:08</a>)  下の方に「許可」ってあるんで この許可をクリックします<br>
(<a href="#" class="imk-cue" data-seek="7:19" translate="no">00:07:19</a>)  これでいいと思います そしたらこれあれですね 「実行開始」って出ましたねすでに<br>
(<a href="#" class="imk-cue" data-seek="7:25" translate="no">00:07:25</a>)  ということはすでに動いているんで<br>
(<a href="#" class="imk-cue" data-seek="7:29" translate="no">00:07:29</a>)  この無題の...スプレッドシート名 名前変えたはずだけど<br>
(<a href="#" class="imk-cue" data-seek="7:35" translate="no">00:07:35</a>)  スプレッドシート名は無題のスプレッドシートのままか<br>
(<a href="#" class="imk-cue" data-seek="7:38" translate="no">00:07:38</a>)  ここに「おはようございます」って出てるんですね<br>
(<a href="#" class="imk-cue" data-seek="7:44" translate="no">00:07:44</a>)  OKを押します<br>
(<a href="#" class="imk-cue" data-seek="7:47" translate="no">00:07:47</a>)  もう一回戻ります<br>
(<a href="#" class="imk-cue" data-seek="7:51" translate="no">00:07:51</a>)  GASのタイトルは「はじめてのGAS」です<br>
(<a href="#" class="imk-cue" data-seek="7:55" translate="no">00:07:55</a>)  今 多少命令文を入れたのがあります 実質1個だけね<br>
(<a href="#" class="imk-cue" data-seek="8:00" translate="no">00:08:00</a>)  これをもう一回 実行します<br>
(<a href="#" class="imk-cue" data-seek="8:04" translate="no">00:08:04</a>)  そうすると 実行はスプレッドシート上で起きていて<br>
(<a href="#" class="imk-cue" data-seek="8:12" translate="no">00:08:12</a>)  このように「おはようございます」と表示されていますので<br>
(<a href="#" class="imk-cue" data-seek="8:16" translate="no">00:08:16</a>)  OKを押すと 実行が完了します<br>
(<a href="#" class="imk-cue" data-seek="8:25" translate="no">00:08:25</a>)  ということでですね 一連の流れが終了するということになります<br>
(<a href="#" class="imk-cue" data-seek="8:31" translate="no">00:08:31</a>)  ちょうどこのスプレッドシートもあれですね なんだっけ 「はじめてのGAS」にしときましょうかこれ<br>
(<a href="#" class="imk-cue" data-seek="8:41" translate="no">00:08:41</a>)  その方が分かりがいいよね<br>
(<a href="#" class="imk-cue" data-seek="526:00" translate="no">08:46.00</a>)  「はじめてのGAS」としておきます<br>
(<a href="#" class="imk-cue" data-seek="547:00" translate="no">09:07.00</a>)  そうすると 「はじめてのGAS」と<br>
(<a href="#" class="imk-cue" data-seek="552:00" translate="no">09:12.00</a>)  これが作れたということですね<br>
(<a href="#" class="imk-cue" data-seek="557:00" translate="no">09:17.00</a>)  はい それでは<br>
(<a href="#" class="imk-cue" data-seek="563:00" translate="no">09:23.00</a>)  GASを作り始めるベースの勉強を今日はしました 以上です<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></div>            <script>
            document.addEventListener("DOMContentLoaded", function(){
                var video = document.getElementById("myVideo");
                if(!video) return;

                            });
            </script>
            

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

    function protectVideo() {
      var target = wrapper ? wrapper : document;
      var mediaEls = target.querySelectorAll('video, audio');
      mediaEls.forEach(function(v){
        if(v.dataset.protected === 'true') return;
        v.dataset.protected = 'true';
        v.setAttribute('controlsList', 'nodownload');
        v.oncontextmenu = function() { return false; };
        v.addEventListener('contextmenu', function(e){ e.preventDefault(); return false; }, false);
      });
    }

    function initSubtitles() {
      var target = wrapper ? wrapper : document;
      var video = target.querySelector('video, audio');
      var listContainer = target.querySelector('details > p');
      
      if (!video) 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;
      }

      // 初期状態のセット（リストがなければ最初から showing に）
      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 = (!listContainer) ? "showing" : "hidden";
             }
          }
        }
      } catch(e){}

      // 字幕一覧が存在する場合のみ、リストのフォーマット処理を行う
      if (listContainer) {
          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";
          }

          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 ts = a.getAttribute("data-seek");
              if(!ts) return;
              var p = ts.trim().split(":").map(function(x){return parseInt(x,10)||0;});
              var sec = (p.length===2) ? p[0]*60+p[1] : (p.length===3 ? p[0]*3600+p[1]*60+p[2] : null);
              if(sec==null) return;
              try{ video.currentTime = sec; if(video.paused) video.play(); }catch(_){}
            });
          }
      }

      // ★ dr52.php と全く同じ「常時監視」のロジック
      // これにより、Safariが読み込み遅延を起こしても確実にONになります
      video.addEventListener("timeupdate", function(){
        var hasList = (listContainer !== null);
        var desiredMode = (isSpecialMode() || !hasList) ? "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){}

        // リストがない場合はこれ以降のハイライト処理をスキップ
        if (!hasList) return;

        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 ts = cues[i].getAttribute("data-seek");
            if(!ts) continue;
            var p = ts.trim().split(":").map(function(x){return parseInt(x,10)||0;});
            var t = (p.length===2) ? p[0]*60+p[1] : (p.length===3 ? p[0]*3600+p[1]*60+p[2] : null);
            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;
    }

    var checks = 0;
    var checkTimer = setInterval(function(){
      protectVideo();
      var success = initSubtitles();
      checks++;
      if (success || checks > 20) { 
        clearInterval(checkTimer);
      }
    }, 500); 

    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>



<h6 class="wp-block-heading">（１）JSONファイルの生成条件</h6>



<p class="wp-block-paragraph">1) &#8220;シート1&#8243;のB列に、一つでもTRUEがある場合は、下記のJSONファイルの上書きを実行して、上書きが終了したら、B列の値を全てFALSEに置き換える。</p>



<p class="wp-block-paragraph">2) JSONファイルの先頭に&#8221;[&#8220;、末尾に&#8221;]&#8221;を入れる。</p>



<p class="wp-block-paragraph">3) &#8220;シート1&#8243;のA列の値が&#8221;公開&#8221;の場合、C F H J L N列のデータを書き込む。無しの場合は空欄&#8221;&#8221;。</p>



<p class="wp-block-paragraph">4) 全てのデータの書き込みが終わったら、&#8221;シート2&#8243;のA列に、その日時を入れた行を追加する。</p>



<p class="wp-block-paragraph">5) GASは、トリガー設定、実行関数：generateJSON 　イベントのソースを選択：スプレッドシートから　イベントの種類を選択：変更時　エラー通知設定；毎日通知を受け取る。</p>



<h6 class="wp-block-heading">（２）リンク</h6>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1L6trw9qNC8ohvoIl01cZ3O9to3bWaq0vctxHHsISD_4/edit?usp=sharing">JSONファイル生成のGAS<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<h4 class="wp-block-heading"><span class="red"><span class="fz-28px">❹</span></span>　WordPressテンプレート用phpを作成する。</h4>



<p class="wp-block-paragraph">動的サイトを置く場所は、WordPressの固定ページにしました。今のところ、WordPressプレーヤーを組み込んだ固定ページを２パターン、vimeoのプレーヤーを組み込んだ固定ページを2パターン、dropbox利用のものを2パターン、YouTube利用のものを2パターン、計8パターンのテンプレート用phpを作りました。固定ページ自体は、ほぼ空っぽで、URLでの指示に対応するテンプレートphpに、形式の全ての情報が入っています。</p>



<p class="wp-block-paragraph"><strong>YouTubeの難儀さ</strong></p>



<p class="wp-block-paragraph">YouTubeを組み込む場合は、同じようにYouTube用のphpを作ることになります。ただしYouTubeは、ピクチャーインピクチャー(PIP)といいますが画面を分離して外に表示する方法を使うのが非常に厄介です。つまり、動画の用途がブログ記事の補強である場合は、ブログを読みながら動画を見るわけです。パソコンであればウインドウ分離したりブラウザを2つ使うなど、何らかの工夫ができますが、スマホでは画面が小さくてそうはいきません。スマホでは、動画を上にPIPで表示して、下でブログをスクロールしながら読む、そういう使い方になります。そのような使い方をYouTubeでやろうと思うと、ブログを発信している側の工夫では困難で、受信者側、視聴者側に、アプリやプラグインを入れるなりの面倒をかける事になります(<a rel="noopener" target="_blank" href="https://youtu.be/Si0DM1dNuaY?si=5BGNmuIKEiOM6Lbe">→方法<span class="fa fa-external-link external-icon anchor-icon"></span></a>)。したがって、私としては、それを前提とは考えたくないです。その意味で、YouTubeを選択肢に入れるかどうかはYouTube側への改善期待です。今のところ、Vimeo、Dropbox、自宅サーバーを使うつもりなので、視聴者は何も用意することなくPIPが使えるはずです。</p>



<p class="wp-block-paragraph">なお、Googleドライブに入れた動画をWordPressで表示する方法は、GASやAppSheetが同じドライブ内で動作するので非常に生産性が高そうなのですが、今のところ、ユーザーの自由にさせてもらえない制約があり残念です。</p>



<p class="wp-block-paragraph"><strong>Mac、iPhoneは反面教師</strong></p>



<p class="wp-block-paragraph">最近感じる事ですが、WindowsやAndroidは、AppleのOSと比べると遜色なく進歩している、と思います。しかし、セキュリティについてはAppleの方がしっかりしている、と思います。ですので、WindowsやAndroidでは動くのにAppleでは動かないことがままあります。逆に、Appleで動く場合は大抵WindowsやAndroidでも動くということです。何が言いたいのかというと、最初に、高いハードルであるAppleで動作するようにしておけば、あとがラクになる可能性が高いと思います。いやあくまで傾向としてです。</p>



<h6 class="wp-block-heading">（１）リンク</h6>



<p class="wp-block-paragraph">一応、YouTubeも再生できるように、phpを作成しておきました。</p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1iDrivgAVEtYlGCflC584e0LG4xiBUvMC02Hk3rPgCeI/edit?usp=sharing">vimeo vm5 WordPressリンク用　繰り返し再生なし　php<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1k9QiuVYMYVYVAESM4UXB9GnkRU_g_LSMK7RXYvpItj8/edit?usp=sharing">vimeo vm6 WordPressリンク用　繰り返し再生あり　php<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1PntTo55mw9C0FQMRmpznd3Ab3C3Db6SPmo9XiVKlSfg/edit?usp=sharing">dropbox dr5 動画枠内字幕　WordPressリンク用php<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1zZmZ_bqwHcelj8nY4wxo30J2mwqEufV6kUF_HGYXQOE/edit?usp=sharing">dropbox ds5 動画枠外字幕　WordPressリンク用php<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1CAnSo6df3AX5VGP70UD9-6xmgWt9QQILzKd7uUA9GKk/edit">自宅サーバー_mh2_動画枠内字幕_WordPressリンク用php<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1ZC6Q2xWbbahcuF6yUQlx_wHKVPdHSOcltIWgBFt8pzw/edit">自宅サーバー_mh1_動画枠外字幕_WordPressリンク用php<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/11drdSQ9UvESntwn6t6MrUuHYKQVuLxWfs8zq4nbSNGY/edit?usp=sharing">youtube yt1 繰り返し再生なし php<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/1fwNrSPp8yVHszgz6hEuALuTyVHgI7NGbhC_DRihVExI/edit?usp=sharing">youtube yt2 繰り返し再生あり php<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



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



<h4 class="wp-block-heading"><span class="red"><span class="fz-28px">❺</span></span>　JSONファイルの自動FTPを組み込む。</h4>



<p class="wp-block-paragraph">一応、以下のように、JSONファイルの自動FTPを組み込みました。多少、ギクシャクしたりクラッシュすることもあります。まず、Transmit5でFTP更新がアプリ起動だけで動くようにAutomatorでアプリ化、次にHazelでフォルダ監視をして、フォルダが変化したらアプリが起動するようにしました。決め手は、HazelにAppleScriptが組み込み可能なところです。<br>Hazelに組み込んだAppleScript：</p>



<figure class="wp-block-flexible-table-block-table"><table class="has-fixed-layout"><tbody><tr><td>tell application &#8220;gd_wp_dataアップロード&#8221;<br>	activate<br>end tell</td></tr></tbody></table></figure>



<p class="wp-block-paragraph"><br>但し、Macの起動が必要なので、宅外の場合は、iPhoneのFTPアプリで手動で更新します。</p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://panic.com/jp/transmit/">Transmit5(外部サイト)<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<figure class="wp-block-image size-large"><a href="https://imakat.com/rd.php?id=eKvee4AB.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=eKvee4AB.png" alt=""/></a><figcaption class="wp-element-caption">Transmitの設定</figcaption></figure>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://tech-camp.in/note/pickup/99875/">MacのAutomatorについて(外部サイト)<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<figure class="wp-block-image size-large"><a href="https://imakat.com/rd.php?id=eKvee4AB.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=eKvee4AB.png" alt=""/></a><figcaption class="wp-element-caption">Automatorの設定</figcaption></figure>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://webrandum.net/hazel/">Hazelの説明のサイトは、丁寧な日本語でのものが見当たりませんが、ちょっと古いがこれでしょうか。(外部サイト)<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph"><strong>Hazelの工夫：</strong><br>Hazelですが、自分のフォルダ直下の変化とサブフォルダ内の変化に対して、アクションを起動させるようにするためには、<strong>先頭のルールで、「Kind is Folder」Do the following&#8230;で「Run rules on folder contents」を設定します。次のルール以降で、アクションを設定していきます。今回は、「Extensionがvttのファイルは、それをvttdataフォルダへコピーする」かつ「Transmit5(FTPアプリ)によりWordPressサーバーへ更新する」アクションになります。</strong></p>



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



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



<p class="wp-block-paragraph">上記の方法は、常にMacが起動している環境があれば、悩みは減ります。現在Mac miniを使っていますが、最近のMac miniは発熱も少なく、常時稼働用に向いているでしょう。遅かれ早かれ<a rel="noopener" target="_blank" href="https://docs.google.com/drawings/d/1mozSB2dzBnmHfDj8ctTL1jRNuMv06Kt2qDeCffBb47U/edit?usp=sharing">こんな形<span class="fa fa-external-link external-icon anchor-icon"></span></a>が良さそうです。</p>



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



<p class="wp-block-paragraph"><strong>（１）ローカルパスを記録しておくことが必要</strong>：</p>



<p class="wp-block-paragraph"><strong><span class="bold-red">訂正前の開始点：</span></strong></p>



<p class="wp-block-paragraph">この投稿で書くと埋もれてしまうので、いずれ別の投稿にしますが、Dropboxなどクラウドサーバーで提供されるアクセストークン型リンクURLですが、何らかの理由で変更されてしまうリスクがあります。そのトラブルの修復のためには、「リンク元であるローカルファイルの場所」がすぐに特定されることが、必須です。その場所のことをローカルパスと言いますが以下では簡単にパスと称しています。</p>



<p class="wp-block-paragraph">具体的には、動画web AppSheetでは、動画の構成には、初期画面、動画、字幕、字幕一覧、説明の５種類のファイルを使えるようにしていますが、それらのURLとパスの両方を登録するようにしています。パスの上で右クリックして、Finder内で表示して、内容を確認できます。</p>



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



<p class="wp-block-paragraph">そしてこれらの、動画を構成するために使われたファイルのパスの一覧表を更新するアプリをGASで作成しています。</p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://docs.google.com/document/d/19rFcNHRGxZOz6WTOVnolOAcB8y8RWz-AEHSLLkekdhc/edit?usp=sharing">パス一覧表作成のGAS<span class="fa fa-external-link external-icon anchor-icon"></span></a></p>



<p class="wp-block-paragraph"><strong>（２）出来れば代替URLも登録しておく。</strong></p>



<p class="wp-block-paragraph">VimeoやYouTubeの使用には全く気にしないことですが、私の場合は、その多くがDropboxリンクです。リンク切れ他何らかのトラブルで、再生不可になる可能性は否定はできません。その時の一時的な切り替え先として自宅サーバーを考えています。従って、（１）のローカルパスに加えて代替URLも登録しておく方がいいと思っています。ここについては後日、投稿します。</p>



<p class="wp-block-paragraph"><strong><span class="bold-red">訂正前の終了点：</span></strong></p>



<p class="wp-block-paragraph"><span class="bold-red">訂正後の</span><span class="bold-red">開始点</span><span class="bold-red">：</span></p>



<p class="wp-block-paragraph"><strong>パス一覧表からマッピング表への変更：</strong></p>



<p class="wp-block-paragraph">パス一覧表ですが、コンセプトがちょっと中途半端でしたので、目的を代替対策に絞って、そのためのデータとして、マッピング表を作ることにしました。以下の4つの条件を満たすことにしました。</p>



<p class="wp-block-paragraph">（１）動画や画像を収めるローカルフォルダを決めておくこと。<br>（２）使いやすいようにライブラリーを作ること。<br>（３）そのフォルダ自体を、配信可能なクラウドストレージ例えばDropboxと同期させて、Dropboxリンクが取得できるようにしておくこと。<br>（４）Dropboxのトラブル時の代替として、別の配信可能なサーバーに、そのフォルダをバックアップしておくこと。<br><a href="https://imakat.com/2025/01/08/24997/#alternative-url" target="_blank">こちらの記事をお読みください。</a></p>



<p class="wp-block-paragraph"><span class="bold-red">訂正後の終了点：</span></p>



<p class="wp-block-paragraph">さて、投稿の内容が多過ぎなので、いずれ別の投稿にしますが、<br>字幕を、スマホなど小さい画面で見る時、文字が被らないようにする方法に、2つあって、1つは、字幕を動画の枠外に表示することです。これは、上に既に紹介済みです。あと一つは細かいことですが、動画の枠内の字幕の背景を透過させることです。WordPressプレーヤーを使用する場合は、以下の方法で、デフォルトで透過率を設定することができます。</p>



<p class="wp-block-paragraph">ちょっと横道に外れます。私は、ChatGPTをよく使いますが、3.5の無料版です。有料版は日本円で約2700円/月、ということで、ちょっと高過ぎます。無料版でも、うまく質問をすれば、プログラミングもやってくれます。分からないことをザックリ理解するのに、便利です。活用をお勧めします。</p>



<p class="wp-block-paragraph">手元でデータをサクッと変更できることが一番嬉しいこと！<br>確かに、最近、自動文字起こし、翻訳と便利になってきている一方、人間側として、表記の間違い、漢字の間違い、ほか、間違いの点検が面倒になり、その修正が億劫になっていると思います。そこで、こうした<strong>手元でサクッと、ほぼリアルタイムで修正できる仕組みは、とても助かる</strong>のではと思います。<br>動的サイトの欠点は、探し出す時間が欲しいので、どうしても表示が遅れることでしょう。まあ、ネットはそうでなくても遅延は多いので、気にならなくなると思います。</p>



<p class="wp-block-paragraph">以上</p>



<p class="wp-block-paragraph"></p>
]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">20191</post-id>	</item>
		<item>
		<title>【小団体のIT】スマホから5つのSNSへ、アプリを開かないで送信する方法~AppSheet~</title>
		<link>https://imakat.com/2022/05/06/14993/</link>
		
		<dc:creator><![CDATA[imakat]]></dc:creator>
		<pubDate>Fri, 06 May 2022 07:35:14 +0000</pubDate>
				<category><![CDATA[デジタル]]></category>
		<category><![CDATA[ものづくり]]></category>
		<category><![CDATA[Push7]]></category>
		<category><![CDATA[Blogger]]></category>
		<category><![CDATA[Chrome]]></category>
		<category><![CDATA[SNS]]></category>
		<category><![CDATA[ワンタッチ]]></category>
		<category><![CDATA[Twitter]]></category>
		<category><![CDATA[Gメール]]></category>
		<category><![CDATA[Googleスプレッドシート]]></category>
		<category><![CDATA[中途半端な規模]]></category>
		<category><![CDATA[GAS]]></category>
		<category><![CDATA[LINE]]></category>
		<category><![CDATA[API]]></category>
		<guid isPermaLink="false">https://imakat.com/?p=14993</guid>

					<description><![CDATA[2023.7.31：TwitterがXに移行。APIへの影響が不明。2023.2.16追記：TwitterAPIの有料化の発表がありましたが、投稿bot1500個までは無料化へ自動移行とのことで、多くの場合、問題なさそう [&#8230;]]]></description>
										<content:encoded><![CDATA[
<hr class="wp-block-separator has-text-color has-key-color-color has-css-opacity has-key-color-background-color has-background is-style-wide"/>



<p class="wp-block-paragraph">2023.7.31：TwitterがXに移行。APIへの影響が不明。<br>2023.2.16追記：TwitterAPIの有料化の発表がありましたが、投稿bot1500個までは無料化へ自動移行とのことで、多くの場合、問題なさそうです。<br>2022.5.13更新：Twitterを追加。無料使用に留める場合は、API v2を利用すること。</p>



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



<p class="wp-block-paragraph">＜分散通知をスマホから実行する＞<br><span class="fz-12px"><a href="https://imakat.com/page-220506/" target="_blank">別ページで表示</a></span></p>



<img decoding="async" src="https://docs.google.com/drawings/d/e/2PACX-1vR8WAJSVQk0EV-LtoZdCv8V5n9CnwkUHGAVB1RmMiV05BKu9OWCDJoi8WOuEPfcwWKfEanrFwYxRqft/pub?w=1440&amp;h=1080">



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



<p class="wp-block-paragraph">メールとブログを含めるとSNSよりソシアルメディア(Social Media)という方が正しいのでしょうが、単語として分かりにくいので、ここでは「情報を配信するツール」としてSNSと呼ばせてもらいます。</p>



<p class="wp-block-paragraph">さて、昨年5回に亘って、「分散通知の仕組みを作る」として、電子メール、LINE、Push7、Bloggerのそれぞれへ、<strong><span class="marker">アプリを開かないで送信する仕組み</span></strong>、を説明しました。</p>



<p class="wp-block-paragraph">しかし、スマホで操作すると、GoogleスプシをChromeのPCサイトから扱う、という方法は非常に扱いづらいことは分かっていました。</p>



<p class="wp-block-paragraph">今回、それを、かなり<strong><span class="marker">実用的に改善しました</span></strong>ので紹介します。</p>



<p class="wp-block-paragraph">実は、AppSheetとGASの連携については、Google内で開発が進んでいますので、半年先には、もっと簡単に色々できるようになっているかもしれません。</p>



<p class="wp-block-paragraph">しかし今回私が改善したいこと自体が、さほど、高度な技術を要求することでもありませんので、現状の技量でアプローチしてみます。</p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



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



<h4 class="wp-block-heading">＜1＞ 人の手作業は、文を作成修正する→送りたいSNSを選び送信する、ただそれだけ。</h4>



<p class="wp-block-paragraph">前回の通知方式では、SNSアプリ別にGoogleSSとGASを組み合わせて、GoogleSSを立ち上げて内容を確認して、送信ボタンを押す、これをSNSアプリ毎に行う方式でしたが、今回は、GoogleSSは一つのファイルにして、その中へ、GASを各アプリ別に組み込む、という方法にしました。</p>



<p class="wp-block-paragraph">その各アプリ別のGASは、前回の通知方式で作ったものを、ほぼそのまま流用しています。<br>作業手順は以下のようになります。</p>



<p class="wp-block-paragraph">＜作業手順＞<br><span class="fz-12px"><a href="https://imakat.com/page-220507/" target="_blank">別ページで表示</a></span></p>



<img decoding="async" src="https://docs.google.com/drawings/d/e/2PACX-1vQWnxlTE0kL7hQM7qSqi0qRi0U5C5GMRkO8XM-D5EdpkDVyPPPfuzfDKy5GulyJMi1QOOylwOqPxkoT/pub?w=1440&amp;h=1080">



<p class="wp-block-paragraph">前回は、各GoogleSSを立ち上げて、投稿ボタンを押す、これを繰り返すという手間がありました。それがAppSheetの以下の２つのメニューで完結するようにしました。なお、AppSheetについては、<a href="https://imakat.com/2022/02/27/14686/" target="_blank">こちらの投稿</a>の中で、概略触れています。解説している日本語の書物は殆ど見かけませんが、唯一<a rel="noopener" target="_blank" href="https://www.amazon.co.jp/Google-AppSheet-ではじめる-ノーコード開発入門-掌田津耶乃/dp/4899775199/ref=asc_df_4899775199/?tag=jpgo-22&amp;linkCode=df0&amp;hvadid=524423533651&amp;hvpos=&amp;hvnetw=g&amp;hvrand=18135569281701901134&amp;hvpone=&amp;hvptwo=&amp;hvqmt=&amp;hvdev=c&amp;hvdvcmdl=&amp;hvlocint=&amp;hvlocphy=1009446&amp;hvtargid=pla-1290663459033&amp;psc=1&amp;th=1&amp;psc=1">これ<span class="fa fa-external-link external-icon anchor-icon"></span></a>くらいです。使っているうちにだんだん慣れてくるとは思います。</p>



<p class="wp-block-paragraph">AppSheetアプリの実際の動きは、以下の動画をご覧ください。</p>



<div style="position:relative;">
<iframe src="https://player.vimeo.com/video/707215784?&#10;title=0&amp;&#10;byline=0&amp;&#10;muted=0&amp;&#10;portrait=0&amp;&#10;autopause=0" style="position:absolute;top:0;
left:0;
width:100%;
height:100%;
" frameborder="0" allow="autoplay;
fullscreen" allowfullscreen="">
</iframe>
</div>
<script src="https://player.vimeo.com/api/player.js">
</script>
<p>このビデオは無音です。Twitterは組み込む前です。</p>



<p class="wp-block-paragraph">以上のような動きになりますが、その中で、通知の作成及び修正の画面が以下です。追加または修正した行が、通知の送信の対象となります。ですから、今現在適当なテスト内容になっていますが、例えば、「避難情報通知用」などテンプレートとして用意しておくのもいい方法です。</p>



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



<p class="wp-block-paragraph"></p>



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



<p class="wp-block-paragraph"></p>



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



<p class="wp-block-paragraph">上図を表示しているデータは、以下です。sheet1には順次新しい投稿が書き込まれて、それを更新日時でSORTしたものがsheet2へ入り、その最新行からsheet3をコピーしています。</p>



<p class="wp-block-paragraph"></p>



<figure class="wp-block-image size-large"><a href="https://imakat.com/rd.php?id=IoyR23xN.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=IoyR23xN.png" alt=""/></a><figcaption class="wp-element-caption">Twitterについては、投稿の重複は拒否されるので、その点の工夫が必要。</figcaption></figure>



<p class="wp-block-paragraph">「拡張機能」→「Apps Script」の中に記述したスクリプトは、全部掲載します。</p>



<p class="wp-block-paragraph"><a href="https://imakat.com/page-220507-2/" target="_blank">複数SNSの送信GAS</a></p>



<h4 class="wp-block-heading">＜２＞　Twitterを使えるようにする。</h4>



<p class="wp-block-paragraph"><strong>Twitter</strong>ですが、災害発生時には最も実績のある情報発信ツールであることは、東日本大震災他大災害の時を振り返れば明らかです。ただ、利用者が多いからか、イタズラや不正利用を防止せねばならず、APIのような、外部からアクセスできるツールに対する許可は、敷居が高い印象がありました。</p>



<p class="wp-block-paragraph">しかし、申し込んでみると結構すんなりいけます。最近、APIが、APIv1.1からAPI v2にバージョンアップしました。どうもAPI v2から直接使う方法が分かりにくく、色々調べて、TwitterAPI v2をEssentialから<strong>Elevated(無料）</strong>へ引き上げる方法が良さそうです。</p>



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



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">引き上げる際に、許可が必要で、用途に関する質問に英語で返答する必要がありますが、簡単な英語で書いても大丈夫かと思います。数多く解説のブログが書かれていますが、例えば<a rel="noopener" target="_blank" href="http://pineplanter.moo.jp/non-it-salaryman/2021/07/17/gas-twitter/">このブログ<span class="fa fa-external-link external-icon anchor-icon"></span></a>は分かりやすいです。</p>



<p class="wp-block-paragraph"><br>引き上げておいて、<br>OAuth1.0aのみにチェック<br>OAUTH1.0A SETTINGS でRead and writeにチェック<br>CallbackURI/RedirectURL ,WebsiteURL,Terms of service,Privacy policyは、https://twitter.com<br>と設定します。</p>



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



<p class="wp-block-paragraph"><br>Twitterは、同一内容の複数投稿は拒否するようです。その辺りは、GoogleSSのカラムに前回の投稿内容をコピーして今回の投稿内容と比較して、同じ場合は、tweet.gs内でルーチンを通さないようにしました(上のGASを参照）。</p>



<p class="wp-block-paragraph"><br></p>



<h4 class="wp-block-heading">＜３＞　AppSheetで作ったアプリはプロの仕上がり感</h4>



<p class="wp-block-paragraph">AppSheetは、各SNSのロゴをイメージとして読み込んで表示するだけのことですが、上の図のように、プロが作ったようなアプリになります。そこが素晴らしい。</p>



<p class="wp-block-paragraph">課題点というか仕方ない点としては、各SNS別に送信履歴を残していない点です。これはまあ、各アプリ側では当然履歴として残っていますのでそれで十分でしょう。</p>



<p class="wp-block-paragraph">現状は、各SNS側の画面から通知文の修正は出来ないようになっています。しかし、基本となる通知文を作った後で、それを各アプリ側でコピーして、各アプリ側で修正して送信する、という流れの方が素直かも知れません。<br>このあたりは、AppSheetとGASの連携の開発が進むと、すぐに可能になりそうです。しかしながら、今回のものでも、特に不便は感じません。</p>



<h4 class="wp-block-heading">＜４＞頻繁にテスト出来ない悩み</h4>



<p class="wp-block-paragraph">この複数通知の仕組みを作って思う課題、課題というか悩みは、頻繁にテスト出来ないことです。なにしろ、緊急通知が目的ですから、滅多に通知なんか発信されるものではないです。テスト用にそれぞれIDやアドレスを作ったとしても、実用としては常に本番用のアドレスにしておかなければ意味がありません。そんなわけで、実際に全部テストできるのは、年に一度の「防災訓練の日」の活動の一環としてテスト送信させてもらう、ということになります。</p>



<p class="wp-block-paragraph">そこがちょっと不便なところ。</p>



<p class="wp-block-paragraph">でも多くの方は、そんな緊急発信のためではなく、いわゆる普通の「伝言板」「回覧板」的な使い方になると思いますので、十分、応用できると思います。</p>



<h4 class="wp-block-heading">＜５＞まとめ〜中途半端な規模の人たちのために〜懸念材料</h4>



<p class="wp-block-paragraph">地方自治体で多いのは、「LINEに加入してアプリを入れて活用してください」型です。正直言ってLINEを嫌いな人もいるはず。しかし最近、だんだん、LINEに限定させず複数のSNSの中から、ユーザーが選択できる形式も増えてきました。</p>



<p class="wp-block-paragraph">スタッフの充実した都市の役所や大規模組織なら色々そうした工夫ができるでしょう。逆に、本当に小さい規模なら電話一本、伝言でOKでしょう。しかし<strong>大多数は、そのどちらとも言えない中途半端な規模</strong>の自治会、中途半端な規模のNPO。公民館はあるが住み込みは置けない。電話もない。自治会としてインターネット契約をすることは結構面倒なので、個人に契約者になってもらおうとすると、その個人がいつまで肩代わりしてくれるか保証はない。そうなると、Googleなどのサービスも無料で使えるものが中心となります。そんな人たちのために、少しでもお役に立てば嬉しいです。</p>



<p class="wp-block-paragraph">懸念材料としては、Twitter Botに有料化の動きがあること。GASやAppSheetの連携が自動化処理と見做されると停止されるか有料化されることを懸念します。つまり無料で使えるインターネットサービスは、減少していく方向にあるでしょう。</p>



<p class="wp-block-paragraph">以上です。</p>


]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">14993</post-id>	</item>
		<item>
		<title>【GAS】分散通知の仕組みを作る〜Googleアプリ、GAS及びAPIの活用　STEP5: ブログ(Blogger)への投稿・全体まとめ(5/5)</title>
		<link>https://imakat.com/2021/10/15/14054/</link>
		
		<dc:creator><![CDATA[imakat]]></dc:creator>
		<pubDate>Fri, 15 Oct 2021 02:33:29 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[デジタル]]></category>
		<category><![CDATA[Googleスプレッドシート]]></category>
		<category><![CDATA[GAS]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Blogger]]></category>
		<guid isPermaLink="false">https://imakat.com/?p=14054</guid>

					<description><![CDATA[＜分散通知の仕組みを作る　STEP5: ブログ(Blogger)への投稿＞別ページで表示 ブログは、時系列の掲示板であり、その中には、今回取り上げている緊急通知も含めていいと考えています。記事の性格は、楽しい思い出づくり [&#8230;]]]></description>
										<content:encoded><![CDATA[
<hr class="wp-block-separator has-text-color has-key-color-color has-css-opacity has-key-color-background-color has-background is-style-wide"/>



<p class="wp-block-paragraph">＜分散通知の仕組みを作る　STEP5: ブログ(Blogger)への投稿＞<br><span class="fz-12px"><a href="https://imakat.com/page-11646-4-2-3-2/" target="_blank">別ページで表示</a></span></p>



<img decoding="async" src="https://docs.google.com/drawings/d/e/2PACX-1vS9vKizc6xV7tI7qoc0Xd0k1DHE11asFoRTPnnevUBwBrBuY4Eiy6GDSQ694HDKRS9TTmpMy_YBzZ1W/pub?w=1440&amp;h=1080">



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



<p class="wp-block-paragraph">ブログは、時系列の掲示板であり、その中には、今回取り上げている緊急通知も含めていいと考えています。記事の性格は、楽しい思い出づくりとは異なりますが、緊急かつ重要な情報は、どこにでも飛び込んでいいものと考えます。</p>



<p class="wp-block-paragraph">今回、無料のブログの選択には、多少悩みました。この種のサービスは打ち切りになることが多いからです。その中から、Googleと相性がいいもの、シンプルなもの、であるBloggerを選択しました。Bloggerは他のサービスへの移動、例えばWordPressへの移動などについても、説明が数多くあることも安心です。</p>



<p class="wp-block-paragraph"></p>



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



<h4 class="wp-block-heading">＜1＞ GoogleSSへの取り込み</h4>



<p class="wp-block-paragraph">流れとしては、通知文GoogleSS→Blogger送信用GoogleSS→Blogger、です。APIは使いません。Bloggerにはメール投稿機能が備わっており、それを利用します。</p>



<p class="wp-block-paragraph">Blogger送信用GoogleSSの画面は以下です。</p>



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



<p class="wp-block-paragraph">この画面には、Googleフォームへ入力した通知文GoogleSSが取り込まれるため、内容を確認するだけです。問題がなければ、「Blogger投稿」ボタンを押します。</p>



<p class="wp-block-paragraph"><strong>通知文の読み込み：</strong></p>



<p class="wp-block-paragraph">IMPORTRANGE関数を使います。<br>読み込みたいGoogleSSのURLが、下記のようになっていたとして、</p>



<pre class="wp-block-code"><code>https:&#47;&#47;docs.google.com/spreadsheets/d/【この部分】/edit#gid=0</code></pre>



<p class="wp-block-paragraph">【この部分】を以下の場所に当てはめてください。sheet1は実際のシート名、A10,A12のところも実際のセル位置を当てはめてください。</p>



<p class="wp-block-paragraph">Bloggerでは、タイトル、本文と関係リンク、の２データを、通知文GoogleSS から読み込んで、このBlogger用GoogleSSへ取り込みます。</p>



<pre class="wp-block-code"><code>=IMPORTRANGE("【この部分】","sheet1!A10")
=IMPORTRANGE("【この部分】","sheet1!A12")</code></pre>



<h4 class="wp-block-heading">＜2＞GAS記述</h4>



<p class="wp-block-paragraph"><strong>GASの記述：</strong></p>



<p class="wp-block-paragraph">このままコピペください。<span class="bold-red">赤字</span>は、例示です。</p>



<p class="wp-block-paragraph">STEP2の電子メールと、考え方は同じです。</p>



<p class="wp-block-paragraph">・<span class="bold-red">nihonnofujisan001</span>は、google個人アカウントです。<br>・投稿用のメールアドレスが、Bloggerから与えられます。その時【任意の文字列】を設定します。<br></p>



<pre class="wp-block-code"><code>function sendMail(){
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getActiveSheet();
  const from = '<span class="bold-red">nihonnofujisan001</span>@gmail.com';
  const to = '<span class="bold-red">nihonnofujisan001</span>.【任意の文字列】@blogger.com';
  const subject = sheet.getRange(<span class="bold-red">3,1</span>).getValue();
  const body = sheet.getRange(<span class="bold-red">5,2</span>).getValue();
GmailApp.sendEmail(to, subject, body);
}
</code></pre>



<h4 class="wp-block-heading"><strong>＜３＞なぜ30分以内？：</strong></h4>



<p class="wp-block-paragraph">ブログ（ネット掲示板）をユーザーが見るのを30分以内、としているのは、ブログには、Push7からRSS連携：</p>



<p class="wp-block-paragraph"><strong><span class="bold-red">赤字</span></strong>は、例示です。</p>



<pre class="wp-block-code"><code>https://<span class="bold-red">nihonnofujisan001</span>.blogspot.com/feeds/posts/default</code></pre>



<p class="wp-block-paragraph">を貼り付けています。こうしたRSSフィードは、様々なサービスがあるので、もっと短い巡回時間のものもあると思います。一応、Push7の巡回は30分以内となっています。30分以内は標準的かと思います。</p>



<p class="wp-block-paragraph">ちなみに私は、Push7を、ブログ更新とは切り離した緊急通知用と、ブログ更新とリンクした一般通知用の２箇所に貼り付けています。</p>



<h4 class="wp-block-heading">＜４＞全体のまとめ</h4>



<h5 class="wp-block-heading">１）配信数の制約に注意。緊急通知だけなら、会員700人以下なら無料で運用できそう。</h5>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<figure class="wp-block-table"><table><tbody><tr><td>サービス名</td><td class="has-text-align-center" data-align="center">無料：同時に1回何通まで</td><td class="has-text-align-center" data-align="center">無料：日・月の合計数の上限</td><td class="has-text-align-center" data-align="center">想定最大通知数</td><td class="has-text-align-center" data-align="center">想定利用者上限(歩留り70%)</td></tr><tr><td><a rel="noopener" target="_blank" href="https://support.google.com/mail/answer/22839?hl=ja#zippy=%2C送信できるメールの制限数に達しました">Googleグループメール<span class="fa fa-external-link external-icon anchor-icon"></span></a> </td><td class="has-text-align-center" data-align="center">500通</td><td class="has-text-align-center" data-align="center">500通/日</td><td class="has-text-align-center" data-align="center">週2回</td><td class="has-text-align-center" data-align="center">175人</td></tr><tr><td><a rel="noopener" target="_blank" href="https://line-sm.com/blog/lineofficial_message_count/">LINE公式アカウント<span class="fa fa-external-link external-icon anchor-icon"></span></a></td><td class="has-text-align-center" data-align="center"></td><td class="has-text-align-center" data-align="center">1000通/月</td><td class="has-text-align-center" data-align="center">週2回</td><td class="has-text-align-center" data-align="center">88人</td></tr><tr><td><a rel="noopener" target="_blank" href="https://push7.jp/blog/faq/">Push7<span class="fa fa-external-link external-icon anchor-icon"></span></a></td><td class="has-text-align-center" data-align="center"></td><td class="has-text-align-center" data-align="center">5000通/月</td><td class="has-text-align-center" data-align="center">週2回</td><td class="has-text-align-center" data-align="center">437人</td></tr><tr><td></td><td class="has-text-align-center" data-align="center"></td><td class="has-text-align-center" data-align="center"></td><td class="has-text-align-center" data-align="center">合計</td><td class="has-text-align-center" data-align="center">700人</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">現在、私は、全世帯が、3つから１つだけ選んで登録するとして、600〜700世帯を想定しています。トータルとしては、この３つのサービスで、お金をかけずに続けそうですが、自由に選んでもらうとLINEに集中するのでは。LINEの無料のワクは非常に小さいです。後でPush7やメールへ変更を促すことになるのでしょうかね。いずれにしても、緊急通知は一方通行、仮に事態が集中したとしても週２〜３回に収まるのではないでしょうか。</p>



<p class="wp-block-paragraph">緊急通知の配信基準を設けておく必要があるでしょう。</p>



<p class="wp-block-paragraph">例として、</p>



<hr class="wp-block-separator has-css-opacity"/>



<p class="wp-block-paragraph">・水害・土砂災害における避難警戒レベル３以上の発令に伴い、自治体から、当該地域あてに発出された情報。</p>



<p class="wp-block-paragraph">・地域の災害対策組織の長（自治会長や町内会長など）が決定した配信情報。例えば、道路の陥没、建物の倒壊、断層など上部自治体の危険箇所情報からこぼれ落ちた地域住民向けの情報。</p>



<p class="wp-block-paragraph">・事件事故の発生に伴い、警察消防から発出された、地域住民への警戒情報。</p>



<p class="wp-block-paragraph">・その他、自治体から要請があり当該長が了承した緊急通知。例えば、同報無線の能力不足、故障時の支援も含む。</p>



<hr class="wp-block-separator has-css-opacity"/>



<p class="wp-block-paragraph">など。何がどう重なるか分かりませんが、不幸が重なったとしても週２〜３回で収まると、私は想像します。</p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">しかし世帯数が1,000世帯を超えるようだと、レンタルサーバーを使うなど、有料にならざるを得ないのでは。</p>



<p class="wp-block-paragraph">理想的には、500〜600世帯ごとに、このような仕組みが運営できれば、機動的でしょう。</p>



<h5 class="wp-block-heading">２）異なったサービスだが、操作方法は統一する。その上で、一つ一つ、送信成功を確かめながら送るのがいい。</h5>



<p class="wp-block-paragraph">今回の、分散通知ですが、使用頻度が非常に低いです。防災などの緊急通知が主目的。そんな災害は頻繁にはないです。ですから、わかりやすく言えば、<strong>この仕組みの使い方を忘れた頃、突然、使うことになる</strong>のだと想像します。従って、覚える操作方法は一つだけにすること。そしてそれを、それぞれのサービスに適用して、送信出来るようにしておくのが重要だと考えます。</p>



<p class="wp-block-paragraph"></p>



<h5 class="wp-block-heading">3)  GoogleSSをアプリ毎に別ファイルにした理由</h5>



<p class="wp-block-paragraph">アプリ側はそれぞれ異なる会社のサーバーになります。全体が一箇所のトラブルに巻き込まれないように、GoogleSSは、シート別ではなく、ファイル別に用意しました。</p>



<h5 class="wp-block-heading">4）目標：緊急通知を、スマホから、１３分以内で、７００人へ送る仕組みを、タダで作る。</h5>



<p class="wp-block-paragraph">今回、この目標を達成できたような気もしていますが、実用上、どうなるかはわかりません。</p>



<p class="wp-block-paragraph">今回、私のブログを読んで下さった方は、私同様、開発費もタダにすることができると思います。これからも工夫改善は続きます。</p>



<p class="wp-block-paragraph"><a href="https://imakat.com/2021/10/13/13863/" target="_blank">STEP1へ戻る</a></p>



<p class="wp-block-paragraph">以上</p>


]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">14054</post-id>	</item>
		<item>
		<title>【GAS】分散通知の仕組みを作る〜Googleアプリ、GAS及びAPIの活用　STEP4: Push7のプッシュ通知(4/5)</title>
		<link>https://imakat.com/2021/10/15/14021/</link>
		
		<dc:creator><![CDATA[imakat]]></dc:creator>
		<pubDate>Thu, 14 Oct 2021 22:33:17 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[デジタル]]></category>
		<category><![CDATA[Googleスプレッドシート]]></category>
		<category><![CDATA[GAS]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Push7]]></category>
		<category><![CDATA[プッシュ通知]]></category>
		<guid isPermaLink="false">https://imakat.com/?p=14021</guid>

					<description><![CDATA[＜分散通知の仕組みを作る　STEP4: Push7のプッシュ通知＞別ページで表示 LINEや電子メールは双方向の会話の機能があるので、「りんごちゃん」などニックネームで構わないが何らかのID情報が配信側に伝わります。しか [&#8230;]]]></description>
										<content:encoded><![CDATA[
<hr class="wp-block-separator has-text-color has-key-color-color has-css-opacity has-key-color-background-color has-background is-style-wide"/>



<p class="wp-block-paragraph">＜分散通知の仕組みを作る　STEP4: Push7のプッシュ通知＞<br><span class="fz-12px"><a href="https://imakat.com/page-11646-4-2-3/" target="_blank">別ページで表示</a></span></p>



<img decoding="async" src="https://docs.google.com/drawings/d/e/2PACX-1vQbOAqUsZ3ihHYbzYqnutFIBTTZN5oywF3wjFlkdzol2WoBJJEUkPHV0fhSYG_Szb22ufvPz2YRWk85/pub?w=1440&amp;h=1080">



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



<p class="wp-block-paragraph">LINEや電子メールは双方向の会話の機能があるので、「りんごちゃん」などニックネームで構わないが何らかのID情報が配信側に伝わります。しかし、利用者側には、それすら知られたくない人もいます。</p>



<p class="wp-block-paragraph">Push7は、ニックネームすら入力不要、です。敷居が低いです。</p>



<p class="wp-block-paragraph">Push7に似た仕組みは、既にネット上に溢れています。ふだんサイトを見ていると、ヒョコッと顔を出して、「登録しませんか」と誘いかけられ、即座に、×、拒否、NO、不要を返事する、それが条件反射になっているあれです（ブラウザの設定でポップアップを禁止に出来ると思いますが）。</p>



<p class="wp-block-paragraph">今私は、緊急通知を準備しているので、ポップアップ禁止設定にしたおかげで目にも触れない、というのでは困ります。そこで、サイトの文面の中で、説明を加えて、ボタンを押してもらって申し込んでもらう手順にしています。このPush7のサイトへの設置方法の説明は、長くなるので、この記事では、割愛します。</p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph">このSTEP4における配信作業の流れでは、Push7のアプリは何も触りません。</p>



<p class="wp-block-paragraph">Push7のアプリをスマホから触りたくない理由ですが、プッシュ通知を打ち込むまでの画面の操作が非常に扱いにくい点があります。アプ通知文がSTEP1で作成済みならば、STEP2、STEP3とやることはほぼ同じです。ChromeからGoogleSSを立ち上げる-&gt;PC版サイトを選ぶ-&gt;iphoneを横向きにする-&gt;閉じるをクリック-&gt;内容を一応点検したら「Push7投稿」ボタンをクリック。という手順。</p>



<p class="wp-block-paragraph">Push7のいい点は、管理する側における、利用者の登録や削除については、作業は何もないです。</p>



<p class="wp-block-paragraph">実に簡単です。</p>



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



<h4 class="wp-block-heading">＜1＞ GoogleSSへの取り込み</h4>



<p class="wp-block-paragraph">Push7で送信する内容のうち、毎回変更されるのは、タイトル、関係リンク、本文の３個です。</p>



<p class="wp-block-paragraph"></p>



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



<p class="wp-block-paragraph">この画面には、Googleフォームへ入力した通知文が取り込まれるため、内容を確認するだけです。問題がなければ、「Push7投稿」ボタンを押します。</p>



<p class="wp-block-paragraph"><strong>通知文の読み込み：</strong></p>



<p class="wp-block-paragraph">IMPORTRANGE関数を使います。<br>読み込みたいGoogleSSのURLが、下記のようになっていたとして、</p>



<pre class="wp-block-code"><code>https:&#47;&#47;docs.google.com/spreadsheets/d/【この部分】/edit#gid=0</code></pre>



<p class="wp-block-paragraph">【この部分】を以下の場所に当てはめてください。sheet1は実際のシート名、A10,A12,A14のところも実際のセル位置を当てはめてください。</p>



<p class="wp-block-paragraph">Push7では、タイトル、関係リンク、本文の３データを、通知文GoogleSS から読み込んで、このPush7用GoogleSSへ取り込みます。</p>



<pre class="wp-block-code"><code>=IMPORTRANGE("【この部分】","sheet1!A10")
=IMPORTRANGE("【この部分】","sheet1!A12")
=IMPORTRANGE("【この部分】","sheet1!A14")</code></pre>



<h4 class="wp-block-heading">＜2＞APIの取得とGAS記述</h4>



<p class="wp-block-paragraph"><strong>APIの取得：</strong></p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://push7.jp">Push7<span class="fa fa-external-link external-icon anchor-icon"></span></a>は、親切に、API設置方法などが解説されています。</p>



<p class="wp-block-paragraph"><a rel="noopener" target="_blank" href="https://push7.jp/docs/development/api/">Push7 APIの利用<span class="fa fa-external-link external-icon anchor-icon"></span></a>　←この中の「Webプッシュ通知を送信するAPI」の項目が参考になります。</p>



<p class="wp-block-paragraph">Push7は、メールアドレスとパスワードで登録できます。次に、プロジェクトを例えば「ABC会_通知」などとつけて設置すると、そのプロジェクトごとに、下記のように、App NumberとAPI Keyが発行されます。</p>



<figure class="wp-block-image size-large"><a href="https://imakat.com/rd.php?id=ACBb1sf3.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=ACBb1sf3.png" alt=""/></a><figcaption class="wp-element-caption">Push7 API : API NumberとAPI Keyを取得する。</figcaption></figure>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"><strong>GASの記述：</strong></p>



<p class="wp-block-paragraph">このままコピペください。<span class="bold-red">赤字</span>は、例示です。</p>



<p class="wp-block-paragraph">・iconは、ここに指定した画像が選択されて通知に表示されます。<br>・urlは、表示された通知画面をクリックすると移動するサイトです。<br>・disappear_instantlyは、falseにすると画面の表示にタッチされるまでは表示が残ります。trueにすると数秒後には消えます。</p>



<pre class="wp-block-code"><code>const notifyPush7 = () =&gt; {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getActiveSheet();
  const apikey = "【上画像のAPI Key】"
  const appno = '【上画像のApp Number】'
  const url = 'https://api.push7.jp/api/v1/【上画像のApp Number】/send';
  const headers = {
    'Content-Type' : 'application/json; charset=UTF-8',
    'Authorization' : 'Bearer ' + apikey,
 };
const data = {
'title': sheet.getRange(<span class="bold-red">3,1</span>).getValue(),
'body' : sheet.getRange(<span class="bold-red">7,1</span>).getValue(),
'icon' : "<span class="bold-red">https://***.com/****.jpeg</span>",
'url' :  sheet.getRange(<span class="bold-red">5,1</span>).getValue(),
'apikey' : "【上画像のAPI Key】",
'disappear_instantly' : false,
//'transmission_time": "2021/10/10 10:10"
//'query' : true,
}
const options = {
  'method' : 'post',
  'headers': headers,
  'payload': JSON.stringify(data)
};
UrlFetchApp.fetch(url,options);
}
</code></pre>



<p class="wp-block-paragraph">具体的には、以下の、アプリによる送信画面を見て、対応関係を確認ください。</p>



<p class="wp-block-paragraph">この「タイトル」「URL」「内容」の部分を、STEP1で作った通知文GoogleSSから、自動的に取り込むプログラムになっています。</p>



<p class="wp-block-paragraph"></p>



<figure class="wp-block-image size-large"><a href="https://imakat.com/rd.php?id=4yzyetYc.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=4yzyetYc.png" alt=""/></a><figcaption class="wp-element-caption">Push7アプリの新規プッシュ通知の画面</figcaption></figure>



<p class="wp-block-paragraph">次回のSTEP5は、Googleが提供するブログであるBloggerへ、同じ通知文を投稿する方法を説明します。割と簡単です。</p>



<p class="wp-block-paragraph"><a href="https://imakat.com/2021/10/15/14054/" target="_blank">STEP5</a></p>



<p class="wp-block-paragraph">以上</p>


]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">14021</post-id>	</item>
		<item>
		<title>【GAS】分散通知の仕組みを作る〜Googleアプリ、GAS及びAPIの活用　STEP3: LINEのメッセージ配信(3/5)</title>
		<link>https://imakat.com/2021/10/14/13982/</link>
		
		<dc:creator><![CDATA[imakat]]></dc:creator>
		<pubDate>Thu, 14 Oct 2021 04:17:55 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[デジタル]]></category>
		<category><![CDATA[GAS]]></category>
		<category><![CDATA[LINE]]></category>
		<category><![CDATA[API]]></category>
		<category><![CDATA[Googleスプレッドシート]]></category>
		<guid isPermaLink="false">https://imakat.com/?p=13982</guid>

					<description><![CDATA[＜分散通知の仕組みを作る　STEP3: LINEのメッセージ配信＞別ページで表示 iPhoneのLINE公式アカウントアプリには、「メッセージを配信する」機能があり、扱い易いです。しかしその扱いやすさの程度ですが、アプリ [&#8230;]]]></description>
										<content:encoded><![CDATA[
<hr class="wp-block-separator has-text-color has-key-color-color has-css-opacity has-key-color-background-color has-background is-style-wide"/>



<p class="wp-block-paragraph">＜分散通知の仕組みを作る　STEP3: LINEのメッセージ配信＞<br><span class="fz-12px"><a href="https://imakat.com/page-11646-4-2-2/" target="_blank">別ページで表示</a></span></p>



<img decoding="async" src="https://docs.google.com/drawings/d/e/2PACX-1vTTOSyFp0XDoz9QBQBS44O-VEXF_XlteV-PbnRZfwkVEKQh46dMZSSaKU0WBkYrOta-yO6kKzUVhhGG/pub?w=1440&amp;h=1080">



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



<p class="wp-block-paragraph">iPhoneのLINE公式アカウントアプリには、「メッセージを配信する」機能があり、扱い易いです。しかしその扱いやすさの程度ですが、アプリを開く-&gt;「メッセージ配信する」をクリック-&gt;追加をクリック-&gt;テキストを選ぶ-&gt;テキストをコピペする-&gt;次へ-&gt;「すべての友だち」を選択して配信。という手順。</p>



<p class="wp-block-paragraph">確かにほとんど悩むことなく進めますが、やはり、余分なことを神経を使いながら覚える、そんな印象。</p>



<p class="wp-block-paragraph">このSTEP3における配信作業の流れでは、LINEのアプリは何も触りません。通知文がSTEP1で作成済みならば、STEP2とやることはほぼ同じです。ChromeからGoogleSSを立ち上げる-&gt;PC版サイトを選ぶ-&gt;iphoneを横向きにする-&gt;閉じるをクリック-&gt;内容を一応点検したら「LINE投稿」ボタンをクリック。という手順。</p>



<p class="wp-block-paragraph">LINEのいい点は、管理する側では、友だちの登録や削除などの作業は、何もないです。</p>



<p class="wp-block-paragraph">実に簡単です。</p>



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



<h4 class="wp-block-heading">＜1＞ GoogleSSへの取り込み</h4>



<p class="wp-block-paragraph">送信する内容はコンパクトに、LINEの吹き出し１個だけです。</p>



<p class="wp-block-paragraph"></p>



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



<p class="wp-block-paragraph">この画面には、Googleフォームへ入力した通知文が取り込まれるため、内容を確認するだけです。問題がなければ、「LINE投稿」ボタンを押します。</p>



<p class="wp-block-paragraph"><strong>通知文の読み込み：</strong></p>



<p class="wp-block-paragraph">IMPORTRANGE関数を使います。<br>読み込みたいGoogleSSのURLが、下記のようになっていたとして、</p>



<pre class="wp-block-code"><code>https:&#47;&#47;docs.google.com/spreadsheets/d/【この部分】/edit#gid=0</code></pre>



<p class="wp-block-paragraph">【この部分】を以下の場所に当てはめてください。sheet1は実際のシート名、A20のところも実際のセル位置を当てはめてください。</p>



<p class="wp-block-paragraph">LINEでは、吹き出し枠一つの中に、タイトル〜本文〜関係リンクを一まとめにして入れています。</p>



<pre class="wp-block-code"><code>=IMPORTRANGE("【この部分】","sheet1!A20")</code></pre>



<h4 class="wp-block-heading">＜2＞APIの取得とGAS記述</h4>



<p class="wp-block-paragraph"><strong>APIの取得：</strong></p>



<p class="wp-block-paragraph">LINE公式アカウントを取得すると、そのユーザーIDで、下記のLINE Developersにログインして、LINE Messaging APIのアクセストークンを取得します。</p>




<a rel="noopener" target="_blank" href="https://developers.line.biz/ja/services/messaging-api/" title="LINE Developers" 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 data-recalc-dims="1" fetchpriority="high" decoding="async" src="https://i0.wp.com/imakat.com/wp-content/uploads/cocoon-resources/blog-card-cache/dc3da295cadbd7f1ebc1c79124500834.jpg?resize=320%2C180&#038;ssl=1" alt="" class="blogcard-thumb-image external-blogcard-thumb-image" width="320" height="180" /></figure><div class="blogcard-content external-blogcard-content"><div class="blogcard-title external-blogcard-title">LINE Developers</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=https://developers.line.biz/ja/services/messaging-api/" alt="" class="blogcard-favicon-image external-blogcard-favicon-image" width="16" height="16" /></div><div class="blogcard-domain external-blogcard-domain">developers.line.biz</div></div></div></div></a>



<p class="wp-block-paragraph"></p>



<p class="wp-block-paragraph"><strong>GASの記述：</strong></p>



<p class="wp-block-paragraph">このままコピペください。<span class="bold-red">赤字</span>は、例示です。</p>



<pre class="wp-block-code"><code>const notifyLine = () =&gt; {
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getActiveSheet();
// LINE DevelopersのChannel Access Tokenを【アクセストークン】へ入れます。
const ACCESS_TOKEN = "【アクセストークン】"
// LINE Developersの自分のユーザーIDを【ユーザーID】へ入れます。
const USER_ID = '【ユーザーID】'
const url = 'https://api.line.me/v2/bot/message/broadcast';
const headers = {
  'Content-Type' : 'application/json; charset=UTF-8',
  'Authorization': 'Bearer ' + ACCESS_TOKEN,
};

const message = sheet.getRange(<span class="bold-red">3,1</span>).getValue();
const data = {
  'messages' : &#91;
    {
      'type':'text',
      'text':message,
    }
  ]
};

const options = {
  'method':'post',
  'headers': headers,
  'payload':JSON.stringify(data)
};

UrlFetchApp.fetch(url,options);
}</code></pre>



<p class="wp-block-paragraph">「みんな」に対してメッセージ配信する場合は、上記のように、APIの最後の部分にbroadcastを使います。</p>



<p class="wp-block-paragraph">iPhoneで使う時は、STEP2と同様に、上記のGoogleSSのLINE投稿ファイルを、今度はiPhoneで呼び出してから「PC版サイトを見る」を選択-&gt;iPhoneを横向きにする-&gt;上段に出る警告を「閉じる」-&gt;「LINE投稿」のボタンを押す。と、同じ手順になります。</p>



<p class="wp-block-paragraph">次のSTEP4では、Push7の新規プッシュ通知を、Push7のアプリを何も触らないで実行する方法を説明します。考え方はLINEと同じです。</p>



<p class="wp-block-paragraph"><a href="https://imakat.com/2021/10/15/14021/" target="_blank">STEP4</a></p>



<p class="wp-block-paragraph">以上</p>


]]></content:encoded>
					
		
		
		<post-id xmlns="com-wordpress:feed-additions:1">13982</post-id>	</item>
		<item>
		<title>【GAS】分散通知の仕組みを作る〜Googleアプリ、GAS及びAPIの活用　STEP2: 電子メール配信(2/5)</title>
		<link>https://imakat.com/2021/10/13/13906/</link>
		
		<dc:creator><![CDATA[imakat]]></dc:creator>
		<pubDate>Wed, 13 Oct 2021 07:49:54 +0000</pubDate>
				<category><![CDATA[WordPress]]></category>
		<category><![CDATA[デジタル]]></category>
		<category><![CDATA[Googleスプレッドシート]]></category>
		<category><![CDATA[GAS]]></category>
		<category><![CDATA[Googleグループメール]]></category>
		<guid isPermaLink="false">https://imakat.com/?p=13906</guid>

					<description><![CDATA[＜分散通知の仕組みを作る　STEP2: 電子メール配信＞別ページで表示 STEP2として電子メール配信を説明します。実際の配信の手順は、STEP5のブログ配信を先に行い、そのリンクURLを、電子メール、LINE、Push [&#8230;]]]></description>
										<content:encoded><![CDATA[
<hr class="wp-block-separator has-text-color has-key-color-color has-css-opacity has-key-color-background-color has-background is-style-wide"/>



<p class="wp-block-paragraph">＜分散通知の仕組みを作る　STEP2: 電子メール配信＞<br><span class="fz-12px"><a href="https://imakat.com/page-11646-4-2/" target="_blank">別ページで表示</a></span></p>



<img decoding="async" src="https://docs.google.com/drawings/d/e/2PACX-1vSFTkb6ovfeLBKdqvcsUNGg0oMLPHiIhJV04pZDhRwO-VnEsOt33oSDcoBl4UrHbkhGqm0ySJnbX6B-/pub?w=1440&amp;h=1080">



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



<p class="wp-block-paragraph">STEP2として電子メール配信を説明します。実際の配信の手順は、STEP5のブログ配信を先に行い、そのリンクURLを、電子メール、LINE、Push7の関係リンクにします。</p>



<p class="wp-block-paragraph">ここでは、昔からある、電子メールによる配信、グループメール配信を基本形として先に扱うことにします。</p>



<p class="wp-block-paragraph">なおGoogleグループメールの配信先ですが、Googleメールでよく使うGoogle連絡先を使います。Google連絡先にまず登録（※1)→GoogleグループアプリへGoogle連絡先に登録されているメールアドレスを呼び込んで登録、という手順を行なっています。原本の共有化です。</p>



<p class="wp-block-paragraph">ビジネス用途であるGoogle workspaceというサービスがあり、これの方が本格的ですが、あくまで無料の小規模な利用から始めますので、普通のGoogle個人アカウントを使います。これであっても、配信件数限度は少なくなりますが、Googleグループメール は使うことができます。 </p>



<p class="wp-block-paragraph">Google個人アカウント@gmail.comを持っていれば、<br>Google個人アカウント@googlegroups.com というグループメールアドレスが取得出来ます。</p>



<p class="wp-block-paragraph">例えば、適当ですが、<span class="bold-red">nihonnofujisan001</span>@gmail.com、を持っていれば<br><span class="bold-red">nihonnofujisan001</span>@googlegroups.com というグループメールアドレスが取得出来ます。</p>



<p class="wp-block-paragraph">使い方は簡単、メールをたった1個、以下のように打てば、グループ全員に届くことです。</p>



<p class="wp-block-paragraph">TO:<span class="bold-red">nihonnofujisan001</span>@googlegroups.com<br>FROM:<span class="bold-red">nihonnofujisan001</span>@gmail.com<br>ーーーーーーーーーーーーーーーーーーーーー<br>＊＊＊の件<br>＊＊＊＊<br>＊＊＊＊＊＊＊＊<br></p>



<p class="wp-block-paragraph">※1: 当面、手作業で配信依頼先のメールアドレスを登録します。別のWebサイトで配信の申し込みができるようにしておりGoogleフォームを通じてGoogleSSへ記録しています。従って同じGoogleアカウントのGoogleアプリ同士なので、APIか関数で割と簡単にGoogle連絡先へ自動登録が可能でしょう。しかしメールアドレスについては、一応、イタズラの有無など人間がチェックした方がいいと捉えています。</p>



<p class="wp-block-paragraph">別の方法として、姓名、メールアドレスをGoogleSSに登録しておいて、for文でループしながら送信するやり方もあります。もし、送信手段がメールだけなら気長に待てるかも知れませんが、今回、私は、複数のSNSから次々と送ろうとしていますので、手離れよくするために、グループメールアドレスを使うようにしました。</p>



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



<h4 class="wp-block-heading">＜１＞Googleグループアプリの設定〜オーナーの配信のみに制限。</h4>



<p class="wp-block-paragraph">このグループメールは、グループメンバー間での議論に利用することが多いと思われますが、今回、私がこれを使う目的は、緊急通知の配信、です。一方通行です。従って、投稿者は私のみ、メンバーからは投稿不可、の制約を加えています。</p>



<p class="wp-block-paragraph">グループ設定の中の「投稿ポリシー」の設定：</p>



<figure class="wp-block-table"><table><tbody><tr><td>メールでの投稿を許可</td><td>許可する</td></tr><tr><td>ウエブからの投稿を許可</td><td>許可する</td></tr><tr><td>会話の履歴</td><td>オフ</td></tr><tr><td>投稿者に非公開で返信できるユーザー</td><td>グループのオーナー</td></tr><tr><td>ファイルを添付できるユーザー</td><td>グループのオーナー</td></tr><tr><td>コンテンツを管理できるユーザー</td><td>グループのオーナー</td></tr><tr><td>メタデータを管理できるユーザー</td><td>グループのオーナー</td></tr><tr><td>グループとして投稿できるユーザー</td><td>グループのオーナー</td></tr><tr><td>デフォルトの差出人</td><td>投稿者のアドレス</td></tr><tr><td>メッセージの管理</td><td>管理しない</td></tr><tr><td>新しいメンバーの制限</td><td>新しいメンバーに投稿を許可しない</td></tr><tr><td>スパムメッセージの処理</td><td>スパムに分類されたすべてのメッセージを拒否</td></tr><tr><td>拒否されたメッセージに関する通知</td><td>オフ</td></tr></tbody></table></figure>



<p class="wp-block-paragraph">以上のように、グループのオーナーからの一方的な通知に限定しています。</p>



<p class="wp-block-paragraph">送信テストをするために、少なくとも２個、自分で確認できるメールアドレスを連絡先→グループメール連絡先選択、を済ませておきます。</p>



<p class="wp-block-paragraph">どのメーラーでもいいですので、例えば私は、Macの純正アプリである「メール」アプリを使って以下のように送ってみます。Gmailの送信を使う必要はありません。</p>



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



<p class="wp-block-paragraph">その結果、以下のようなメールが<strong>複数箇所へ</strong>届けばOKです（赤塗りが多くてすみません。）ーー以下の部分は、グループ設定の中で、規定できます。但しーーー以下の内容は、無料のアカウントでは変更できません。やむを得ず、「下の段落は無視してください。」と注釈しました。</p>



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



<p class="wp-block-paragraph">以上でGoogleグループメール側の準備が出来ました。</p>



<p class="wp-block-paragraph"></p>



<h4 class="wp-block-heading">&lt;２&gt;  GoogleSSへの取り込み、及び GAS記述</h4>



<p class="wp-block-paragraph">緊急通知なので、送信する内容はコンパクトに、subject とbodyだけです。</p>



<p class="wp-block-paragraph"></p>



<figure class="wp-block-image size-large"><a href="https://imakat.com/rd.php?id=0OT7taEA.png" target="_blank"><img decoding="async" src="https://imakat.com/rd.php?id=0OT7taEA.png" alt=""/></a><figcaption class="wp-element-caption">グループメール投稿のGoogleSS</figcaption></figure>



<p class="wp-block-paragraph">この画面には、Googleフォームへ入力した通知文が取り込まれるため、内容を確認するだけです。問題がなければ、「グループメール 投稿」ボタンを押します。</p>



<p class="wp-block-paragraph"><strong>通知文の読み込み：</strong></p>



<p class="wp-block-paragraph">IMPORTRANGE関数を使います。<br>読み込みたいGoogleSSのURLが、</p>



<pre class="wp-block-code"><code>https:&#47;&#47;docs.google.com/spreadsheets/d/【この部分】/edit#gid=0</code></pre>



<p class="wp-block-paragraph">【この部分】を以下の部分に当てはめてください。sheet1は実際のシート名、A20のところも実際のセル位置を当てはめてください。</p>



<p class="wp-block-paragraph">タイトル、本文、関係リンクそれぞれ、当てはめてください。</p>



<pre class="wp-block-code"><code>=IMPORTRANGE("【この部分】","sheet1!A20")
=IMPORTRANGE("【この部分】","sheet1!A22")
=IMPORTRANGE("【この部分】","sheet1!A24")</code></pre>



<p class="wp-block-paragraph"><strong>GASの記述：</strong></p>



<p class="wp-block-paragraph"><span class="bold-red">赤字</span>は、例示。</p>



<pre class="wp-block-code"><code>function sendMail(){
  const ss = SpreadsheetApp.getActiveSpreadsheet();
  const sheet = ss.getActiveSheet();
  const from = '<span class="bold-red">nihonnofujisan001</span>@gmail.com';
  const to = '<span class="bold-red">nihonnofujisan001</span>@googlegroups.com';
  const subject = sheet.getRange(<span class="bold-red">3,1</span>).getValue();
  const body = sheet.getRange(<span class="bold-red">9,1</span>).getValue();
GmailApp.sendEmail(to, subject, body);
}</code></pre>



<p class="wp-block-paragraph">わずか９行です。</p>



<h4 class="wp-block-heading">＜３＞GoogleSSのGASをiPhoneで使う裏技。PC版サイトで扱う。</h4>



<p class="wp-block-paragraph">iPhoneでの操作方法は、以下の動画をご覧ください。</p>



<p class="wp-block-paragraph">PC版にした後、iPhoneを横向きにするのがポイントです。</p>



<p class="wp-block-paragraph"></p>



<p class="has-text-align-center wp-block-paragraph"><span class="fz-12px">　　字幕の翻訳はトップ左の言語をお選びください。</span></p>



<figure class="wp-block-video aligncenter"><video controls src="https://imakat.com/rd.php?id=ZRKVRwmK.mov" playsinline><track src="https://imakat.com/wp-content/uploads/2021/10/211013_緊急通知をiPhoneから_日本語.vtt" kind="captions" srclang="ja" label="緊急通知をiPhone送信"/></video><figcaption class="wp-element-caption"><span class="fz-12px">＜字幕は、画面右下の字幕選択をON↑＞</span></figcaption></figure>



<div class="example">
[google-translator]
＜字幕＞<br>
〜緊急通知をiPhoneから投稿〜<br>
(1)Google Chromeを使います。<br>
(2)ブックマークから目的のGoogleSSを選びます。<br>
(3)モバイルサイトなので画面表示が一部分しか見えません。<br>
(4)「PC版サイトを見る」を選択します。<br>
(5)全体が見えると、今度は文字が小さ過ぎる。<br>
(6)iPhoneを横向きに変えます。<br>
(7)キーボードが邪魔。ここの「閉じる」を押します。<br>
(8)見やすい。<br>
(9)文章の最終チェックをします。<br>
(10)「グループメール投稿」のボタンを押します。<br>
(11)スクリプトが実行されています。<br>
(12)スクリプトが終了。<br>
E(13)このGoogleSSを閉じます。
</div>

<style>
div.example {
width: 100%; /*ブロックの幅*/
height: 200px; /*ブロックの高さ*/
background-color: #EDF7FF; /*背景色*/
overflow: scroll; /*スクロール*/
}
</style>



<p class="wp-block-paragraph">STEP3以降、GoogleSSの操作は、これと同じやり方になります。<br>つまり、<strong><span class="marker">「作業の標準化」です。アプリは違っても操作方法は同じ。作業方法を一つを覚えれば、電子メールも、LINEも、Push7も、ブログ投稿も、それで済んでしまう。</span></strong></p>



<p class="wp-block-paragraph">それでは次回STEP3は、LINEを使ったメッセージ配信をLINEアプリを触らずに外側から実行する方法を説明します。</p>



<p class="wp-block-paragraph"><a href="https://imakat.com/2021/10/14/13982/" target="_blank">STEP3</a></p>



<p class="wp-block-paragraph">以上。</p>


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