{"id":25821,"date":"2025-01-25T14:01:38","date_gmt":"2025-01-25T05:01:38","guid":{"rendered":"http:\/\/www.tyosuke20xx.com\/blog\/?p=25821"},"modified":"2025-01-25T14:01:39","modified_gmt":"2025-01-25T05:01:39","slug":"%e3%83%a9%e3%82%a4%e3%83%96%e3%82%b9%e3%83%88%e3%83%aa%e3%83%bc%e3%83%9f%e3%83%b3%e3%82%b0%e3%82%b5%e3%82%a4%e3%83%88","status":"publish","type":"post","link":"http:\/\/www.tyosuke20xx.com\/blog\/?p=25821","title":{"rendered":"\u30e9\u30a4\u30d6\u30b9\u30c8\u30ea\u30fc\u30df\u30f3\u30b0\u30b5\u30a4\u30c8"},"content":{"rendered":"\n<pre class=\"wp-block-code\"><code>&lt;!DOCTYPE html>\n&lt;html lang=\"ja\">\n&lt;head>\n  &lt;meta charset=\"UTF-8\" \/>\n  &lt;title>\u7591\u4f3c\u914d\u4fe1\u30b5\u30a4\u30c8 - PC\u753b\u9762\uff06\u30b7\u30b9\u30c6\u30e0\u97f3\u58f0&lt;\/title>\n  &lt;style>\n    \/* \u30d9\u30fc\u30b9\u30ea\u30bb\u30c3\u30c8 *\/\n    * {\n      box-sizing: border-box;\n      margin: 0;\n      padding: 0;\n    }\n\n    body {\n      font-family: sans-serif;\n      background: #f5f5f5;\n      color: #333;\n    }\n\n    header, footer {\n      background: #333;\n      color: #fff;\n      padding: 15px;\n      text-align: center;\n    }\n\n    header h1 {\n      margin: 0;\n      font-size: 1.5rem;\n      letter-spacing: 0.05em;\n    }\n\n    footer p {\n      margin: 0;\n      font-size: 0.9rem;\n    }\n\n    main {\n      max-width: 1200px;\n      margin: 20px auto;\n      padding: 20px;\n      background: #fff;\n      box-shadow: 0 0 10px rgba(0,0,0,0.1);\n    }\n\n    .page-title {\n      text-align: center;\n      margin-bottom: 20px;\n      font-size: 1.4rem;\n    }\n\n    \/* 2\u30ab\u30e9\u30e0\u30ec\u30a4\u30a2\u30a6\u30c8 *\/\n    .container {\n      display: flex;\n      flex-wrap: wrap;\n      gap: 20px;\n    }\n    .video-section {\n      flex: 1 1 600px;\n      min-width: 300px;\n    }\n    .aside-section {\n      flex: 1 1 350px;\n      min-width: 300px;\n      background: #fafafa;\n      border-left: 1px solid #ccc;\n      padding: 10px;\n    }\n\n    \/* \u52d5\u753b\u8868\u793a\u9818\u57df *\/\n    .video-wrapper {\n      background: #000;\n      overflow: hidden;\n    }\n    .video-wrapper video {\n      display: block;\n      width: 100%;\n      height: auto;\n      background: #000;\n    }\n    .video-title {\n      margin: 10px 0;\n      font-weight: bold;\n    }\n    .video-controls {\n      text-align: center;\n      margin-top: 10px;\n    }\n    .video-controls button {\n      margin: 0 5px;\n      padding: 8px 16px;\n      font-size: 1rem;\n      cursor: pointer;\n    }\n\n    \/* \u30c1\u30e3\u30c3\u30c8UI *\/\n    .chat-section {\n      display: flex;\n      flex-direction: column;\n      height: 400px;\n    }\n    .chat-log {\n      flex: 1;\n      border: 1px solid #ccc;\n      padding: 10px;\n      overflow-y: auto;\n      margin-bottom: 10px;\n      background: #fff;\n    }\n    .chat-log p {\n      margin: 0 0 5px 0;\n    }\n    .chat-log p span.username {\n      font-weight: bold;\n      color: #3366cc;\n      margin-right: 5px;\n    }\n    .chat-input-area {\n      display: flex;\n      gap: 5px;\n    }\n    .chat-input-area input&#91;type=\"text\"] {\n      flex: 1;\n      padding: 8px;\n      font-size: 1rem;\n    }\n    .chat-input-area button {\n      padding: 8px 16px;\n      font-size: 1rem;\n      cursor: pointer;\n    }\n\n    \/* \u30b9\u30b1\u30b8\u30e5\u30fc\u30eb *\/\n    .schedule {\n      margin-top: 20px;\n    }\n    .schedule h2 {\n      font-size: 1.2rem;\n      margin-bottom: 10px;\n    }\n    .schedule table {\n      width: 100%;\n      border-collapse: collapse;\n    }\n    .schedule th, .schedule td {\n      border: 1px solid #ccc;\n      padding: 10px;\n      text-align: center;\n    }\n    .schedule th {\n      background: #f0f0f0;\n    }\n    .schedule tr:nth-child(even) {\n      background: #fafafa;\n    }\n  &lt;\/style>\n&lt;\/head>\n&lt;body>\n\n&lt;!-- \u30d8\u30c3\u30c0\u30fc -->\n&lt;header>\n  &lt;h1>My Advanced Live Streaming (Local Demo)&lt;\/h1>\n&lt;\/header>\n\n&lt;!-- \u30e1\u30a4\u30f3\u30b3\u30f3\u30c6\u30f3\u30c4 -->\n&lt;main>\n  &lt;div class=\"page-title\">PC\u753b\u9762\uff06\u30b7\u30b9\u30c6\u30e0\u97f3\u58f0\u3092\u30ed\u30fc\u30ab\u30eb\u518d\u751f\u3059\u308b\u30c7\u30e2&lt;\/div>\n\n  &lt;div class=\"container\">\n\n    &lt;!-- \u25bc \u52d5\u753b\u30a8\u30ea\u30a2 \u25bc -->\n    &lt;section class=\"video-section\">\n      &lt;div class=\"video-title\">\u7591\u4f3c\u30e9\u30a4\u30d6\u6620\u50cf&lt;\/div>\n      &lt;div class=\"video-wrapper\">\n        &lt;video id=\"liveVideo\" controls autoplay>&lt;\/video>\n      &lt;\/div>\n\n      &lt;!-- \u30dc\u30bf\u30f3\u985e -->\n      &lt;div style=\"text-align: center; margin-top: 10px;\">\n        &lt;button id=\"screenShareBtn\">\u753b\u9762\u5171\u6709(\u30b7\u30b9\u30c6\u30e0\u97f3\u58f0)&lt;\/button>\n        &lt;button id=\"cameraShareBtn\">\u30ab\u30e1\u30e9\uff06\u30de\u30a4\u30af&lt;\/button>\n        &lt;button id=\"stopBtn\">\u505c\u6b62&lt;\/button>\n      &lt;\/div>\n\n      &lt;!-- \u518d\u751f\/\u4e00\u6642\u505c\u6b62\/\u30df\u30e5\u30fc\u30c8\/\u5168\u753b\u9762 -->\n      &lt;div class=\"video-controls\">\n        &lt;button id=\"playBtn\">\u518d\u751f&lt;\/button>\n        &lt;button id=\"pauseBtn\">\u4e00\u6642\u505c\u6b62&lt;\/button>\n        &lt;button id=\"muteBtn\">\u30df\u30e5\u30fc\u30c8\/\u89e3\u9664&lt;\/button>\n        &lt;button id=\"fullscreenBtn\">\u5168\u753b\u9762&lt;\/button>\n      &lt;\/div>\n\n      &lt;div class=\"schedule\">\n        &lt;h2>\u914d\u4fe1\u30b9\u30b1\u30b8\u30e5\u30fc\u30eb\uff08\u4eee\uff09&lt;\/h2>\n        &lt;table>\n          &lt;thead>\n            &lt;tr>\n              &lt;th>\u65e5\u4ed8&lt;\/th>\n              &lt;th>\u914d\u4fe1\u30bf\u30a4\u30c8\u30eb&lt;\/th>\n              &lt;th>\u958b\u59cb\u6642\u9593&lt;\/th>\n              &lt;th>\u4e88\u5b9a&lt;\/th>\n            &lt;\/tr>\n          &lt;\/thead>\n          &lt;tbody>\n            &lt;tr>\n              &lt;td>2\/15&lt;\/td>\n              &lt;td>PC\u753b\u9762\u5171\u6709\u30c6\u30b9\u30c8&lt;\/td>\n              &lt;td>18:00&lt;\/td>\n              &lt;td>30\u5206&lt;\/td>\n            &lt;\/tr>\n            &lt;tr>\n              &lt;td>2\/18&lt;\/td>\n              &lt;td>\u97f3\u58f0\u30df\u30ad\u30b7\u30f3\u30b0\u7df4\u7fd2&lt;\/td>\n              &lt;td>20:00&lt;\/td>\n              &lt;td>1\u6642\u9593&lt;\/td>\n            &lt;\/tr>\n            &lt;tr>\n              &lt;td>2\/20&lt;\/td>\n              &lt;td>\u9031\u672b\u96d1\u8ac7&lt;\/td>\n              &lt;td>21:30&lt;\/td>\n              &lt;td>2\u6642\u9593&lt;\/td>\n            &lt;\/tr>\n          &lt;\/tbody>\n        &lt;\/table>\n      &lt;\/div>\n    &lt;\/section>\n\n    &lt;!-- \u25bc \u30c1\u30e3\u30c3\u30c8\u30a8\u30ea\u30a2 \u25bc -->\n    &lt;aside class=\"aside-section\">\n      &lt;h2>\u30c1\u30e3\u30c3\u30c8&lt;\/h2>\n      &lt;div class=\"chat-section\">\n        &lt;!-- \u30c1\u30e3\u30c3\u30c8\u30ed\u30b0 -->\n        &lt;div id=\"chatLog\" class=\"chat-log\">&lt;\/div>\n        &lt;!-- \u5165\u529b\u30d5\u30a9\u30fc\u30e0 -->\n        &lt;div class=\"chat-input-area\">\n          &lt;input type=\"text\" id=\"usernameInput\" placeholder=\"\u30e6\u30fc\u30b6\u30fc\u540d\" \/>\n          &lt;input type=\"text\" id=\"messageInput\" placeholder=\"\u30e1\u30c3\u30bb\u30fc\u30b8\u3092\u5165\u529b\u2026\" \/>\n          &lt;button id=\"sendBtn\">\u9001\u4fe1&lt;\/button>\n        &lt;\/div>\n      &lt;\/div>\n    &lt;\/aside>\n\n  &lt;\/div>&lt;!-- \/container -->\n\n&lt;\/main>\n\n&lt;!-- \u30d5\u30c3\u30bf\u30fc -->\n&lt;footer>\n  &lt;p>\u00a9 2025 My Advanced Live Streaming (Local Demo)&lt;\/p>\n&lt;\/footer>\n\n&lt;script>\n\/*****************************************************************\n * 1. PC\u753b\u9762\uff06\u30b7\u30b9\u30c6\u30e0\u97f3\u58f0 or \u30ab\u30e1\u30e9\uff06\u30de\u30a4\u30af\u3092\u53d6\u5f97\n *****************************************************************\/\nconst video = document.getElementById('liveVideo');\nconst screenShareBtn = document.getElementById('screenShareBtn');\nconst cameraShareBtn = document.getElementById('cameraShareBtn');\nconst stopBtn = document.getElementById('stopBtn');\n\nlet localStream = null;\n\n\/\/ \u753b\u9762\u5171\u6709 (PC\u753b\u9762 + \u30b7\u30b9\u30c6\u30e0\u97f3\u58f0)\nasync function startScreenShare() {\n  stopMedia(); \/\/ \u65e2\u5b58\u30b9\u30c8\u30ea\u30fc\u30e0\u3092\u6b62\u3081\u3066\u304b\u3089\u958b\u59cb\n  try {\n    \/\/ getDisplayMedia\u3067\u753b\u9762\u3092\u5171\u6709\n    \/\/ audio:true -> Chrome\u306e\u5834\u5408\u300c\u30b7\u30b9\u30c6\u30e0\u97f3\u58f0\u3092\u5171\u6709\u300d\u30aa\u30d7\u30b7\u30e7\u30f3\u304c\u8868\u793a\u3055\u308c\u308b\n    localStream = await navigator.mediaDevices.getDisplayMedia({\n      video: true,\n      audio: true \/\/ \u305f\u3060\u3057\u30d6\u30e9\u30a6\u30b6\u3084OS\u306b\u3088\u3063\u3066\u306f\u7121\u8996\u3055\u308c\u308b\u53ef\u80fd\u6027\u3042\u308a\n    });\n    video.srcObject = localStream;\n    \/\/ \u30b7\u30b9\u30c6\u30e0\u97f3\u58f0\u3092\u30e2\u30cb\u30bf\u30ea\u30f3\u30b0\u3059\u308b\u5834\u5408\u3001\u30df\u30e5\u30fc\u30c8OFF\u306b\u3059\u308b\n    video.muted = false; \n    console.log('\u753b\u9762\u5171\u6709\u958b\u59cb (\u30b7\u30b9\u30c6\u30e0\u97f3\u58f0\u542b\u3080\u53ef\u80fd\u6027)');\n  } catch (err) {\n    alert('\u753b\u9762\u5171\u6709\u3092\u958b\u59cb\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f: ' + err.message);\n  }\n}\n\n\/\/ \u30ab\u30e1\u30e9\uff06\u30de\u30a4\u30af\nasync function startCameraShare() {\n  stopMedia();\n  try {\n    localStream = await navigator.mediaDevices.getUserMedia({video: true, audio: true});\n    video.srcObject = localStream;\n    \/\/ \u81ea\u5206\u306e\u30de\u30a4\u30af\u97f3\u58f0\u304c\u30eb\u30fc\u30d7\u3057\u306a\u3044\u3088\u3046\u306b\u3057\u305f\u3044\u5834\u5408\u306f video.muted = true;\n    video.muted = true; \n    console.log('\u30ab\u30e1\u30e9\uff06\u30de\u30a4\u30af\u958b\u59cb');\n  } catch (err) {\n    alert('\u30ab\u30e1\u30e9\/\u30de\u30a4\u30af\u3092\u53d6\u5f97\u3067\u304d\u307e\u305b\u3093\u3067\u3057\u305f: ' + err.message);\n  }\n}\n\n\/\/ \u505c\u6b62\nfunction stopMedia() {\n  if (!localStream) return;\n  localStream.getTracks().forEach(track => track.stop());\n  localStream = null;\n  video.srcObject = null;\n  console.log('\u30e1\u30c7\u30a3\u30a2\u505c\u6b62');\n}\n\nscreenShareBtn.addEventListener('click', startScreenShare);\ncameraShareBtn.addEventListener('click', startCameraShare);\nstopBtn.addEventListener('click', stopMedia);\n\n\n\/*****************************************************************\n * 2. \u518d\u751f\/\u4e00\u6642\u505c\u6b62\/\u30df\u30e5\u30fc\u30c8\/\u5168\u753b\u9762\u306a\u3069\u52d5\u753b\u30b3\u30f3\u30c8\u30ed\u30fc\u30eb\n *****************************************************************\/\nconst playBtn = document.getElementById('playBtn');\nconst pauseBtn = document.getElementById('pauseBtn');\nconst muteBtn = document.getElementById('muteBtn');\nconst fullscreenBtn = document.getElementById('fullscreenBtn');\n\nplayBtn.addEventListener('click', () => {\n  video.play();\n});\npauseBtn.addEventListener('click', () => {\n  video.pause();\n});\nmuteBtn.addEventListener('click', () => {\n  video.muted = !video.muted;\n});\nfullscreenBtn.addEventListener('click', () => {\n  if (!document.fullscreenElement) {\n    video.requestFullscreen().catch(err => {\n      console.warn('\u30d5\u30eb\u30b9\u30af\u30ea\u30fc\u30f3\u30e2\u30fc\u30c9\u306b\u3067\u304d\u307e\u305b\u3093:', err);\n    });\n  } else {\n    document.exitFullscreen();\n  }\n});\n\n\n\/*****************************************************************\n * 3. \u7c21\u6613\u30c1\u30e3\u30c3\u30c8\u6a5f\u80fd\uff08\u30ed\u30fc\u30ab\u30eb\u306e\u307f\uff09\n *****************************************************************\/\nconst chatLog = document.getElementById('chatLog');\nconst usernameInput = document.getElementById('usernameInput');\nconst messageInput = document.getElementById('messageInput');\nconst sendBtn = document.getElementById('sendBtn');\n\nlet messages = &#91;];\n\nfunction renderChatLog() {\n  chatLog.innerHTML = '';\n  messages.forEach(msg => {\n    const p = document.createElement('p');\n    const userSpan = document.createElement('span');\n    userSpan.className = 'username';\n    userSpan.textContent = msg.username + ': ';\n    const textNode = document.createTextNode(msg.text);\n    p.appendChild(userSpan);\n    p.appendChild(textNode);\n    chatLog.appendChild(p);\n  });\n  chatLog.scrollTop = chatLog.scrollHeight;\n}\n\nfunction sendMessage() {\n  const username = usernameInput.value.trim();\n  const text = messageInput.value.trim();\n  if (!username || !text) return;\n\n  messages.push({ username, text });\n  renderChatLog();\n  messageInput.value = '';\n}\n\nsendBtn.addEventListener('click', sendMessage);\nmessageInput.addEventListener('keydown', e => {\n  if (e.key === 'Enter') sendMessage();\n});\n\n\/\/ \u30c7\u30e2\u7528\u30e1\u30c3\u30bb\u30fc\u30b8\n(function initDemoChat() {\n  messages.push(\n    { username: 'Alice', text: '\u3053\u3093\u306b\u3061\u306f\uff01' },\n    { username: 'Bob', text: '\u30b7\u30b9\u30c6\u30e0\u97f3\u58f0\u805e\u3053\u3048\u308b\uff1f' },\n    { username: 'Carol', text: '\u30bf\u30d6\u306e\u97f3\u306f\u5171\u6709\u3067\u304d\u3066\u307e\u3059\u301c' }\n  );\n  renderChatLog();\n})();\n&lt;\/script>\n\n&lt;\/body>\n&lt;\/html>\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"_uf_show_specific_survey":0,"_uf_disable_surveys":false,"footnotes":""},"categories":[80],"tags":[3],"class_list":["post-25821","post","type-post","status-publish","format-standard","hentry","category-html","tag-programming"],"aioseo_notices":[],"jetpack_featured_media_url":"","_links":{"self":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/25821","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=25821"}],"version-history":[{"count":1,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/25821\/revisions"}],"predecessor-version":[{"id":25822,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/25821\/revisions\/25822"}],"wp:attachment":[{"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=25821"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=25821"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.tyosuke20xx.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=25821"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}