提交 26f6d137 编写于 作者: Q qinliwen

<新增camera&audio&player Validator用例>

Signed-off-by: Nqinliwen <qinliwen3@huawei.com>
上级 c22cb058
import audio from '@ohos.multimedia.audio'
import deviceInfo from '@ohos.deviceInfo'
import fileio from '@ohos.fileio'
import image from '@ohos.multimedia.image'
import media from '@ohos.multimedia.media'
import mediaLibrary from '@ohos.multimedia.mediaLibrary'
import Logger from '../model/Logger'
import MediaUtils from '../model/MediaUtils'
// @ts-ignore
import fs from '@ohos.file.fs'
import mediaPlay from '../model/mediaPlay'
class AudioCapturer {
private tag: string = 'qlw AudioCapture'
private static instance: AudioCapturer = new AudioCapturer()
private audioCapturer: audio.AudioCapturer = undefined
private fd: number = undefined
private isRecorder: boolean = false
private file: fs.File = undefined
async createAudioCapturer() {
let AudioStreamInfo = {
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
channels: audio.AudioChannel.CHANNEL_2,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
}
let AudioCapturerInfo = {
source: audio.SourceType.SOURCE_TYPE_MIC,
capturerFlags: 0
}
let AudioCapturerOptions = {
streamInfo: AudioStreamInfo,
capturerInfo: AudioCapturerInfo
// @ts-ignore
}
this.audioCapturer = await audio.createAudioCapturer(AudioCapturerOptions)
}
async getFileFd() {
let filesDir = globalThis.abilityContext.filesDir
let path = filesDir + '/test.wav'
Logger.info(this.tag, `getFileFd path : ${path}`)
this.file = fs.openSync(path, fs.OpenMode.READ_WRITE | fs.OpenMode.CREATE | fs.OpenMode.TRUNC)
return this.file.fd
}
async startCapturer() {
try {
this.fd = await this.getFileFd()
Logger.info(this.tag, `fd : ${this.fd}`)
if (this.fd !== null) {
Logger.info(this.tag, `create audio fileAssets success fd : ${this.fd}`)
}
else {
Logger.info(this.tag, `create audio fileAssets error`)
}
let header = mediaPlay.encodeWAV(audio.AudioSamplingRate.SAMPLE_RATE_44100, audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE, audio.AudioChannel.CHANNEL_2)
Logger.info(this.tag, `wav header length: ${header.buffer.byteLength}`)
fs.writeSync(this.fd, header.buffer)
this.audioCapturer.start(async (err) => {
if (err) {
Logger.info(this.tag, `Capture start failed`)
} else {
Logger.info(this.tag, `Capture start success`)
let bufferSize = await this.audioCapturer.getBufferSize()
Logger.info(this.tag, `audioCapture bufferSize: ${bufferSize}`)
this.isRecorder = true
while (this.isRecorder) {
Logger.info(this.tag, 'audioCapture: ---------READ BUFFER---------')
let buffer = await this.audioCapturer.read(bufferSize, true)
Logger.info(this.tag, 'audioCapture: ---------WRITE BUFFER---------')
fs.writeSync(this.fd, buffer)
}
}
})
} catch (err) {
Logger.info(this.tag, `startCapturer fail err: ${err}, message: ${err.message}, code: ${err.code}`)
}
}
async stopCapturer() {
try {
await this.audioCapturer.stop()
this.isRecorder = false
Logger.info(this.tag, `stopCapturer success`)
} catch (err) {
Logger.info(this.tag, `stopCapturer fail err: ${err}, message: ${err.message}, code: ${err.code}`)
}
}
async releaseCapturer() {
try {
if (this.audioCapturer) {
await this.audioCapturer.release()
Logger.info(this.tag, `releaseCapturer success`)
}
if (this.file) {
fs.closeSync(this.file);
Logger.info(this.tag, `release file success`)
}
} catch (err) {
Logger.info(this.tag, `stopCapturer fail err: ${err}, message: ${err.message}, code: ${err.code}`)
}
}
}
export default new AudioCapturer()
\ No newline at end of file
import audio from '@ohos.multimedia.audio'
import fileio from '@ohos.fileio'
import Logger from '../model/Logger'
// @ts-ignore
import fs from '@ohos.file.fs';
class AudioRenderer {
private tag: string = 'qlw AudioRenderer'
private static instance: AudioRenderer = new AudioRenderer()
private audioRenderer: audio.AudioRenderer = undefined
private fd: number = undefined
private offset: number = undefined
async createAudioRenderer(){
let audioStreamInfo = {
samplingRate: audio.AudioSamplingRate.SAMPLE_RATE_44100,
channels: audio.AudioChannel.CHANNEL_2,
// channels: audio.AudioChannel.CHANNEL_1,
sampleFormat: audio.AudioSampleFormat.SAMPLE_FORMAT_S16LE,
encodingType: audio.AudioEncodingType.ENCODING_TYPE_RAW
}
let audioRendererInfo = {
content: audio.ContentType.CONTENT_TYPE_MUSIC,
usage: audio.StreamUsage.STREAM_USAGE_MEDIA,
rendererFlags: 0
}
let audioRendererOptions = {
streamInfo: audioStreamInfo,
rendererInfo: audioRendererInfo
}
this.audioRenderer = await audio.createAudioRenderer(audioRendererOptions);
}
async startRenderer(){
try{
await this.audioRenderer.start()
// await globalThis.abilityContext.resourceManager.getRawFileDescriptor('test_44100_2.wav').then(value => {
// this.fd = value.fd
// Logger.info(this.tag, `fd : ${this.fd}`)
// let fileDescriptor = {fd: value.fd, offset: value.offset, length: value.length};
// Logger.info(this.tag, `getRawFileDescriptor success fileDescriptor:` + JSON.stringify(fileDescriptor) )
// }).catch(error => {
// console.log('case getRawFileDescriptor err: ' + error);
// });
globalThis.abilityContext.resourceManager.getRawFd("test_44100_2.wav").then(value => {
this.fd = value.fd
this.offset = value.offset
Logger.info(this.tag, `getRawFd fd : ${this.fd}, offset: ${value.offset}, length: ${value.length}`)
}).catch(err => {
console.log(`getRawFd fail err: ${err}, message: ${err.message}, code: ${err.code}`);
})
let bufferSize = await this.audioRenderer.getBufferSize()
Logger.info(this.tag, `audioRenderer bufferSize:` + JSON.stringify(bufferSize))
let stat = await fs.stat(this.fd);
let len = stat.size % bufferSize == 0 ? Math.floor(stat.size / bufferSize) : Math.floor(stat.size / bufferSize + 1);
let buf = new ArrayBuffer(bufferSize);
while (true) {
for (let i = 0;i < len; i++) {
let options = {
offset: i * bufferSize + this.offset,
length: bufferSize
}
await fs.read(this.fd, buf, options)
try {
await this.audioRenderer.write(buf)
} catch (err) {
console.error(`audioRenderer.write err: ${err}`)
}
}
}
}catch(err){
Logger.info(this.tag, `startRenderer fail err: ${err}, message: ${err.message}, code: ${err.code}`)
}
}
async stopRenderer(){
try{
await this.audioRenderer.stop()
}catch(err){
Logger.info(this.tag, `stopCapturer fail err: ${err}, message: ${err.message}, code: ${err.code}`)
}
}
async releaseRenderer(){
try{
if (this.audioRenderer){
await this.audioRenderer.release()
// await globalThis.abilityContext.resourceManager.closeRawFileDescriptor('test_44100_2.wav').then(()=> {
// Logger.info(this.tag, `closeRawFileDescriptor success`)
// }).catch(err => {
// Logger.info(this.tag, `closeRawFileDescriptor fail err: ${err}, message: ${err.message}, code: ${err.code}`)
// });
await globalThis.abilityContext.resourceManager.closeRawFd('test_44100_2.wav').then(()=> {
Logger.info(this.tag, `closeRawFileDescriptor success`)
}).catch(err => {
Logger.info(this.tag, `closeRawFileDescriptor fail err: ${err}, message: ${err.message}, code: ${err.code}`)
});
}
}catch(err){
Logger.info(this.tag, `stopCapturer fail err: ${err}, message: ${err.message}, code: ${err.code}`)
}
}
}
export default new AudioRenderer()
\ No newline at end of file
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file 日期工具
*/
export default class DateTimeUtil {
/**
* 时分秒
*/
getTime() {
const DATETIME = new Date()
return this.concatTime(DATETIME.getHours(), DATETIME.getMinutes(), DATETIME.getSeconds())
}
getHour() {
const DATETIME = new Date()
return DATETIME.getHours()
}
getMinute() {
const DATETIME = new Date()
return DATETIME.getMinutes()
}
getSecond() {
const DATETIME = new Date()
return DATETIME.getSeconds()
}
/**
* 年月日
*/
getDate() {
const DATETIME = new Date()
return this.concatDate(DATETIME.getFullYear(), DATETIME.getMonth() + 1, DATETIME.getDate())
}
getFullYear() {
const DATETIME = new Date()
return DATETIME.getFullYear()
}
getMonth() {
const DATETIME = new Date()
return DATETIME.getMonth() + 1
}
getDay() {
const DATETIME = new Date()
return DATETIME.getDate()
}
/**
* 日期不足两位补充0
* @param value-数据值
*/
fill(value: number) {
return (value > 9 ? '' : '0') + value
}
/**
* 年月日格式修饰
* @param year
* @param month
* @param date
*/
concatDate(year: number, month: number, date: number) {
return `${year}${this.fill(month)}${this.fill(date)}`
}
/**
* 时分秒格式修饰
* @param hours
* @param minutes
* @param seconds
*/
concatTime(hours: number, minutes: number, seconds: number) {
return `${this.fill(hours)}${this.fill(minutes)}${this.fill(seconds)}`
}
}
\ No newline at end of file
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import hilog from '@ohos.hilog';
class Logger {
private domain: number;
private prefix: string;
private format: string = "%{public}s, %{public}s";
constructor(prefix: string) {
this.prefix = prefix;
this.domain = 0xFF00;
}
debug(...args: any[]) {
hilog.debug(this.domain, this.prefix, this.format, args);
}
info(...args: any[]) {
hilog.info(this.domain, this.prefix, this.format, args);
}
warn(...args: any[]) {
hilog.warn(this.domain, this.prefix, this.format, args);
}
error(...args: any[]) {
hilog.error(this.domain, this.prefix, this.format, args);
}
}
export default new Logger('[Screenshot]');
\ No newline at end of file
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import mediaLibrary from '@ohos.multimedia.mediaLibrary'
import DateTimeUtil from '../model/DateTimeUtil'
import Logger from './Logger'
export default class MediaUtils {
private tag: string = 'qlw MediaUtils'
private mediaTest: mediaLibrary.MediaLibrary = mediaLibrary.getMediaLibrary(globalThis.abilityContext)
private static instance: MediaUtils = new MediaUtils()
public static getInstance() {
if (this.instance === undefined) {
this.instance = new MediaUtils()
}
return this.instance
}
async createAndGetUri(mediaType: number) {
let info = this.getInfoFromType(mediaType)
let dateTimeUtil = new DateTimeUtil()
let name = `${dateTimeUtil.getDate()}_${dateTimeUtil.getTime()}`
let displayName = `${info.prefix}${name}${info.suffix}`
Logger.info(this.tag, `displayName = ${displayName},mediaType = ${mediaType}`)
let publicPath = await this.mediaTest.getPublicDirectory(info.directory)
Logger.info(this.tag, `publicPath = ${publicPath}`)
try{
return await this.mediaTest.createAsset(mediaType, displayName, publicPath)
}catch(err){
Logger.info(this.tag, `createAsset err ` + JSON.stringify(err))
}
}
async queryFile(dataUri: any) {
let fileKeyObj = mediaLibrary.FileKey
if (dataUri !== undefined) {
let args = dataUri.id.toString()
let fetchOp = {
selections: `${fileKeyObj.ID}=?`,
selectionArgs: [args],
}
const fetchFileResult = await this.mediaTest.getFileAssets(fetchOp)
Logger.info(this.tag, `fetchFileResult.getCount() = ${fetchFileResult.getCount()}`)
const fileAsset = await fetchFileResult.getAllObject()
return fileAsset[0]
}
}
async getFdPath(fileAsset: any) {
let fd = await fileAsset.open('Rw')
Logger.info(this.tag, `fd = ${fd}`)
return fd
}
async createFile(mediaType: number) {
let dataUri = await this.createAndGetUri(mediaType)
if (dataUri) {
let fileAsset = await this.queryFile(dataUri)
if (fileAsset) {
let fd = await this.getFdPath(fileAsset)
return fd
}
}
}
async getFileAssetsFromType(mediaType: number) {
Logger.info(this.tag, `getFileAssetsFromType,mediaType = ${mediaType}`)
let fileKeyObj = mediaLibrary.FileKey
let fetchOp = {
selections: `${fileKeyObj.MEDIA_TYPE}=?`,
selectionArgs: [`${mediaType}`],
}
const fetchFileResult = await this.mediaTest.getFileAssets(fetchOp)
Logger.info(this.tag, `getFileAssetsFromType,fetchFileResult.count = ${fetchFileResult.getCount()}`)
let fileAssets = []
if (fetchFileResult.getCount() > 0) {
fileAssets = await fetchFileResult.getAllObject()
}
return fileAssets
}
async getAlbums() {
Logger.info(this.tag, 'getAlbums begin')
let albums = []
const [ files, images, videos, audios ] = await Promise.all([
this.getFileAssetsFromType(mediaLibrary.MediaType.FILE),
this.getFileAssetsFromType(mediaLibrary.MediaType.IMAGE),
this.getFileAssetsFromType(mediaLibrary.MediaType.VIDEO),
this.getFileAssetsFromType(mediaLibrary.MediaType.AUDIO)
])
albums.push({
albumName: 'Documents', count: files.length, mediaType: mediaLibrary.MediaType.FILE
})
albums.push({
albumName: 'Pictures', count: images.length, mediaType: mediaLibrary.MediaType.IMAGE
})
albums.push({
albumName: 'Videos', count: videos.length, mediaType: mediaLibrary.MediaType.VIDEO
})
albums.push({
albumName: 'Audios', count: audios.length, mediaType: mediaLibrary.MediaType.AUDIO
})
return albums
}
deleteFile(media: any) {
let uri = media.uri
Logger.info(this.tag, `deleteFile,uri = ${uri}`)
return this.mediaTest.deleteAsset(uri)
}
onDateChange(callback: () => void) {
this.mediaTest.on('albumChange', () => {
Logger.info(this.tag, 'albumChange called')
callback()
})
this.mediaTest.on('imageChange', () => {
Logger.info(this.tag, 'imageChange called')
callback()
})
this.mediaTest.on('audioChange', () => {
Logger.info(this.tag, 'audioChange called')
callback()
})
this.mediaTest.on('videoChange', () => {
Logger.info(this.tag, 'videoChange called')
callback()
})
this.mediaTest.on('fileChange', () => {
Logger.info(this.tag, 'fileChange called')
callback()
})
}
offDateChange() {
this.mediaTest.off('albumChange')
this.mediaTest.off('imageChange')
this.mediaTest.off('audioChange')
this.mediaTest.off('videoChange')
this.mediaTest.off('fileChange')
}
getInfoFromType(mediaType: number) {
let result = {
prefix: '', suffix: '', directory: 0
}
switch (mediaType) {
case mediaLibrary.MediaType.FILE:
result.prefix = 'FILE_'
result.suffix = '.txt'
result.directory = mediaLibrary.DirectoryType.DIR_DOCUMENTS
break
case mediaLibrary.MediaType.IMAGE:
result.prefix = 'IMG_'
result.suffix = '.jpg'
result.directory = mediaLibrary.DirectoryType.DIR_IMAGE
break
case mediaLibrary.MediaType.VIDEO:
result.prefix = 'VID_'
result.suffix = '.mp4'
result.directory = mediaLibrary.DirectoryType.DIR_VIDEO
break
case mediaLibrary.MediaType.AUDIO:
result.prefix = 'AUD_'
result.suffix = '.wav'
result.directory = mediaLibrary.DirectoryType.DIR_AUDIO
break
}
return result
}
}
\ No newline at end of file
/*
* Copyright (c) 2022 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import media from '@ohos.multimedia.media'
import Logger from '../model/Logger'
let audioConfig = {
audioSourceType: 1,
audioEncoder: 3,
audioEncodeBitRate: 22050,
audioSampleRate: 22050,
numberOfChannels: 2,
format: 6,
uri: ''
}
export default class RecordModel {
private tag: string = 'qlw RecordModel'
private audioRecorder: media.AudioRecorder = undefined
initAudioRecorder(handleStateChange: () => void) {
this.release();
this.audioRecorder = media.createAudioRecorder()
Logger.info(this.tag, 'create audioRecorder success')
this.audioRecorder.on('prepare', () => {
Logger.info(this.tag, 'setCallback prepare case callback is called')
this.audioRecorder.start()
})
this.audioRecorder.on('start', () => {
Logger.info(this.tag, 'setCallback start case callback is called')
handleStateChange()
})
this.audioRecorder.on('stop', () => {
Logger.info(this.tag, 'audioRecorder stop called')
this.audioRecorder.release()
})
this.audioRecorder.on('pause', () => {
Logger.info(this.tag, 'audioRecorder pause finish')
handleStateChange()
})
this.audioRecorder.on('resume', () => {
Logger.info(this.tag, 'audioRecorder resume finish')
handleStateChange()
})
}
release() {
if (typeof (this.audioRecorder) !== `undefined`) {
Logger.info(this.tag, 'audioRecorder release')
this.audioRecorder.release()
this.audioRecorder = undefined
}
}
startRecorder(pathName: string) {
Logger.info(this.tag, `startRecorder, pathName = ${pathName}`)
if (typeof (this.audioRecorder) !== 'undefined') {
Logger.info(this.tag, 'start prepare')
audioConfig.uri = pathName
this.audioRecorder.prepare(audioConfig)
} else {
Logger.error(this.tag, 'case failed, audioRecorder is null')
}
}
pause() {
Logger.info(this.tag, 'audioRecorder pause called')
if (typeof (this.audioRecorder) !== `undefined`) {
this.audioRecorder.pause()
}
}
resume() {
Logger.info(this.tag, 'audioRecorder resume called')
if (typeof (this.audioRecorder) !== `undefined`) {
this.audioRecorder.resume()
}
}
finish() {
if (typeof (this.audioRecorder) !== `undefined`) {
this.audioRecorder.stop()
}
}
}
\ No newline at end of file
// @ts-nocheck
import media from '@ohos.multimedia.media'
import fs from '@ohos.file.fs'
import Logger from './Logger'
const TAG = 'qlw play'
export class mediaPlay {
private avPlay: media.AVPlayer = undefined
private surfaceId: number = -1
public totalDuration: number
async getFileFd(name) {
let filesDir = globalThis.abilityContext.filesDir
let path = filesDir + '/' + name
let file = fs.openSync(path)
return file.fd
}
async getRawfileFd(name) {
let file = await globalThis.abilityContext.resourceManager.getRawFd(name)
return file.fd
}
getCurrentTime() {
return 0
}
seek() {
}
async init(surfaceId?) {
let fd
if (surfaceId) {
this.surfaceId = surfaceId
fd = await this.getFileFd('test.mp4')
} else {
fd = await this.getFileFd('test.wav')
}
Logger.info(TAG, ` fd success : ${fd}`)
this.avPlay = await media.createAVPlayer()
this.setCallBack(this.avPlay)
this.avPlay.url = 'fd://' + fd
}
async initVideo(surfaceId) {
this.surfaceId = surfaceId
let fd = await this.getRawfileFd('video.mp4')
Logger.info(TAG, ` fd success : ${fd}`)
this.avPlay = await media.createAVPlayer()
this.setCallBack(this.avPlay)
this.avPlay.url = 'fd://' + fd
}
async Play() {
await this.avPlay.play()
}
setCallBack(AVPlayer) {
AVPlayer.on('stateChange', async (state, reason) => {
switch (state) {
case 'idle':
Logger.info(TAG, 'state idle start')
break;
case 'initialized':
Logger.info(TAG + 'state initialized start ')
if (this.surfaceId) {
AVPlayer.surfaceId = this.surfaceId
}
await AVPlayer.prepare()
Logger.info(TAG, 'state initialized end')
break;
case 'prepared':
Logger.info(TAG, 'state prepared start')
await AVPlayer.play()
Logger.info(TAG, 'state prepared end')
break;
case 'playing':
Logger.info(TAG, 'state playing callback')
break;
case 'paused':
Logger.info(TAG, 'state paused callback')
break;
case 'completed':
await AVPlayer.stop()
await AVPlayer.release()
case 'error':
Logger.info(TAG, 'state error callback')
break;
}
})
AVPlayer.on('error', (err) => {
Logger.info(TAG, `state error callback err:${err},code:${err.code},message:${err.message}}`)
})
}
async release(){
if (this.avPlay){
await this.avPlay.release()
Logger.info(TAG, 'avplay release success')
}
}
encodeWAV(sampleRateValue, sampleBitsValue, channelCountValue) {
let sampleRate = sampleRateValue;
let dataLen = sampleRate * 1000;
let sampleBits = sampleBitsValue * 8 + 8 // 采样格式
let channelCount = channelCountValue; // 单声道
let offset = 0;
let buffer = new ArrayBuffer(44);
let data = new DataView(buffer);
// 资源交换文件标识符
this.writeString(data, offset, 'RIFF');
offset += 4;
// 下个地址开始到文件尾总字节数,即文件大小-8
data.setUint32(offset, 36 + dataLen, true);
offset += 4;
// WAV文件标志
this.writeString(data, offset, 'WAVE');
offset += 4;
// 波形格式标志
this.writeString(data, offset, 'fmt ');
offset += 4;
// 过滤字节,一般为 0x10 = 16
data.setUint32(offset, 16, true);
offset += 4;
// 格式类别 (PCM形式采样数据)
data.setUint16(offset, 1, true);
offset += 2;
// 通道数
data.setUint16(offset, channelCount, true);
offset += 2;
// 采样率,每秒样本数,表示每个通道的播放速度
data.setUint32(offset, sampleRate, true);
offset += 4;
// 波形数据传输率 (每秒平均字节数) 单声道×每秒数据位数×每样本数据位/8
data.setUint32(offset, channelCount * sampleRate * (sampleBits / 8), true);
offset += 4;
// 快数据调整数 采样一次占用字节数 单声道×每样本的数据位数/8
data.setUint16(offset, channelCount * (sampleBits / 8), true);
offset += 2;
// 每样本数据位数
data.setUint16(offset, sampleBits, true);
offset += 2;
// 数据标识符
this.writeString(data, offset, 'data');
offset += 4;
// 采样数据总数,即数据总大小-44
data.setUint32(offset, dataLen, true);
offset += 4;
return data;
}
writeString(data, offset, str) {
for (let i = 0; i < str.length; i++) {
data.setUint8(offset + i, str.charCodeAt(i));
}
}
}
export default new mediaPlay()
export function fillNum(num) {
if (num < 10) {
return '0' + num
}
return num.toString()
}
export function getTimeString(time) {
if (time == -1 || time == undefined) {
time = 0
}
let hour = Math.floor(time % (1000 * 60 * 60 * 24) / (1000 * 60 * 60))
let minute = Math.floor(time % (1000 * 60 * 60) / (1000 * 60))
let second = Math.floor(time % (1000 * 60) / 1000)
if (hour > 0) {
return `${fillNum(hour)}:${fillNum(minute)}:${fillNum(second)}`
}
return `${fillNum(minute)}:${fillNum(second)}`
}
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册