Update index.html
Browse files- index.html +380 -322
 
    	
        index.html
    CHANGED
    
    | 
         @@ -2,10 +2,11 @@ 
     | 
|
| 2 | 
         
             
            <html lang="ja">
         
     | 
| 3 | 
         
             
            <head>
         
     | 
| 4 | 
         
             
                <meta charset="UTF-8">
         
     | 
| 
         | 
|
| 5 | 
         
             
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
         
     | 
| 6 | 
         
             
                <title>高度な音声動画プレイヤー</title>
         
     | 
| 7 | 
         
            -
                <script src="https://soiz1-eruda3.hf.space/eruda.js"></script>
         
     | 
| 8 | 
         
             
                <style>
         
     | 
| 
         | 
|
| 9 | 
         
             
                    body {
         
     | 
| 10 | 
         
             
                        font-family: 'Arial', sans-serif;
         
     | 
| 11 | 
         
             
                        background-color: #0a192f;
         
     | 
| 
         @@ -320,28 +321,7 @@ 
     | 
|
| 320 | 
         
             
                        width: 100%;
         
     | 
| 321 | 
         
             
                        border-radius: 0;
         
     | 
| 322 | 
         
             
                    }
         
     | 
| 323 | 
         
            -
             
     | 
| 324 | 
         
            -
                    .time-input-container {
         
     | 
| 325 | 
         
            -
                        display: flex;
         
     | 
| 326 | 
         
            -
                        align-items: center;
         
     | 
| 327 | 
         
            -
                        gap: 5px;
         
     | 
| 328 | 
         
            -
                    }
         
     | 
| 329 | 
         
            -
                    
         
     | 
| 330 | 
         
            -
                    .set-time-btn {
         
     | 
| 331 | 
         
            -
                        background-color: #112240;
         
     | 
| 332 | 
         
            -
                        border: 1px solid #64ffda;
         
     | 
| 333 | 
         
            -
                        color: #e6f1ff;
         
     | 
| 334 | 
         
            -
                        padding: 5px 8px;
         
     | 
| 335 | 
         
            -
                        border-radius: 3px;
         
     | 
| 336 | 
         
            -
                        cursor: pointer;
         
     | 
| 337 | 
         
            -
                        font-size: 12px;
         
     | 
| 338 | 
         
            -
                        transition: background-color 0.3s;
         
     | 
| 339 | 
         
            -
                    }
         
     | 
| 340 | 
         
            -
                    
         
     | 
| 341 | 
         
            -
                    .set-time-btn:hover {
         
     | 
| 342 | 
         
            -
                        background-color: rgba(100, 255, 218, 0.2);
         
     | 
| 343 | 
         
            -
                    }
         
     | 
| 344 | 
         
            -
                    
         
     | 
| 345 | 
         
             
                    /* ローディングアニメーション */
         
     | 
| 346 | 
         
             
                    .loading-overlay {
         
     | 
| 347 | 
         
             
                        position: fixed;
         
     | 
| 
         @@ -433,6 +413,22 @@ 
     | 
|
| 433 | 
         
             
                            transform: rotate(360deg);
         
     | 
| 434 | 
         
             
                        }
         
     | 
| 435 | 
         
             
                    }
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 436 | 
         
             
                </style>
         
     | 
| 437 | 
         
             
            </head>
         
     | 
| 438 | 
         
             
            <body>
         
     | 
| 
         @@ -482,16 +478,16 @@ 
     | 
|
| 482 | 
         
             
                        <h2>設定</h2>
         
     | 
| 483 | 
         
             
                        <div class="setting-item">
         
     | 
| 484 | 
         
             
                            <label for="start-time">再生開始秒数:</label>
         
     | 
| 485 | 
         
            -
                            <div 
     | 
| 486 | 
         
             
                                <input type="number" id="start-time" min="0" value="0" step="0.1">
         
     | 
| 487 | 
         
            -
                                <button class="set- 
     | 
| 488 | 
         
             
                            </div>
         
     | 
| 489 | 
         
             
                        </div>
         
     | 
| 490 | 
         
             
                        <div class="setting-item">
         
     | 
| 491 | 
         
             
                            <label for="end-time">再生終了秒数:</label>
         
     | 
| 492 | 
         
            -
                            <div 
     | 
| 493 | 
         
             
                                <input type="number" id="end-time" min="0" value="0" step="0.1">
         
     | 
| 494 | 
         
            -
                                <button class="set- 
     | 
| 495 | 
         
             
                            </div>
         
     | 
| 496 | 
         
             
                        </div>
         
     | 
| 497 | 
         
             
                        <div class="setting-item">
         
     | 
| 
         @@ -548,6 +544,45 @@ 
     | 
|
| 548 | 
         | 
| 549 | 
         
             
                <script>
         
     | 
| 550 | 
         
             
                    document.addEventListener('DOMContentLoaded', function() {
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 551 | 
         
             
                        // 要素を取得
         
     | 
| 552 | 
         
             
                        const video = document.getElementById('video');
         
     | 
| 553 | 
         
             
                        const videoContainer = document.getElementById('video-container');
         
     | 
| 
         @@ -565,19 +600,16 @@ 
     | 
|
| 565 | 
         
             
                        const fullscreenBtn = document.getElementById('fullscreen-btn');
         
     | 
| 566 | 
         
             
                        const startTimeInput = document.getElementById('start-time');
         
     | 
| 567 | 
         
             
                        const endTimeInput = document.getElementById('end-time');
         
     | 
| 568 | 
         
            -
                        const setStartBtn = document.getElementById('set-start-btn');
         
     | 
| 569 | 
         
            -
                        const setEndBtn = document.getElementById('set-end-btn');
         
     | 
| 570 | 
         
             
                        const loopCheckbox = document.getElementById('loop');
         
     | 
| 571 | 
         
             
                        const globalVolumeSlider = document.getElementById('global-volume');
         
     | 
| 572 | 
         
             
                        const globalVolumeValue = document.getElementById('global-volume-value');
         
     | 
| 573 | 
         
             
                        const audioSliders = document.querySelectorAll('.audio-slider');
         
     | 
| 574 | 
         
             
                        const volumeValues = document.querySelectorAll('.volume-value');
         
     | 
| 575 | 
         
            -
                        const  
     | 
| 
         | 
|
| 576 | 
         | 
| 577 | 
         
             
                        // 音声オブジェクトを作成
         
     | 
| 578 | 
         
             
                        const audioElements = {};
         
     | 
| 579 | 
         
            -
                        const audioContexts = {};
         
     | 
| 580 | 
         
            -
                        const audioGains = {};
         
     | 
| 581 | 
         | 
| 582 | 
         
             
                        // 音声ファイル名の配列
         
     | 
| 583 | 
         
             
                        const audioFiles = ['p', 'a', 't', 's', 'k'];
         
     | 
| 
         @@ -588,80 +620,89 @@ 
     | 
|
| 588 | 
         
             
                        let isVideoPlaying = false;
         
     | 
| 589 | 
         
             
                        let lastVolume = 1;
         
     | 
| 590 | 
         
             
                        let currentPlaybackRate = 1;
         
     | 
| 591 | 
         
            -
                        let allAudioLoaded = false;
         
     | 
| 592 | 
         
            -
                        let videoLoaded = false;
         
     | 
| 593 | 
         
            -
                        
         
     | 
| 594 | 
         
            -
                        // ローディングアニメーションを非表示にする関数
         
     | 
| 595 | 
         
            -
                        function hideLoadingOverlay() {
         
     | 
| 596 | 
         
            -
                            loadingOverlay.style.opacity = '0';
         
     | 
| 597 | 
         
            -
                            setTimeout(function() {
         
     | 
| 598 | 
         
            -
                                loadingOverlay.style.display = 'none';
         
     | 
| 599 | 
         
            -
                            }, 1000);
         
     | 
| 600 | 
         
            -
                        }
         
     | 
| 601 | 
         
            -
                        
         
     | 
| 602 | 
         
            -
                        // すべてのメディアが読み込まれたかチェック
         
     | 
| 603 | 
         
            -
                        function checkAllMediaLoaded() {
         
     | 
| 604 | 
         
            -
                            if (allAudioLoaded && videoLoaded) {
         
     | 
| 605 | 
         
            -
                                setTimeout(hideLoadingOverlay, 500);
         
     | 
| 606 | 
         
            -
                            }
         
     | 
| 607 | 
         
            -
                        }
         
     | 
| 608 | 
         | 
| 609 | 
         
             
                        // 動画のメタデータが読み込まれたら
         
     | 
| 610 | 
         
             
                        video.addEventListener('loadedmetadata', function() {
         
     | 
| 611 | 
         
            -
                             
     | 
| 612 | 
         
            -
             
     | 
| 613 | 
         
            -
             
     | 
| 614 | 
         
            -
             
     | 
| 615 | 
         
            -
             
     | 
| 616 | 
         
            -
             
     | 
| 617 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 618 | 
         
             
                        });
         
     | 
| 619 | 
         | 
| 620 | 
         
            -
                        //  
     | 
| 621 | 
         
             
                        video.addEventListener('error', function() {
         
     | 
| 622 | 
         
            -
                             
     | 
| 623 | 
         
            -
                            videoLoaded = true;
         
     | 
| 624 | 
         
            -
                            checkAllMediaLoaded();
         
     | 
| 625 | 
         
             
                        });
         
     | 
| 626 | 
         | 
| 627 | 
         
            -
                        //  
     | 
| 628 | 
         
            -
                        playPauseBtn.addEventListener('click', function( 
     | 
| 629 | 
         
            -
                             
     | 
| 630 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 631 | 
         
             
                        });
         
     | 
| 632 | 
         | 
| 633 | 
         
            -
                        // 時間表示を更新 
     | 
| 634 | 
         
             
                        function updateTimeDisplay() {
         
     | 
| 635 | 
         
            -
                             
     | 
| 636 | 
         
            -
             
     | 
| 637 | 
         
            -
             
     | 
| 638 | 
         
            -
             
     | 
| 639 | 
         
            -
             
     | 
| 640 | 
         
            -
             
     | 
| 641 | 
         
            -
             
     | 
| 642 | 
         
            -
             
     | 
| 643 | 
         
            -
             
     | 
| 644 | 
         
            -
             
     | 
| 645 | 
         
            -
             
     | 
| 646 | 
         
            -
                                 
     | 
| 647 | 
         
            -
             
     | 
| 648 | 
         
            -
             
     | 
| 649 | 
         
            -
             
     | 
| 650 | 
         
            -
             
     | 
| 651 | 
         
            -
             
     | 
| 652 | 
         
            -
             
     | 
| 653 | 
         
            -
             
     | 
| 654 | 
         
            -
             
     | 
| 655 | 
         
            -
             
     | 
| 656 | 
         
            -
                                if ( 
     | 
| 657 | 
         
            -
                                     
     | 
| 658 | 
         
            -
             
     | 
| 659 | 
         
            -
             
     | 
| 660 | 
         
            -
                                         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 661 | 
         
             
                                    }
         
     | 
| 662 | 
         
            -
                                } else {
         
     | 
| 663 | 
         
            -
                                    pauseMedia();
         
     | 
| 664 | 
         
             
                                }
         
     | 
| 
         | 
|
| 
         | 
|
| 665 | 
         
             
                            }
         
     | 
| 666 | 
         
             
                        }
         
     | 
| 667 | 
         | 
| 
         @@ -672,58 +713,74 @@ 
     | 
|
| 672 | 
         | 
| 673 | 
         
             
                        // 動画終了時の処理
         
     | 
| 674 | 
         
             
                        video.addEventListener('ended', function() {
         
     | 
| 675 | 
         
            -
                             
     | 
| 676 | 
         
            -
                                 
     | 
| 677 | 
         
            -
             
     | 
| 678 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 679 | 
         
             
                            }
         
     | 
| 680 | 
         
             
                        });
         
     | 
| 681 | 
         | 
| 682 | 
         
             
                        // プログレスバークリックでシーク
         
     | 
| 683 | 
         
             
                        progressContainer.addEventListener('click', function(e) {
         
     | 
| 684 | 
         
            -
                             
     | 
| 685 | 
         
            -
             
     | 
| 686 | 
         
            -
             
     | 
| 687 | 
         
            -
             
     | 
| 688 | 
         
            -
             
     | 
| 689 | 
         
            -
             
     | 
| 690 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 691 | 
         
             
                        });
         
     | 
| 692 | 
         | 
| 693 | 
         
             
                        // 指定した時間にシーク
         
     | 
| 694 | 
         
             
                        function seekMedia(time) {
         
     | 
| 695 | 
         
            -
                             
     | 
| 696 | 
         
            -
             
     | 
| 697 | 
         
            -
             
     | 
| 698 | 
         
            -
             
     | 
| 699 | 
         
            -
             
     | 
| 700 | 
         
            -
             
     | 
| 701 | 
         
            -
             
     | 
| 702 | 
         
            -
             
     | 
| 703 | 
         
            -
             
     | 
| 704 | 
         
            -
             
     | 
| 705 | 
         
            -
             
     | 
| 706 | 
         
            -
                                 
     | 
| 707 | 
         
            -
                                    audioElements[file] 
     | 
| 708 | 
         
            -
             
     | 
| 709 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 710 | 
         
             
                        }
         
     | 
| 711 | 
         | 
| 712 | 
         
             
                        // プログレスバー上でマウス移動時に時間を表示
         
     | 
| 713 | 
         
             
                        progressContainer.addEventListener('mousemove', function(e) {
         
     | 
| 714 | 
         
            -
                             
     | 
| 715 | 
         
            -
             
     | 
| 716 | 
         
            -
             
     | 
| 717 | 
         
            -
             
     | 
| 718 | 
         
            -
             
     | 
| 719 | 
         
            -
             
     | 
| 720 | 
         
            -
             
     | 
| 721 | 
         
            -
             
     | 
| 722 | 
         
            -
             
     | 
| 723 | 
         
            -
             
     | 
| 724 | 
         
            -
             
     | 
| 725 | 
         
            -
             
     | 
| 726 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 727 | 
         
             
                        });
         
     | 
| 728 | 
         | 
| 729 | 
         
             
                        progressContainer.addEventListener('mouseleave', function() {
         
     | 
| 
         @@ -746,22 +803,30 @@ 
     | 
|
| 746 | 
         | 
| 747 | 
         
             
                        // 音量コントロール
         
     | 
| 748 | 
         
             
                        volumeSlider.addEventListener('input', function() {
         
     | 
| 749 | 
         
            -
                             
     | 
| 750 | 
         
            -
             
     | 
| 751 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 752 | 
         
             
                        });
         
     | 
| 753 | 
         | 
| 754 | 
         
             
                        // 音量ボタン
         
     | 
| 755 | 
         
             
                        volumeBtn.addEventListener('click', function() {
         
     | 
| 756 | 
         
            -
                             
     | 
| 757 | 
         
            -
                                 
     | 
| 758 | 
         
            -
             
     | 
| 759 | 
         
            -
             
     | 
| 760 | 
         
            -
             
     | 
| 761 | 
         
            -
                                 
     | 
| 762 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 763 | 
         
             
                            }
         
     | 
| 764 | 
         
            -
                            updateVolumeIcon();
         
     | 
| 765 | 
         
             
                        });
         
     | 
| 766 | 
         | 
| 767 | 
         
             
                        // 音量アイコンを更新
         
     | 
| 
         @@ -777,43 +842,59 @@ 
     | 
|
| 777 | 
         | 
| 778 | 
         
             
                        // 再生速度スライダー (動画プレイヤー)
         
     | 
| 779 | 
         
             
                        speedSlider.addEventListener('input', function() {
         
     | 
| 780 | 
         
            -
                             
     | 
| 781 | 
         
            -
             
     | 
| 782 | 
         
            -
             
     | 
| 783 | 
         
            -
             
     | 
| 784 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 785 | 
         
             
                        });
         
     | 
| 786 | 
         | 
| 787 | 
         
             
                        // 再生速度スライダー (設定メニュー)
         
     | 
| 788 | 
         
             
                        playbackSpeedSlider.addEventListener('input', function() {
         
     | 
| 789 | 
         
            -
                             
     | 
| 790 | 
         
            -
             
     | 
| 791 | 
         
            -
             
     | 
| 792 | 
         
            -
             
     | 
| 793 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 794 | 
         
             
                        });
         
     | 
| 795 | 
         | 
| 796 | 
         
             
                        function updatePlaybackRate(speed) {
         
     | 
| 797 | 
         
            -
                             
     | 
| 798 | 
         
            -
             
     | 
| 799 | 
         
            -
             
     | 
| 800 | 
         
            -
             
     | 
| 801 | 
         
            -
             
     | 
| 802 | 
         
            -
                                 
     | 
| 803 | 
         
            -
                                    audioElements[file] 
     | 
| 804 | 
         
            -
             
     | 
| 805 | 
         
            -
             
     | 
| 806 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 807 | 
         
             
                        }
         
     | 
| 808 | 
         | 
| 809 | 
         
             
                        // 全画面ボタン
         
     | 
| 810 | 
         
             
                        fullscreenBtn.addEventListener('click', function() {
         
     | 
| 811 | 
         
            -
                             
     | 
| 812 | 
         
            -
                                videoContainer.requestFullscreen 
     | 
| 813 | 
         
            -
             
     | 
| 814 | 
         
            -
                                videoContainer.webkitRequestFullscreen 
     | 
| 815 | 
         
            -
             
     | 
| 816 | 
         
            -
                                videoContainer.msRequestFullscreen 
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 817 | 
         
             
                            }
         
     | 
| 818 | 
         
             
                        });
         
     | 
| 819 | 
         | 
| 
         @@ -835,119 +916,94 @@ 
     | 
|
| 835 | 
         | 
| 836 | 
         
             
                        // 音声ファイルをロード
         
     | 
| 837 | 
         
             
                        function loadAudioFiles() {
         
     | 
| 838 | 
         
            -
                            let loadedCount = 0;
         
     | 
| 839 | 
         
            -
                            
         
     | 
| 840 | 
         
             
                            audioFiles.forEach(file => {
         
     | 
| 841 | 
         
            -
                                const audio = new Audio(`${file}.mp3`);
         
     | 
| 842 | 
         
            -
                                audio.preload = 'auto';
         
     | 
| 843 | 
         
            -
                                audio.preservesPitch = true; // ピッチを保持
         
     | 
| 844 | 
         
            -
                                audio.loop = false;
         
     | 
| 845 | 
         
            -
                                audioElements[file] = audio;
         
     | 
| 846 | 
         
            -
                                
         
     | 
| 847 | 
         
            -
                                // Web Audio API コンテキストを作成
         
     | 
| 848 | 
         
             
                                try {
         
     | 
| 849 | 
         
            -
                                    const  
     | 
| 850 | 
         
            -
                                     
     | 
| 851 | 
         
            -
                                     
     | 
| 
         | 
|
| 
         | 
|
| 852 | 
         | 
| 853 | 
         
            -
                                     
     | 
| 854 | 
         
            -
                                     
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 855 | 
         | 
| 856 | 
         
            -
                                     
     | 
| 857 | 
         
            -
                                     
     | 
| 858 | 
         
            -
             
     | 
| 859 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 860 | 
         
             
                                }
         
     | 
| 861 | 
         
            -
                                
         
     | 
| 862 | 
         
            -
                                // 音声が読み込まれたら
         
     | 
| 863 | 
         
            -
                                audio.addEventListener('loadedmetadata', function() {
         
     | 
| 864 | 
         
            -
                                    console.log(`${file}.mp3 loaded`);
         
     | 
| 865 | 
         
            -
                                    loadedCount++;
         
     | 
| 866 | 
         
            -
                                    
         
     | 
| 867 | 
         
            -
                                    if (loadedCount === audioFiles.length) {
         
     | 
| 868 | 
         
            -
                                        allAudioLoaded = true;
         
     | 
| 869 | 
         
            -
                                        checkAllMediaLoaded();
         
     | 
| 870 | 
         
            -
                                    }
         
     | 
| 871 | 
         
            -
                                });
         
     | 
| 872 | 
         
            -
                                
         
     | 
| 873 | 
         
            -
                                // エラー処理
         
     | 
| 874 | 
         
            -
                                audio.addEventListener('error', function() {
         
     | 
| 875 | 
         
            -
                                    console.error(`Error loading ${file}.mp3`);
         
     | 
| 876 | 
         
            -
                                    loadedCount++;
         
     | 
| 877 | 
         
            -
                                    
         
     | 
| 878 | 
         
            -
                                    if (loadedCount === audioFiles.length) {
         
     | 
| 879 | 
         
            -
                                        allAudioLoaded = true;
         
     | 
| 880 | 
         
            -
                                        checkAllMediaLoaded();
         
     | 
| 881 | 
         
            -
                                    }
         
     | 
| 882 | 
         
            -
                                });
         
     | 
| 883 | 
         
             
                            });
         
     | 
| 884 | 
         
             
                        }
         
     | 
| 885 | 
         | 
| 886 | 
         
             
                        function playAudio(file, startTime) {
         
     | 
| 887 | 
         
             
                            if (!audioElements[file]) return;
         
     | 
| 888 | 
         | 
| 889 | 
         
            -
                             
     | 
| 890 | 
         
            -
             
     | 
| 891 | 
         
            -
             
     | 
| 892 | 
         
            -
             
     | 
| 893 | 
         
            -
             
     | 
| 894 | 
         
            -
             
     | 
| 895 | 
         
            -
             
     | 
| 896 | 
         
            -
             
     | 
| 897 | 
         
            -
                                audioGains[file].gain.value = volume;
         
     | 
| 898 | 
         
            -
                            } else {
         
     | 
| 899 | 
         
             
                                audio.volume = volume;
         
     | 
| 900 | 
         
            -
             
     | 
| 901 | 
         
            -
             
     | 
| 902 | 
         
            -
             
     | 
| 903 | 
         
            -
             
     | 
| 904 | 
         
            -
             
     | 
| 905 | 
         
            -
             
     | 
| 906 | 
         
            -
             
     | 
| 907 | 
         
            -
             
     | 
| 908 | 
         
            -
             
     | 
| 909 | 
         
            -
             
     | 
| 910 | 
         
            -
             
     | 
| 911 | 
         
            -
             
     | 
| 912 | 
         
            -
             
     | 
| 913 | 
         
            -
             
     | 
| 914 | 
         
            -
             
     | 
| 915 | 
         
            -
                            if (playPromise !== undefined) {
         
     | 
| 916 | 
         
            -
                                playPromise.catch(e => {
         
     | 
| 917 | 
         
            -
                                    console.log("Audio play failed:", e);
         
     | 
| 918 | 
         
            -
                                    // ユーザー操作がない場合、音声をミュートにして再試行
         
     | 
| 919 | 
         
            -
                                    audio.muted = true;
         
     | 
| 920 | 
         
            -
                                    audio.play().catch(e => console.log("Retry with mute failed:", e));
         
     | 
| 921 | 
         
            -
                                });
         
     | 
| 922 | 
         
            -
                            }
         
     | 
| 923 | 
         
            -
                            
         
     | 
| 924 | 
         
            -
                            // ループ設定
         
     | 
| 925 | 
         
            -
                            audio.loop = loopCheckbox.checked;
         
     | 
| 926 | 
         
            -
                            
         
     | 
| 927 | 
         
            -
                            if (!loopCheckbox.checked) {
         
     | 
| 928 | 
         
            -
                                // ループ再生でない場合、終了時間に達したら停止
         
     | 
| 929 | 
         
            -
                                setTimeout(() => {
         
     | 
| 930 | 
         
            -
                                    if (audio.currentTime >= playEndTime) {
         
     | 
| 931 | 
         
            -
                                        audio.pause();
         
     | 
| 932 | 
         
             
                                    }
         
     | 
| 933 | 
         
            -
                                } 
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 934 | 
         
             
                            }
         
     | 
| 935 | 
         
             
                        }
         
     | 
| 936 | 
         | 
| 937 | 
         
             
                        // 再生関数
         
     | 
| 938 | 
         
             
                        function playMedia() {
         
     | 
| 939 | 
         
            -
                             
     | 
| 940 | 
         
            -
             
     | 
| 941 | 
         
            -
             
     | 
| 942 | 
         
            -
             
     | 
| 943 | 
         
            -
             
     | 
| 944 | 
         
            -
             
     | 
| 945 | 
         
            -
                                 
     | 
| 946 | 
         
            -
                                 
     | 
| 947 | 
         
            -
             
     | 
| 948 | 
         
            -
             
     | 
| 949 | 
         
            -
             
     | 
| 950 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 951 | 
         
             
                                isPlaying = true;
         
     | 
| 952 | 
         
             
                                isVideoPlaying = true;
         
     | 
| 953 | 
         
             
                                playPauseBtn.textContent = '⏸';
         
     | 
| 
         @@ -956,79 +1012,95 @@ 
     | 
|
| 956 | 
         
             
                                audioFiles.forEach(file => {
         
     | 
| 957 | 
         
             
                                    playAudio(file, video.currentTime);
         
     | 
| 958 | 
         
             
                                });
         
     | 
| 959 | 
         
            -
                            } 
     | 
| 960 | 
         
            -
                                 
     | 
| 961 | 
         
            -
                            } 
     | 
| 962 | 
         
             
                        }
         
     | 
| 963 | 
         | 
| 964 | 
         
             
                        // 一時停止関数
         
     | 
| 965 | 
         
             
                        function pauseMedia() {
         
     | 
| 966 | 
         
             
                            if (!isPlaying) return;
         
     | 
| 967 | 
         | 
| 968 | 
         
            -
                             
     | 
| 969 | 
         
            -
             
     | 
| 970 | 
         
            -
                                 
     | 
| 971 | 
         
            -
                                    audioElements[file] 
     | 
| 972 | 
         
            -
             
     | 
| 973 | 
         
            -
             
     | 
| 974 | 
         
            -
             
     | 
| 975 | 
         
            -
             
     | 
| 976 | 
         
            -
             
     | 
| 977 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 978 | 
         
             
                        }
         
     | 
| 979 | 
         | 
| 980 | 
         
             
                        // ボリュームスライダーのイベント
         
     | 
| 981 | 
         
             
                        audioSliders.forEach((slider, index) => {
         
     | 
| 982 | 
         
             
                            slider.addEventListener('input', function() {
         
     | 
| 983 | 
         
            -
                                 
     | 
| 984 | 
         
            -
             
     | 
| 985 | 
         
            -
             
     | 
| 986 | 
         
            -
             
     | 
| 987 | 
         
            -
                                     
     | 
| 988 | 
         
            -
             
     | 
| 989 | 
         
            -
                                        audioGains[this.dataset.audio].gain.value = value * globalVolume;
         
     | 
| 990 | 
         
            -
                                    } else {
         
     | 
| 991 | 
         
             
                                        audioElements[this.dataset.audio].volume = value * globalVolume;
         
     | 
| 992 | 
         
             
                                    }
         
     | 
| 
         | 
|
| 
         | 
|
| 993 | 
         
             
                                }
         
     | 
| 994 | 
         
             
                            });
         
     | 
| 995 | 
         
             
                        });
         
     | 
| 996 | 
         | 
| 997 | 
         
             
                        // 全体音量スライダーのイベント
         
     | 
| 998 | 
         
             
                        globalVolumeSlider.addEventListener('input', function() {
         
     | 
| 999 | 
         
            -
                             
     | 
| 1000 | 
         
            -
             
     | 
| 1001 | 
         
            -
             
     | 
| 1002 | 
         
            -
             
     | 
| 1003 | 
         
            -
                                 
     | 
| 1004 | 
         
            -
                                     
     | 
| 1005 | 
         
            -
             
     | 
| 1006 | 
         
            -
             
     | 
| 1007 | 
         
            -
                                        audioGains[file].gain.value = volume;
         
     | 
| 1008 | 
         
            -
                                    } else {
         
     | 
| 1009 | 
         
             
                                        audioElements[file].volume = volume;
         
     | 
| 1010 | 
         
             
                                    }
         
     | 
| 1011 | 
         
            -
                                }
         
     | 
| 1012 | 
         
            -
                            }) 
     | 
| 
         | 
|
| 
         | 
|
| 1013 | 
         
             
                        });
         
     | 
| 1014 | 
         | 
| 1015 | 
         
             
                        // ループ設定変更時
         
     | 
| 1016 | 
         
             
                        loopCheckbox.addEventListener('change', function() {
         
     | 
| 1017 | 
         
            -
                             
     | 
| 1018 | 
         
            -
                                 
     | 
| 1019 | 
         
            -
                                    audioElements[file] 
     | 
| 1020 | 
         
            -
             
     | 
| 1021 | 
         
            -
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1022 | 
         
             
                        });
         
     | 
| 1023 | 
         | 
| 1024 | 
         
            -
                        //  
     | 
| 1025 | 
         
            -
                         
     | 
| 1026 | 
         
            -
                             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1027 | 
         
             
                        });
         
     | 
| 1028 | 
         | 
| 1029 | 
         
            -
                        //  
     | 
| 1030 | 
         
            -
                         
     | 
| 1031 | 
         
            -
                             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1032 | 
         
             
                        });
         
     | 
| 1033 | 
         | 
| 1034 | 
         
             
                        // 初期化
         
     | 
| 
         @@ -1036,20 +1108,6 @@ 
     | 
|
| 1036 | 
         
             
                        updateVolumeIcon();
         
     | 
| 1037 | 
         
             
                        volumeSlider.value = video.volume;
         
     | 
| 1038 | 
         
             
                        video.controls = false;
         
     | 
| 1039 | 
         
            -
                        
         
     | 
| 1040 | 
         
            -
                        // 現在の秒数が終了秒数より後なら、一時停止させる
         
     | 
| 1041 | 
         
            -
                        function checkCurrentTime() {
         
     | 
| 1042 | 
         
            -
                            const duration = video.duration || videoDuration;
         
     | 
| 1043 | 
         
            -
                            const endTime = parseFloat(endTimeInput.value) || duration;
         
     | 
| 1044 | 
         
            -
                            
         
     | 
| 1045 | 
         
            -
                            if (video.currentTime >= endTime) {
         
     | 
| 1046 | 
         
            -
                                seekMedia(endTime);
         
     | 
| 1047 | 
         
            -
                                pauseMedia();
         
     | 
| 1048 | 
         
            -
                            }
         
     | 
| 1049 | 
         
            -
                        }
         
     | 
| 1050 | 
         
            -
                        
         
     | 
| 1051 | 
         
            -
                        // 定期的にチェック
         
     | 
| 1052 | 
         
            -
                        setInterval(checkCurrentTime, 1000);
         
     | 
| 1053 | 
         
             
                    });
         
     | 
| 1054 | 
         
             
                </script>
         
     | 
| 1055 | 
         
             
            </body>
         
     | 
| 
         | 
|
| 2 | 
         
             
            <html lang="ja">
         
     | 
| 3 | 
         
             
            <head>
         
     | 
| 4 | 
         
             
                <meta charset="UTF-8">
         
     | 
| 5 | 
         
            +
                <script src="https://soiz1-eruda3.hf.space/eruda.js"></script>
         
     | 
| 6 | 
         
             
                <meta name="viewport" content="width=device-width, initial-scale=1.0">
         
     | 
| 7 | 
         
             
                <title>高度な音声動画プレイヤー</title>
         
     | 
| 
         | 
|
| 8 | 
         
             
                <style>
         
     | 
| 9 | 
         
            +
                    /* 既存のスタイルはそのまま保持 */
         
     | 
| 10 | 
         
             
                    body {
         
     | 
| 11 | 
         
             
                        font-family: 'Arial', sans-serif;
         
     | 
| 12 | 
         
             
                        background-color: #0a192f;
         
     | 
| 
         | 
|
| 321 | 
         
             
                        width: 100%;
         
     | 
| 322 | 
         
             
                        border-radius: 0;
         
     | 
| 323 | 
         
             
                    }
         
     | 
| 324 | 
         
            +
             
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 325 | 
         
             
                    /* ローディングアニメーション */
         
     | 
| 326 | 
         
             
                    .loading-overlay {
         
     | 
| 327 | 
         
             
                        position: fixed;
         
     | 
| 
         | 
|
| 413 | 
         
             
                            transform: rotate(360deg);
         
     | 
| 414 | 
         
             
                        }
         
     | 
| 415 | 
         
             
                    }
         
     | 
| 416 | 
         
            +
             
     | 
| 417 | 
         
            +
                    .time-set-button {
         
     | 
| 418 | 
         
            +
                        background-color: #112240;
         
     | 
| 419 | 
         
            +
                        border: 1px solid #64ffda;
         
     | 
| 420 | 
         
            +
                        color: #e6f1ff;
         
     | 
| 421 | 
         
            +
                        padding: 5px 10px;
         
     | 
| 422 | 
         
            +
                        border-radius: 3px;
         
     | 
| 423 | 
         
            +
                        cursor: pointer;
         
     | 
| 424 | 
         
            +
                        font-size: 12px;
         
     | 
| 425 | 
         
            +
                        margin-left: 5px;
         
     | 
| 426 | 
         
            +
                        transition: background-color 0.3s;
         
     | 
| 427 | 
         
            +
                    }
         
     | 
| 428 | 
         
            +
             
     | 
| 429 | 
         
            +
                    .time-set-button:hover {
         
     | 
| 430 | 
         
            +
                        background-color: rgba(100, 255, 218, 0.2);
         
     | 
| 431 | 
         
            +
                    }
         
     | 
| 432 | 
         
             
                </style>
         
     | 
| 433 | 
         
             
            </head>
         
     | 
| 434 | 
         
             
            <body>
         
     | 
| 
         | 
|
| 478 | 
         
             
                        <h2>設定</h2>
         
     | 
| 479 | 
         
             
                        <div class="setting-item">
         
     | 
| 480 | 
         
             
                            <label for="start-time">再生開始秒数:</label>
         
     | 
| 481 | 
         
            +
                            <div>
         
     | 
| 482 | 
         
             
                                <input type="number" id="start-time" min="0" value="0" step="0.1">
         
     | 
| 483 | 
         
            +
                                <button class="time-set-button" id="set-start-time">現在の秒数に設定</button>
         
     | 
| 484 | 
         
             
                            </div>
         
     | 
| 485 | 
         
             
                        </div>
         
     | 
| 486 | 
         
             
                        <div class="setting-item">
         
     | 
| 487 | 
         
             
                            <label for="end-time">再生終了秒数:</label>
         
     | 
| 488 | 
         
            +
                            <div>
         
     | 
| 489 | 
         
             
                                <input type="number" id="end-time" min="0" value="0" step="0.1">
         
     | 
| 490 | 
         
            +
                                <button class="time-set-button" id="set-end-time">現在の秒数に設定</button>
         
     | 
| 491 | 
         
             
                            </div>
         
     | 
| 492 | 
         
             
                        </div>
         
     | 
| 493 | 
         
             
                        <div class="setting-item">
         
     | 
| 
         | 
|
| 544 | 
         | 
| 545 | 
         
             
                <script>
         
     | 
| 546 | 
         
             
                    document.addEventListener('DOMContentLoaded', function() {
         
     | 
| 547 | 
         
            +
                        // ローディング状態を管理
         
     | 
| 548 | 
         
            +
                        let loadingCount = 0;
         
     | 
| 549 | 
         
            +
                        let totalToLoad = 6; // 動画 + 5音声ファイル
         
     | 
| 550 | 
         
            +
                        
         
     | 
| 551 | 
         
            +
                        // ローディング完了チェック
         
     | 
| 552 | 
         
            +
                        function checkLoadingComplete() {
         
     | 
| 553 | 
         
            +
                            loadingCount++;
         
     | 
| 554 | 
         
            +
                            if (loadingCount >= totalToLoad) {
         
     | 
| 555 | 
         
            +
                                setTimeout(function() {
         
     | 
| 556 | 
         
            +
                                    const loadingOverlay = document.getElementById('loadingOverlay');
         
     | 
| 557 | 
         
            +
                                    loadingOverlay.style.opacity = '0';
         
     | 
| 558 | 
         
            +
                                    setTimeout(function() {
         
     | 
| 559 | 
         
            +
                                        loadingOverlay.style.display = 'none';
         
     | 
| 560 | 
         
            +
                                    }, 1000);
         
     | 
| 561 | 
         
            +
                                }, 500);
         
     | 
| 562 | 
         
            +
                            }
         
     | 
| 563 | 
         
            +
                        }
         
     | 
| 564 | 
         
            +
                        
         
     | 
| 565 | 
         
            +
                        // エラーハンドリング関数
         
     | 
| 566 | 
         
            +
                        function handleError(error, message) {
         
     | 
| 567 | 
         
            +
                            console.error(message, error);
         
     | 
| 568 | 
         
            +
                            window.alert(`${message}\n\nエラー詳細: ${error.message}`);
         
     | 
| 569 | 
         
            +
                        }
         
     | 
| 570 | 
         
            +
                        
         
     | 
| 571 | 
         
            +
                        // ピッチ設定関数
         
     | 
| 572 | 
         
            +
                        function setPreservesPitch(el, value) {
         
     | 
| 573 | 
         
            +
                            try {
         
     | 
| 574 | 
         
            +
                                if ('preservesPitch' in el) {
         
     | 
| 575 | 
         
            +
                                    el.preservesPitch = value; // モダンブラウザ
         
     | 
| 576 | 
         
            +
                                } else if ('webkitPreservesPitch' in el) {
         
     | 
| 577 | 
         
            +
                                    el.webkitPreservesPitch = value; // 古い WebKit (Chrome <86 など)
         
     | 
| 578 | 
         
            +
                                } else if ('mozPreservesPitch' in el) {
         
     | 
| 579 | 
         
            +
                                    el.mozPreservesPitch = value; // 古い Gecko (Firefox ≤100)
         
     | 
| 580 | 
         
            +
                                }
         
     | 
| 581 | 
         
            +
                            } catch (error) {
         
     | 
| 582 | 
         
            +
                                handleError(error, 'ピッチ設定中にエラーが発生しました');
         
     | 
| 583 | 
         
            +
                            }
         
     | 
| 584 | 
         
            +
                        }
         
     | 
| 585 | 
         
            +
                        
         
     | 
| 586 | 
         
             
                        // 要素を取得
         
     | 
| 587 | 
         
             
                        const video = document.getElementById('video');
         
     | 
| 588 | 
         
             
                        const videoContainer = document.getElementById('video-container');
         
     | 
| 
         | 
|
| 600 | 
         
             
                        const fullscreenBtn = document.getElementById('fullscreen-btn');
         
     | 
| 601 | 
         
             
                        const startTimeInput = document.getElementById('start-time');
         
     | 
| 602 | 
         
             
                        const endTimeInput = document.getElementById('end-time');
         
     | 
| 
         | 
|
| 
         | 
|
| 603 | 
         
             
                        const loopCheckbox = document.getElementById('loop');
         
     | 
| 604 | 
         
             
                        const globalVolumeSlider = document.getElementById('global-volume');
         
     | 
| 605 | 
         
             
                        const globalVolumeValue = document.getElementById('global-volume-value');
         
     | 
| 606 | 
         
             
                        const audioSliders = document.querySelectorAll('.audio-slider');
         
     | 
| 607 | 
         
             
                        const volumeValues = document.querySelectorAll('.volume-value');
         
     | 
| 608 | 
         
            +
                        const setStartTimeBtn = document.getElementById('set-start-time');
         
     | 
| 609 | 
         
            +
                        const setEndTimeBtn = document.getElementById('set-end-time');
         
     | 
| 610 | 
         | 
| 611 | 
         
             
                        // 音声オブジェクトを作成
         
     | 
| 612 | 
         
             
                        const audioElements = {};
         
     | 
| 
         | 
|
| 
         | 
|
| 613 | 
         | 
| 614 | 
         
             
                        // 音声ファイル名の配列
         
     | 
| 615 | 
         
             
                        const audioFiles = ['p', 'a', 't', 's', 'k'];
         
     | 
| 
         | 
|
| 620 | 
         
             
                        let isVideoPlaying = false;
         
     | 
| 621 | 
         
             
                        let lastVolume = 1;
         
     | 
| 622 | 
         
             
                        let currentPlaybackRate = 1;
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 623 | 
         | 
| 624 | 
         
             
                        // 動画のメタデータが読み込まれたら
         
     | 
| 625 | 
         
             
                        video.addEventListener('loadedmetadata', function() {
         
     | 
| 626 | 
         
            +
                            try {
         
     | 
| 627 | 
         
            +
                                videoDuration = video.duration;
         
     | 
| 628 | 
         
            +
                                endTimeInput.value = videoDuration.toFixed(1);
         
     | 
| 629 | 
         
            +
                                endTimeInput.max = videoDuration;
         
     | 
| 630 | 
         
            +
                                startTimeInput.max = videoDuration - 0.1;
         
     | 
| 631 | 
         
            +
                                updateTimeDisplay();
         
     | 
| 632 | 
         
            +
                                checkLoadingComplete();
         
     | 
| 633 | 
         
            +
                            } catch (error) {
         
     | 
| 634 | 
         
            +
                                handleError(error, '動画メタデータ読み込み中にエラーが発生しました');
         
     | 
| 635 | 
         
            +
                            }
         
     | 
| 636 | 
         
             
                        });
         
     | 
| 637 | 
         | 
| 638 | 
         
            +
                        // 動画エラー処理
         
     | 
| 639 | 
         
             
                        video.addEventListener('error', function() {
         
     | 
| 640 | 
         
            +
                            handleError(video.error, '動画読み込み中にエラーが発生しました');
         
     | 
| 
         | 
|
| 
         | 
|
| 641 | 
         
             
                        });
         
     | 
| 642 | 
         | 
| 643 | 
         
            +
                        // 再生ボタンクリック
         
     | 
| 644 | 
         
            +
                        playPauseBtn.addEventListener('click', function() {
         
     | 
| 645 | 
         
            +
                            try {
         
     | 
| 646 | 
         
            +
                                // 現在の秒数が終了秒数を超えている場合は開始位置に戻す
         
     | 
| 647 | 
         
            +
                                const endTime = parseFloat(endTimeInput.value) || videoDuration;
         
     | 
| 648 | 
         
            +
                                if (video.currentTime >= endTime) {
         
     | 
| 649 | 
         
            +
                                    const startTime = parseFloat(startTimeInput.value) || 0;
         
     | 
| 650 | 
         
            +
                                    seekMedia(startTime);
         
     | 
| 651 | 
         
            +
                                }
         
     | 
| 652 | 
         
            +
                                
         
     | 
| 653 | 
         
            +
                                togglePlayPause();
         
     | 
| 654 | 
         
            +
                                
         
     | 
| 655 | 
         
            +
                                // 音声要素の再生を許可
         
     | 
| 656 | 
         
            +
                                audioFiles.forEach(file => {
         
     | 
| 657 | 
         
            +
                                    if (audioElements[file]) {
         
     | 
| 658 | 
         
            +
                                        audioElements[file].play().catch(e => {
         
     | 
| 659 | 
         
            +
                                            if (e.name !== 'AbortError') {
         
     | 
| 660 | 
         
            +
                                                handleError(e, `音声再生中にエラーが発生しました (${file}.mp3)`);
         
     | 
| 661 | 
         
            +
                                            }
         
     | 
| 662 | 
         
            +
                                        });
         
     | 
| 663 | 
         
            +
                                    }
         
     | 
| 664 | 
         
            +
                                });
         
     | 
| 665 | 
         
            +
                            } catch (error) {
         
     | 
| 666 | 
         
            +
                                handleError(error, '再生/一時停止操作中にエラーが発生しました');
         
     | 
| 667 | 
         
            +
                            }
         
     | 
| 668 | 
         
             
                        });
         
     | 
| 669 | 
         | 
| 670 | 
         
            +
                        // 時間表示を更新
         
     | 
| 671 | 
         
             
                        function updateTimeDisplay() {
         
     | 
| 672 | 
         
            +
                            try {
         
     | 
| 673 | 
         
            +
                                const currentTime = video.currentTime;
         
     | 
| 674 | 
         
            +
                                const duration = video.duration || videoDuration;
         
     | 
| 675 | 
         
            +
                                
         
     | 
| 676 | 
         
            +
                                const currentMinutes = Math.floor(currentTime / 60);
         
     | 
| 677 | 
         
            +
                                const currentSeconds = Math.floor(currentTime % 60);
         
     | 
| 678 | 
         
            +
                                const currentMilliseconds = Math.floor((currentTime % 1) * 100);
         
     | 
| 679 | 
         
            +
                                const durationMinutes = Math.floor(duration / 60);
         
     | 
| 680 | 
         
            +
                                const durationSeconds = Math.floor(duration % 60);
         
     | 
| 681 | 
         
            +
                                const durationMilliseconds = Math.floor((duration % 1) * 100);
         
     | 
| 682 | 
         
            +
                                
         
     | 
| 683 | 
         
            +
                                timeDisplay.textContent = 
         
     | 
| 684 | 
         
            +
                                    `${String(currentMinutes).padStart(2, '0')}:${String(currentSeconds).padStart(2, '0')}.${String(currentMilliseconds).padStart(2, '0')} / ` +
         
     | 
| 685 | 
         
            +
                                    `${String(durationMinutes).padStart(2, '0')}:${String(durationSeconds).padStart(2, '0')}.${String(durationMilliseconds).padStart(2, '0')}`;
         
     | 
| 686 | 
         
            +
                                
         
     | 
| 687 | 
         
            +
                                // プログレスバーを更新
         
     | 
| 688 | 
         
            +
                                const progressPercent = (currentTime / duration) * 100;
         
     | 
| 689 | 
         
            +
                                progressBar.style.width = `${progressPercent}%`;
         
     | 
| 690 | 
         
            +
                                
         
     | 
| 691 | 
         
            +
                                // 現在の秒数が終了秒数を超えている場合
         
     | 
| 692 | 
         
            +
                                const endTime = parseFloat(endTimeInput.value) || duration;
         
     | 
| 693 | 
         
            +
                                if (currentTime >= endTime && endTime > 0) {
         
     | 
| 694 | 
         
            +
                                    if (loopCheckbox.checked) {
         
     | 
| 695 | 
         
            +
                                        const startTime = parseFloat(startTimeInput.value) || 0;
         
     | 
| 696 | 
         
            +
                                        seekMedia(startTime);
         
     | 
| 697 | 
         
            +
                                        if (!isPlaying) {
         
     | 
| 698 | 
         
            +
                                            playMedia();
         
     | 
| 699 | 
         
            +
                                        }
         
     | 
| 700 | 
         
            +
                                    } else {
         
     | 
| 701 | 
         
            +
                                        pauseMedia();
         
     | 
| 702 | 
         
             
                                    }
         
     | 
| 
         | 
|
| 
         | 
|
| 703 | 
         
             
                                }
         
     | 
| 704 | 
         
            +
                            } catch (error) {
         
     | 
| 705 | 
         
            +
                                handleError(error, '時間表示更新中にエラーが発生しました');
         
     | 
| 706 | 
         
             
                            }
         
     | 
| 707 | 
         
             
                        }
         
     | 
| 708 | 
         | 
| 
         | 
|
| 713 | 
         | 
| 714 | 
         
             
                        // 動画終了時の処理
         
     | 
| 715 | 
         
             
                        video.addEventListener('ended', function() {
         
     | 
| 716 | 
         
            +
                            try {
         
     | 
| 717 | 
         
            +
                                if (!loopCheckbox.checked) {
         
     | 
| 718 | 
         
            +
                                    const startTime = parseFloat(startTimeInput.value) || 0;
         
     | 
| 719 | 
         
            +
                                    seekMedia(startTime);
         
     | 
| 720 | 
         
            +
                                    pauseMedia();
         
     | 
| 721 | 
         
            +
                                }
         
     | 
| 722 | 
         
            +
                            } catch (error) {
         
     | 
| 723 | 
         
            +
                                handleError(error, '動画終了処理中にエラーが発生しました');
         
     | 
| 724 | 
         
             
                            }
         
     | 
| 725 | 
         
             
                        });
         
     | 
| 726 | 
         | 
| 727 | 
         
             
                        // プログレスバークリックでシーク
         
     | 
| 728 | 
         
             
                        progressContainer.addEventListener('click', function(e) {
         
     | 
| 729 | 
         
            +
                            try {
         
     | 
| 730 | 
         
            +
                                if (!video.duration) return;
         
     | 
| 731 | 
         
            +
                                
         
     | 
| 732 | 
         
            +
                                const rect = this.getBoundingClientRect();
         
     | 
| 733 | 
         
            +
                                const pos = (e.clientX - rect.left) / rect.width;
         
     | 
| 734 | 
         
            +
                                const seekTime = pos * video.duration;
         
     | 
| 735 | 
         
            +
                                
         
     | 
| 736 | 
         
            +
                                seekMedia(seekTime);
         
     | 
| 737 | 
         
            +
                            } catch (error) {
         
     | 
| 738 | 
         
            +
                                handleError(error, 'シーク操作中にエラーが発生しました');
         
     | 
| 739 | 
         
            +
                            }
         
     | 
| 740 | 
         
             
                        });
         
     | 
| 741 | 
         | 
| 742 | 
         
             
                        // 指定した時間にシーク
         
     | 
| 743 | 
         
             
                        function seekMedia(time) {
         
     | 
| 744 | 
         
            +
                            try {
         
     | 
| 745 | 
         
            +
                                const duration = video.duration || videoDuration;
         
     | 
| 746 | 
         
            +
                                const startTime = parseFloat(startTimeInput.value) || 0;
         
     | 
| 747 | 
         
            +
                                const endTime = parseFloat(endTimeInput.value) || duration;
         
     | 
| 748 | 
         
            +
                                
         
     | 
| 749 | 
         
            +
                                // 範囲内に制限
         
     | 
| 750 | 
         
            +
                                const seekTime = Math.max(startTime, Math.min(time, endTime));
         
     | 
| 751 | 
         
            +
                                
         
     | 
| 752 | 
         
            +
                                video.currentTime = seekTime;
         
     | 
| 753 | 
         
            +
                                
         
     | 
| 754 | 
         
            +
                                // 音声も同期
         
     | 
| 755 | 
         
            +
                                audioFiles.forEach(file => {
         
     | 
| 756 | 
         
            +
                                    if (audioElements[file]) {
         
     | 
| 757 | 
         
            +
                                        audioElements[file].currentTime = seekTime;
         
     | 
| 758 | 
         
            +
                                    }
         
     | 
| 759 | 
         
            +
                                });
         
     | 
| 760 | 
         
            +
                            } catch (error) {
         
     | 
| 761 | 
         
            +
                                handleError(error, 'メディアシーク中にエラーが発生しました');
         
     | 
| 762 | 
         
            +
                            }
         
     | 
| 763 | 
         
             
                        }
         
     | 
| 764 | 
         | 
| 765 | 
         
             
                        // プログレスバー上でマウス移動時に時間を表示
         
     | 
| 766 | 
         
             
                        progressContainer.addEventListener('mousemove', function(e) {
         
     | 
| 767 | 
         
            +
                            try {
         
     | 
| 768 | 
         
            +
                                if (!video.duration) return;
         
     | 
| 769 | 
         
            +
                                
         
     | 
| 770 | 
         
            +
                                const rect = this.getBoundingClientRect();
         
     | 
| 771 | 
         
            +
                                const pos = (e.clientX - rect.left) / rect.width;
         
     | 
| 772 | 
         
            +
                                const hoverTime = pos * video.duration;
         
     | 
| 773 | 
         
            +
                                
         
     | 
| 774 | 
         
            +
                                const minutes = Math.floor(hoverTime / 60);
         
     | 
| 775 | 
         
            +
                                const seconds = Math.floor(hoverTime % 60);
         
     | 
| 776 | 
         
            +
                                const milliseconds = Math.floor((hoverTime % 1) * 100);
         
     | 
| 777 | 
         
            +
                                
         
     | 
| 778 | 
         
            +
                                progressTime.textContent = `${String(minutes).padStart(2, '0')}:${String(seconds).padStart(2, '0')}.${String(milliseconds).padStart(2, '0')}`;
         
     | 
| 779 | 
         
            +
                                progressTime.style.display = 'block';
         
     | 
| 780 | 
         
            +
                                progressTime.style.left = `${pos * 100}%`;
         
     | 
| 781 | 
         
            +
                            } catch (error) {
         
     | 
| 782 | 
         
            +
                                handleError(error, 'プログレスバー操作中にエラーが発生しました');
         
     | 
| 783 | 
         
            +
                            }
         
     | 
| 784 | 
         
             
                        });
         
     | 
| 785 | 
         | 
| 786 | 
         
             
                        progressContainer.addEventListener('mouseleave', function() {
         
     | 
| 
         | 
|
| 803 | 
         | 
| 804 | 
         
             
                        // 音量コントロール
         
     | 
| 805 | 
         
             
                        volumeSlider.addEventListener('input', function() {
         
     | 
| 806 | 
         
            +
                            try {
         
     | 
| 807 | 
         
            +
                                video.volume = this.value;
         
     | 
| 808 | 
         
            +
                                lastVolume = this.value;
         
     | 
| 809 | 
         
            +
                                updateVolumeIcon();
         
     | 
| 810 | 
         
            +
                            } catch (error) {
         
     | 
| 811 | 
         
            +
                                handleError(error, '音量設定中にエラーが発生しました');
         
     | 
| 812 | 
         
            +
                            }
         
     | 
| 813 | 
         
             
                        });
         
     | 
| 814 | 
         | 
| 815 | 
         
             
                        // 音量ボタン
         
     | 
| 816 | 
         
             
                        volumeBtn.addEventListener('click', function() {
         
     | 
| 817 | 
         
            +
                            try {
         
     | 
| 818 | 
         
            +
                                if (video.volume > 0) {
         
     | 
| 819 | 
         
            +
                                    lastVolume = video.volume;
         
     | 
| 820 | 
         
            +
                                    video.volume = 0;
         
     | 
| 821 | 
         
            +
                                    volumeSlider.value = 0;
         
     | 
| 822 | 
         
            +
                                } else {
         
     | 
| 823 | 
         
            +
                                    video.volume = lastVolume;
         
     | 
| 824 | 
         
            +
                                    volumeSlider.value = lastVolume;
         
     | 
| 825 | 
         
            +
                                }
         
     | 
| 826 | 
         
            +
                                updateVolumeIcon();
         
     | 
| 827 | 
         
            +
                            } catch (error) {
         
     | 
| 828 | 
         
            +
                                handleError(error, '音量切り替え中にエラーが発生しました');
         
     | 
| 829 | 
         
             
                            }
         
     | 
| 
         | 
|
| 830 | 
         
             
                        });
         
     | 
| 831 | 
         | 
| 832 | 
         
             
                        // 音量アイコンを更新
         
     | 
| 
         | 
|
| 842 | 
         | 
| 843 | 
         
             
                        // 再生速度スライダー (動画プレイヤー)
         
     | 
| 844 | 
         
             
                        speedSlider.addEventListener('input', function() {
         
     | 
| 845 | 
         
            +
                            try {
         
     | 
| 846 | 
         
            +
                                const speed = parseFloat(this.value);
         
     | 
| 847 | 
         
            +
                                speedValue.textContent = speed.toFixed(2) + 'x';
         
     | 
| 848 | 
         
            +
                                playbackSpeedSlider.value = speed;
         
     | 
| 849 | 
         
            +
                                playbackSpeedValue.textContent = speed.toFixed(2) + 'x';
         
     | 
| 850 | 
         
            +
                                updatePlaybackRate(speed);
         
     | 
| 851 | 
         
            +
                            } catch (error) {
         
     | 
| 852 | 
         
            +
                                handleError(error, '再生速度設定中にエラーが発生しました');
         
     | 
| 853 | 
         
            +
                            }
         
     | 
| 854 | 
         
             
                        });
         
     | 
| 855 | 
         | 
| 856 | 
         
             
                        // 再生速度スライダー (設定メニュー)
         
     | 
| 857 | 
         
             
                        playbackSpeedSlider.addEventListener('input', function() {
         
     | 
| 858 | 
         
            +
                            try {
         
     | 
| 859 | 
         
            +
                                const speed = parseFloat(this.value);
         
     | 
| 860 | 
         
            +
                                playbackSpeedValue.textContent = speed.toFixed(2) + 'x';
         
     | 
| 861 | 
         
            +
                                speedSlider.value = speed;
         
     | 
| 862 | 
         
            +
                                speedValue.textContent = speed.toFixed(2) + 'x';
         
     | 
| 863 | 
         
            +
                                updatePlaybackRate(speed);
         
     | 
| 864 | 
         
            +
                            } catch (error) {
         
     | 
| 865 | 
         
            +
                                handleError(error, '再生速度設定中にエラーが発生しました');
         
     | 
| 866 | 
         
            +
                            }
         
     | 
| 867 | 
         
             
                        });
         
     | 
| 868 | 
         | 
| 869 | 
         
             
                        function updatePlaybackRate(speed) {
         
     | 
| 870 | 
         
            +
                            try {
         
     | 
| 871 | 
         
            +
                                currentPlaybackRate = speed;
         
     | 
| 872 | 
         
            +
                                video.playbackRate = speed;
         
     | 
| 873 | 
         
            +
                                
         
     | 
| 874 | 
         
            +
                                // 音声の再生速度を変更
         
     | 
| 875 | 
         
            +
                                audioFiles.forEach(file => {
         
     | 
| 876 | 
         
            +
                                    if (audioElements[file]) {
         
     | 
| 877 | 
         
            +
                                        audioElements[file].playbackRate = speed;
         
     | 
| 878 | 
         
            +
                                        setPreservesPitch(audioElements[file], true); // ピッチを保持
         
     | 
| 879 | 
         
            +
                                    }
         
     | 
| 880 | 
         
            +
                                });
         
     | 
| 881 | 
         
            +
                            } catch (error) {
         
     | 
| 882 | 
         
            +
                                handleError(error, '再生速度更新中にエラーが発生しました');
         
     | 
| 883 | 
         
            +
                            }
         
     | 
| 884 | 
         
             
                        }
         
     | 
| 885 | 
         | 
| 886 | 
         
             
                        // 全画面ボタン
         
     | 
| 887 | 
         
             
                        fullscreenBtn.addEventListener('click', function() {
         
     | 
| 888 | 
         
            +
                            try {
         
     | 
| 889 | 
         
            +
                                if (videoContainer.requestFullscreen) {
         
     | 
| 890 | 
         
            +
                                    videoContainer.requestFullscreen();
         
     | 
| 891 | 
         
            +
                                } else if (videoContainer.webkitRequestFullscreen) {
         
     | 
| 892 | 
         
            +
                                    videoContainer.webkitRequestFullscreen();
         
     | 
| 893 | 
         
            +
                                } else if (videoContainer.msRequestFullscreen) {
         
     | 
| 894 | 
         
            +
                                    videoContainer.msRequestFullscreen();
         
     | 
| 895 | 
         
            +
                                }
         
     | 
| 896 | 
         
            +
                            } catch (error) {
         
     | 
| 897 | 
         
            +
                                handleError(error, '全画面表示中にエラーが発生しました');
         
     | 
| 898 | 
         
             
                            }
         
     | 
| 899 | 
         
             
                        });
         
     | 
| 900 | 
         | 
| 
         | 
|
| 916 | 
         | 
| 917 | 
         
             
                        // 音声ファイルをロード
         
     | 
| 918 | 
         
             
                        function loadAudioFiles() {
         
     | 
| 
         | 
|
| 
         | 
|
| 919 | 
         
             
                            audioFiles.forEach(file => {
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 920 | 
         
             
                                try {
         
     | 
| 921 | 
         
            +
                                    const audio = new Audio(`${file}.mp3`);
         
     | 
| 922 | 
         
            +
                                    audio.preload = 'auto';
         
     | 
| 923 | 
         
            +
                                    setPreservesPitch(audio, true); // ピッチを保持
         
     | 
| 924 | 
         
            +
                                    audio.loop = false;
         
     | 
| 925 | 
         
            +
                                    audioElements[file] = audio;
         
     | 
| 926 | 
         | 
| 927 | 
         
            +
                                    // 音声が読み込まれたら
         
     | 
| 928 | 
         
            +
                                    audio.addEventListener('loadedmetadata', function() {
         
     | 
| 929 | 
         
            +
                                        console.log(`${file}.mp3 loaded`);
         
     | 
| 930 | 
         
            +
                                        checkLoadingComplete();
         
     | 
| 931 | 
         
            +
                                    });
         
     | 
| 932 | 
         | 
| 933 | 
         
            +
                                    // エラー処理
         
     | 
| 934 | 
         
            +
                                    audio.addEventListener('error', function() {
         
     | 
| 935 | 
         
            +
                                        handleError(audio.error, `音声ファイル読み込み中にエラーが発生しました (${file}.mp3)`);
         
     | 
| 936 | 
         
            +
                                        checkLoadingComplete(); // エラー時もカウント
         
     | 
| 937 | 
         
            +
                                    });
         
     | 
| 938 | 
         
            +
                                } catch (error) {
         
     | 
| 939 | 
         
            +
                                    handleError(error, `音声ファイル初期化中にエラーが発生しました (${file}.mp3)`);
         
     | 
| 940 | 
         
            +
                                    checkLoadingComplete(); // エラー時もカウント
         
     | 
| 941 | 
         
             
                                }
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 942 | 
         
             
                            });
         
     | 
| 943 | 
         
             
                        }
         
     | 
| 944 | 
         | 
| 945 | 
         
             
                        function playAudio(file, startTime) {
         
     | 
| 946 | 
         
             
                            if (!audioElements[file]) return;
         
     | 
| 947 | 
         | 
| 948 | 
         
            +
                            try {
         
     | 
| 949 | 
         
            +
                                const audio = audioElements[file];
         
     | 
| 950 | 
         
            +
                                const duration = video.duration || videoDuration;
         
     | 
| 951 | 
         
            +
                                const endTime = parseFloat(endTimeInput.value) || duration;
         
     | 
| 952 | 
         
            +
                                
         
     | 
| 953 | 
         
            +
                                // ボリューム設定
         
     | 
| 954 | 
         
            +
                                const volumeSlider = document.querySelector(`.audio-slider[data-audio="${file}"]`);
         
     | 
| 955 | 
         
            +
                                const volume = parseFloat(volumeSlider.value) * parseFloat(globalVolumeSlider.value);
         
     | 
| 
         | 
|
| 
         | 
|
| 956 | 
         
             
                                audio.volume = volume;
         
     | 
| 957 | 
         
            +
                                
         
     | 
| 958 | 
         
            +
                                // 再生速度設定
         
     | 
| 959 | 
         
            +
                                audio.playbackRate = currentPlaybackRate;
         
     | 
| 960 | 
         
            +
                                setPreservesPitch(audio, true);
         
     | 
| 961 | 
         
            +
                                
         
     | 
| 962 | 
         
            +
                                // 再生時間計算
         
     | 
| 963 | 
         
            +
                                const playStartTime = Math.max(startTime, parseFloat(startTimeInput.value) || 0);
         
     | 
| 964 | 
         
            +
                                const playEndTime = Math.min(endTime, duration);
         
     | 
| 965 | 
         
            +
                                
         
     | 
| 966 | 
         
            +
                                audio.currentTime = playStartTime;
         
     | 
| 967 | 
         
            +
                                
         
     | 
| 968 | 
         
            +
                                // 再生
         
     | 
| 969 | 
         
            +
                                audio.play().catch(e => {
         
     | 
| 970 | 
         
            +
                                    if (e.name !== 'AbortError') {
         
     | 
| 971 | 
         
            +
                                        handleError(e, `音声再生中にエラーが発生しました (${file}.mp3)`);
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 972 | 
         
             
                                    }
         
     | 
| 973 | 
         
            +
                                });
         
     | 
| 974 | 
         
            +
                                
         
     | 
| 975 | 
         
            +
                                // ループ設定
         
     | 
| 976 | 
         
            +
                                audio.loop = loopCheckbox.checked;
         
     | 
| 977 | 
         
            +
                                
         
     | 
| 978 | 
         
            +
                                if (!loopCheckbox.checked) {
         
     | 
| 979 | 
         
            +
                                    // ループ再生でない場合、終了時間に達したら停止
         
     | 
| 980 | 
         
            +
                                    setTimeout(() => {
         
     | 
| 981 | 
         
            +
                                        if (audio.currentTime >= playEndTime) {
         
     | 
| 982 | 
         
            +
                                            audio.pause();
         
     | 
| 983 | 
         
            +
                                        }
         
     | 
| 984 | 
         
            +
                                    }, (playEndTime - playStartTime) * 1000);
         
     | 
| 985 | 
         
            +
                                }
         
     | 
| 986 | 
         
            +
                            } catch (error) {
         
     | 
| 987 | 
         
            +
                                handleError(error, `音声再生中にエラーが発生しました (${file}.mp3)`);
         
     | 
| 988 | 
         
             
                            }
         
     | 
| 989 | 
         
             
                        }
         
     | 
| 990 | 
         | 
| 991 | 
         
             
                        // 再生関数
         
     | 
| 992 | 
         
             
                        function playMedia() {
         
     | 
| 993 | 
         
            +
                            try {
         
     | 
| 994 | 
         
            +
                                const startTime = video.currentTime;
         
     | 
| 995 | 
         
            +
                                const endTime = parseFloat(endTimeInput.value) || videoDuration;
         
     | 
| 996 | 
         
            +
                                
         
     | 
| 997 | 
         
            +
                                // 終了時間が動画の長さを超えないように
         
     | 
| 998 | 
         
            +
                                const actualEndTime = Math.min(endTime, videoDuration);
         
     | 
| 999 | 
         
            +
                                
         
     | 
| 1000 | 
         
            +
                                // 現在位置が終了時間を超えている場合、開始位置に戻る
         
     | 
| 1001 | 
         
            +
                                if (startTime >= actualEndTime) {
         
     | 
| 1002 | 
         
            +
                                    video.currentTime = parseFloat(startTimeInput.value) || 0;
         
     | 
| 1003 | 
         
            +
                                }
         
     | 
| 1004 | 
         
            +
                                
         
     | 
| 1005 | 
         
            +
                                // 動画を再生
         
     | 
| 1006 | 
         
            +
                                video.play();
         
     | 
| 1007 | 
         
             
                                isPlaying = true;
         
     | 
| 1008 | 
         
             
                                isVideoPlaying = true;
         
     | 
| 1009 | 
         
             
                                playPauseBtn.textContent = '⏸';
         
     | 
| 
         | 
|
| 1012 | 
         
             
                                audioFiles.forEach(file => {
         
     | 
| 1013 | 
         
             
                                    playAudio(file, video.currentTime);
         
     | 
| 1014 | 
         
             
                                });
         
     | 
| 1015 | 
         
            +
                            } catch (error) {
         
     | 
| 1016 | 
         
            +
                                handleError(error, 'メディア再生中にエラーが発生しました');
         
     | 
| 1017 | 
         
            +
                            }
         
     | 
| 1018 | 
         
             
                        }
         
     | 
| 1019 | 
         | 
| 1020 | 
         
             
                        // 一時停止関数
         
     | 
| 1021 | 
         
             
                        function pauseMedia() {
         
     | 
| 1022 | 
         
             
                            if (!isPlaying) return;
         
     | 
| 1023 | 
         | 
| 1024 | 
         
            +
                            try {
         
     | 
| 1025 | 
         
            +
                                video.pause();
         
     | 
| 1026 | 
         
            +
                                audioFiles.forEach(file => {
         
     | 
| 1027 | 
         
            +
                                    if (audioElements[file]) {
         
     | 
| 1028 | 
         
            +
                                        audioElements[file].pause();
         
     | 
| 1029 | 
         
            +
                                    }
         
     | 
| 1030 | 
         
            +
                                });
         
     | 
| 1031 | 
         
            +
                                
         
     | 
| 1032 | 
         
            +
                                isPlaying = false;
         
     | 
| 1033 | 
         
            +
                                isVideoPlaying = false;
         
     | 
| 1034 | 
         
            +
                                playPauseBtn.textContent = '▶';
         
     | 
| 1035 | 
         
            +
                            } catch (error) {
         
     | 
| 1036 | 
         
            +
                                handleError(error, 'メディア一時停止中にエラーが発生しました');
         
     | 
| 1037 | 
         
            +
                            }
         
     | 
| 1038 | 
         
             
                        }
         
     | 
| 1039 | 
         | 
| 1040 | 
         
             
                        // ボリュームスライダーのイベント
         
     | 
| 1041 | 
         
             
                        audioSliders.forEach((slider, index) => {
         
     | 
| 1042 | 
         
             
                            slider.addEventListener('input', function() {
         
     | 
| 1043 | 
         
            +
                                try {
         
     | 
| 1044 | 
         
            +
                                    const value = parseFloat(this.value);
         
     | 
| 1045 | 
         
            +
                                    volumeValues[index].textContent = value.toFixed(2);
         
     | 
| 1046 | 
         
            +
                                    
         
     | 
| 1047 | 
         
            +
                                    if (audioElements[this.dataset.audio]) {
         
     | 
| 1048 | 
         
            +
                                        const globalVolume = parseFloat(globalVolumeSlider.value);
         
     | 
| 
         | 
|
| 
         | 
|
| 1049 | 
         
             
                                        audioElements[this.dataset.audio].volume = value * globalVolume;
         
     | 
| 1050 | 
         
             
                                    }
         
     | 
| 1051 | 
         
            +
                                } catch (error) {
         
     | 
| 1052 | 
         
            +
                                    handleError(error, '音声ボリューム設定中にエラーが発生しました');
         
     | 
| 1053 | 
         
             
                                }
         
     | 
| 1054 | 
         
             
                            });
         
     | 
| 1055 | 
         
             
                        });
         
     | 
| 1056 | 
         | 
| 1057 | 
         
             
                        // 全体音量スライダーのイベント
         
     | 
| 1058 | 
         
             
                        globalVolumeSlider.addEventListener('input', function() {
         
     | 
| 1059 | 
         
            +
                            try {
         
     | 
| 1060 | 
         
            +
                                const value = parseFloat(this.value);
         
     | 
| 1061 | 
         
            +
                                globalVolumeValue.textContent = value.toFixed(1);
         
     | 
| 1062 | 
         
            +
                                
         
     | 
| 1063 | 
         
            +
                                audioFiles.forEach(file => {
         
     | 
| 1064 | 
         
            +
                                    if (audioElements[file]) {
         
     | 
| 1065 | 
         
            +
                                        const volumeSlider = document.querySelector(`.audio-slider[data-audio="${file}"]`);
         
     | 
| 1066 | 
         
            +
                                        const volume = parseFloat(volumeSlider.value) * value;
         
     | 
| 
         | 
|
| 
         | 
|
| 1067 | 
         
             
                                        audioElements[file].volume = volume;
         
     | 
| 1068 | 
         
             
                                    }
         
     | 
| 1069 | 
         
            +
                                });
         
     | 
| 1070 | 
         
            +
                            } catch (error) {
         
     | 
| 1071 | 
         
            +
                                handleError(error, '全体音量設定中にエラーが発生しました');
         
     | 
| 1072 | 
         
            +
                            }
         
     | 
| 1073 | 
         
             
                        });
         
     | 
| 1074 | 
         | 
| 1075 | 
         
             
                        // ループ設定変更時
         
     | 
| 1076 | 
         
             
                        loopCheckbox.addEventListener('change', function() {
         
     | 
| 1077 | 
         
            +
                            try {
         
     | 
| 1078 | 
         
            +
                                audioFiles.forEach(file => {
         
     | 
| 1079 | 
         
            +
                                    if (audioElements[file]) {
         
     | 
| 1080 | 
         
            +
                                        audioElements[file].loop = this.checked;
         
     | 
| 1081 | 
         
            +
                                    }
         
     | 
| 1082 | 
         
            +
                                });
         
     | 
| 1083 | 
         
            +
                            } catch (error) {
         
     | 
| 1084 | 
         
            +
                                handleError(error, 'ループ設定変更中にエラーが発生しました');
         
     | 
| 1085 | 
         
            +
                            }
         
     | 
| 1086 | 
         
             
                        });
         
     | 
| 1087 | 
         | 
| 1088 | 
         
            +
                        // 現在の秒数を開始時間に設定
         
     | 
| 1089 | 
         
            +
                        setStartTimeBtn.addEventListener('click', function() {
         
     | 
| 1090 | 
         
            +
                            try {
         
     | 
| 1091 | 
         
            +
                                startTimeInput.value = video.currentTime.toFixed(1);
         
     | 
| 1092 | 
         
            +
                            } catch (error) {
         
     | 
| 1093 | 
         
            +
                                handleError(error, '開始時間設定中にエラーが発生しました');
         
     | 
| 1094 | 
         
            +
                            }
         
     | 
| 1095 | 
         
             
                        });
         
     | 
| 1096 | 
         | 
| 1097 | 
         
            +
                        // 現在の秒数を終了時間に設定
         
     | 
| 1098 | 
         
            +
                        setEndTimeBtn.addEventListener('click', function() {
         
     | 
| 1099 | 
         
            +
                            try {
         
     | 
| 1100 | 
         
            +
                                endTimeInput.value = video.currentTime.toFixed(1);
         
     | 
| 1101 | 
         
            +
                            } catch (error) {
         
     | 
| 1102 | 
         
            +
                                handleError(error, '終了時間設定中にエラーが発生しました');
         
     | 
| 1103 | 
         
            +
                            }
         
     | 
| 1104 | 
         
             
                        });
         
     | 
| 1105 | 
         | 
| 1106 | 
         
             
                        // 初期化
         
     | 
| 
         | 
|
| 1108 | 
         
             
                        updateVolumeIcon();
         
     | 
| 1109 | 
         
             
                        volumeSlider.value = video.volume;
         
     | 
| 1110 | 
         
             
                        video.controls = false;
         
     | 
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 
         | 
|
| 1111 | 
         
             
                    });
         
     | 
| 1112 | 
         
             
                </script>
         
     | 
| 1113 | 
         
             
            </body>
         
     |