最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

JavaScript實(shí)現(xiàn)獲取指定音視頻流鏈接的時(shí)長(zhǎng)

 更新時(shí)間:2026年02月06日 09:18:12   作者:博客zhu虎康  
這篇文章主要為大家詳細(xì)介紹了JavaScript實(shí)現(xiàn)獲取指定音頻或視頻流鏈接的時(shí)長(zhǎng),文中的示例代碼講解詳細(xì),感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

需求

在上傳音視頻后,后端會(huì)返回一個(gè)視頻地址,如何根據(jù)該地址獲取音視頻的時(shí)長(zhǎng)

思路分析

視頻

利用瀏覽器的 HTMLVideoElement 對(duì)象加載視頻的元數(shù)據(jù)(無(wú)需下載完整視頻),從而獲取精準(zhǔn)的時(shí)長(zhǎng)(秒數(shù))

1.思路

/**
 * 獲取遠(yuǎn)程視頻的時(shí)長(zhǎng)(單位:秒)
 * @param {string} videoUrl - 視頻鏈接
 * @returns {Promise<number>} 視頻時(shí)長(zhǎng)(秒,保留兩位小數(shù))
 */
async function getVideoDurationInSeconds(videoUrl) {
  return new Promise((resolve, reject) => {
    // 創(chuàng)建 video 元素(無(wú)需添加到 DOM)
    const video = document.createElement('video');
    
    // 關(guān)鍵:設(shè)置跨域配置(若視頻服務(wù)器允許跨域,需添加此屬性)
    video.crossOrigin = 'anonymous'; // 或 'use-credentials'(根據(jù)服務(wù)器配置)

    // 監(jiān)聽(tīng)元數(shù)據(jù)加載完成事件(此時(shí)已能獲取時(shí)長(zhǎng))
    video.onloadedmetadata = () => {
      // video.duration 是視頻總時(shí)長(zhǎng)(單位:秒,可能是小數(shù),如 120.5 秒)
      const duration = Number(video.duration.toFixed(2)); // 保留兩位小數(shù)
      // 釋放資源
      video.removeAttribute('src');
      video.load();
      URL.revokeObjectURL(video.src); // 清理臨時(shí) URL
      resolve(duration);
    };

    // 監(jiān)聽(tīng)錯(cuò)誤事件(如跨域、地址無(wú)效、格式不支持)
    video.onerror = (err) => {
      reject(new Error(`獲取視頻時(shí)長(zhǎng)失敗:${video.error?.code || '未知錯(cuò)誤'}`));
      // 釋放資源
      video.removeAttribute('src');
      video.load();
      URL.revokeObjectURL(video.src);
    };

    // 監(jiān)聽(tīng)加載超時(shí)(可選,防止長(zhǎng)時(shí)間無(wú)響應(yīng))
    setTimeout(() => {
      reject(new Error('獲取視頻時(shí)長(zhǎng)超時(shí)'));
    }, 10000); // 10秒超時(shí)

    // 設(shè)置視頻地址,觸發(fā)元數(shù)據(jù)加載
    video.src = videoUrl;
    // 強(qiáng)制加載元數(shù)據(jù)(部分瀏覽器需要)
    video.load();
  });
}

// 調(diào)用示例
const videoUrl = "https://www.dkifly.com/ifly-api/admin-api/infra/file/29/get/20251212/bbb4cc64216dac72124369fd35b7ae00_1765533865580.mp4";
getVideoDurationInSeconds(videoUrl)
  .then(duration => {
    console.log('視頻時(shí)長(zhǎng)(秒):', duration); // 輸出示例:125.36
  })
  .catch(error => {
    console.error(error.message);
  });

2.總代碼

<template>
  <div>
    <el-button @click="fetchVideoDuration">獲取視頻時(shí)長(zhǎng)</el-button>
    <div v-if="duration !== null">視頻時(shí)長(zhǎng)(秒):{{ duration }}</div>
    <div v-if="errorMsg">錯(cuò)誤:{{ errorMsg }}</div>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';

const duration = ref<number | null>(null);
const errorMsg = ref('');

/**
 * 獲取遠(yuǎn)程視頻的時(shí)長(zhǎng)(單位:秒)
 * @param {string} videoUrl - 視頻鏈接
 * @returns {Promise<number>} 視頻時(shí)長(zhǎng)(秒)
 */
const getVideoDurationInSeconds = async (videoUrl: string): Promise<number> => {
  return new Promise((resolve, reject) => {
    const video = document.createElement('video');
    video.crossOrigin = 'anonymous';

    video.onloadedmetadata = () => {
      const duration = Number(video.duration.toFixed(2));
      video.removeAttribute('src');
      video.load();
      URL.revokeObjectURL(video.src);
      resolve(duration);
    };

    video.onerror = () => {
      reject(new Error('視頻加載失敗,可能是跨域或鏈接無(wú)效'));
      video.removeAttribute('src');
      video.load();
      URL.revokeObjectURL(video.src);
    };

    // 10秒超時(shí)
    setTimeout(() => {
      reject(new Error('獲取時(shí)長(zhǎng)超時(shí),請(qǐng)檢查視頻鏈接'));
    }, 10000);

    video.src = videoUrl;
    video.load();
  });
};

// 觸發(fā)獲取時(shí)長(zhǎng)
const fetchVideoDuration = async () => {
  const videoUrl = "https://www.dkifly.com/ifly-api/admin-api/infra/file/29/get/20251212/bbb4cc64216dac72124369fd35b7ae00_1765533865580.mp4";
  try {
    duration.value = await getVideoDurationInSeconds(videoUrl);
    errorMsg.value = '';
  } catch (err) {
    duration.value = null;
    errorMsg.value = (err as Error).message;
  }
};
</script>

音頻

方式一

核心邏輯和視頻是一樣的

1.思路

/**
 * 獲取遠(yuǎn)程音頻/視頻的時(shí)長(zhǎng)(單位:秒,適配 MP3/MP4 等格式)
 * @param {string} mediaUrl - 音頻/視頻鏈接(MP3/MP4 均可)
 * @returns {Promise<number>} 時(shí)長(zhǎng)(秒,保留兩位小數(shù))
 */
async function getMediaDurationInSeconds(mediaUrl) {
  return new Promise((resolve, reject) => {
    // 針對(duì)音頻,使用 audio 元素(語(yǔ)義化,性能更優(yōu))
    const media = document.createElement('audio'); // 替換為 audio 元素
    // 跨域配置(關(guān)鍵:需服務(wù)器支持 CORS)
    media.crossOrigin = 'anonymous';

    // 元數(shù)據(jù)加載完成:獲取時(shí)長(zhǎng)
    media.onloadedmetadata = () => {
      if (isNaN(media.duration)) {
        reject(new Error('無(wú)法獲取媒體時(shí)長(zhǎng),可能是文件格式不支持或元數(shù)據(jù)缺失'));
        return;
      }
      // 轉(zhuǎn)換為秒(保留兩位小數(shù))
      const duration = Number(media.duration.toFixed(2));
      // 釋放資源,避免內(nèi)存泄漏
      media.removeAttribute('src');
      media.load();
      URL.revokeObjectURL(media.src);
      resolve(duration);
    };

    // 錯(cuò)誤處理(跨域、鏈接無(wú)效、格式不支持等)
    media.onerror = (err) => {
      reject(new Error(`獲取時(shí)長(zhǎng)失敗:${media.error?.message || '未知錯(cuò)誤'}`));
      media.removeAttribute('src');
      media.load();
      URL.revokeObjectURL(media.src);
    };

    // 超時(shí)處理(防止長(zhǎng)時(shí)間無(wú)響應(yīng))
    setTimeout(() => {
      reject(new Error('獲取時(shí)長(zhǎng)超時(shí)(10秒)'));
    }, 10000);

    // 設(shè)置媒體地址,觸發(fā)加載
    media.src = mediaUrl;
    media.load();
  });
}

// 調(diào)用示例:音頻鏈接(MP3)
const audioUrl = "https://www.dkifly.com/ifly-api/admin-api/infra/file/29/get/20251212/bbb4cc64216dac72124369fd35b7ae00_1765533865580.mp3";
getMediaDurationInSeconds(audioUrl)
  .then(duration => {
    console.log('音頻時(shí)長(zhǎng)(秒):', duration); // 輸出示例:120.56
  })
  .catch(error => {
    console.error(error.message);
  });

// 調(diào)用示例:視頻鏈接(MP4)(該函數(shù)也兼容視頻)
const videoUrl = "https://www.dkifly.com/ifly-api/admin-api/infra/file/29/get/20251212/bbb4cc64216dac72124369fd35b7ae00_1765533865580.mp4";
getMediaDurationInSeconds(videoUrl)
  .then(duration => {
    console.log('視頻時(shí)長(zhǎng)(秒):', duration);
  })
  .catch(error => {
    console.error(error.message);
  });

2.總代碼

<template>
  <div>
    <el-button @click="fetchAudioDuration">獲取音頻時(shí)長(zhǎng)</el-button>
    <div v-if="duration !== null">音頻時(shí)長(zhǎng)(秒):{{ duration }}</div>
    <div v-if="errorMsg" style="color: red;">{{ errorMsg }}</div>
  </div>
</template>

<script lang="ts" setup>
import { ref } from 'vue';

const duration = ref<number | null>(null);
const errorMsg = ref('');

/**
 * 通用方法:獲取音頻/視頻時(shí)長(zhǎng)(秒)
 */
const getMediaDurationInSeconds = async (mediaUrl: string): Promise<number> => {
  return new Promise((resolve, reject) => {
    const media = document.createElement('audio');
    media.crossOrigin = 'anonymous';

    media.onloadedmetadata = () => {
      if (isNaN(media.duration)) {
        reject(new Error('媒體文件元數(shù)據(jù)缺失,無(wú)法獲取時(shí)長(zhǎng)'));
        return;
      }
      const duration = Number(media.duration.toFixed(2));
      media.removeAttribute('src');
      media.load();
      URL.revokeObjectURL(media.src);
      resolve(duration);
    };

    media.onerror = () => {
      reject(new Error('加載失?。嚎赡苁强缬颉㈡溄訜o(wú)效或格式不支持'));
      media.removeAttribute('src');
      media.load();
      URL.revokeObjectURL(media.src);
    };

    setTimeout(() => {
      reject(new Error('獲取時(shí)長(zhǎng)超時(shí),請(qǐng)檢查鏈接'));
    }, 10000);

    media.src = mediaUrl;
    media.load();
  });
};

// 觸發(fā)獲取音頻時(shí)長(zhǎng)
const fetchAudioDuration = async () => {
  const audioUrl = "https://www.dkifly.com/ifly-api/admin-api/infra/file/29/get/20251212/bbb4cc64216dac72124369fd35b7ae00_1765533865580.mp3";
  try {
    duration.value = await getMediaDurationInSeconds(audioUrl);
    errorMsg.value = '';
  } catch (err) {
    duration.value = null;
    errorMsg.value = (err as Error).message;
  }
};
</script>

方式二

async function getAudioDuration(url) {
  return new Promise((resolve, reject) => {
    const audio = new Audio(url)

    audio.addEventListener('loadedmetadata', () => {
      console.log(audio.duration)
      // 返回四舍五入后的秒數(shù)
      resolve(Math.round(audio.duration))
    })

    audio.addEventListener('error', (e) => {
      reject(new Error('Failed to load audio file'))
    })
  })
}
// 使用
try {
   const duration = await getAudioDuration('https://example.com/audio.mp3');
   console.log(`音頻時(shí)長(zhǎng): ${duration} 秒`)
 } catch (error) {
   console.error('獲取音頻時(shí)長(zhǎng)失敗:', error.message)
}

獲取時(shí)分秒

async function getFormattedDuration(url) {
  const duration = await getAudioDuration(url);
  const minutes = Math.floor(duration / 60);
  const seconds = duration % 60;
  return `${minutes}:${seconds.toString().padStart(2, '0')}`;
}

// 使用示例
const formattedDuration = await getFormattedDuration('https://example.com/audio.mp3');
console.log(`音頻時(shí)長(zhǎng): ${formattedDuration}`); // 輸出格式如: "3:45"

到此這篇關(guān)于JavaScript實(shí)現(xiàn)獲取指定音視頻流鏈接的時(shí)長(zhǎng)的文章就介紹到這了,更多相關(guān)JavaScript獲取音視頻時(shí)長(zhǎng)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

最新評(píng)論

永泰县| 台江县| 拜城县| 石狮市| 长泰县| 伊通| 扶沟县| 定州市| 玛纳斯县| 谷城县| 井陉县| 兖州市| 乌鲁木齐县| 天门市| 武安市| 连江县| 北流市| 新密市| 海丰县| 浑源县| 盖州市| 福建省| 安丘市| 建始县| 苍梧县| 保山市| 延长县| 左贡县| 工布江达县| 馆陶县| 同仁县| 山阳县| 南木林县| 云林县| 孟州市| 武汉市| 曲靖市| 屏山县| 永仁县| 宁明县| 沂水县|