完善长图拼接,添加视频转文字(待完善)
This commit is contained in:
parent
ca75abba37
commit
c6797fd97b
Binary file not shown.
|
|
@ -12,6 +12,7 @@
|
||||||
"cmccssosdk@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/quick_login_hm_1.0.2.har": "cmccssosdk@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/quick_login_hm_1.0.2.har",
|
"cmccssosdk@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/quick_login_hm_1.0.2.har": "cmccssosdk@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/quick_login_hm_1.0.2.har",
|
||||||
"ctaccount@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/ctaccount_v1.1.2.har": "ctaccount@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/ctaccount_v1.1.2.har",
|
"ctaccount@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/ctaccount_v1.1.2.har": "ctaccount@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/ctaccount_v1.1.2.har",
|
||||||
"dljson@../oh_modules/.ohpm/ctaccount@qccjk9bmoqtng+2vpbi+2wqjznsjx4thqhodhlvlvn0=/oh_modules/ctaccount/library/dlJson.har": "dljson@../oh_modules/.ohpm/ctaccount@qccjk9bmoqtng+2vpbi+2wqjznsjx4thqhodhlvlvn0=/oh_modules/ctaccount/library/dlJson.har",
|
"dljson@../oh_modules/.ohpm/ctaccount@qccjk9bmoqtng+2vpbi+2wqjznsjx4thqhodhlvlvn0=/oh_modules/ctaccount/library/dlJson.har": "dljson@../oh_modules/.ohpm/ctaccount@qccjk9bmoqtng+2vpbi+2wqjznsjx4thqhodhlvlvn0=/oh_modules/ctaccount/library/dlJson.har",
|
||||||
|
"qcloudfileflash@libs/qcloudfileflash.har": "qcloudfileflash@libs/qcloudfileflash.har",
|
||||||
"unicom_login_harmony@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/unicom_login_harmony_v1.0.4AR001B0214.har": "unicom_login_harmony@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/unicom_login_harmony_v1.0.4AR001B0214.har"
|
"unicom_login_harmony@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/unicom_login_harmony_v1.0.4AR001B0214.har": "unicom_login_harmony@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/unicom_login_harmony_v1.0.4AR001B0214.har"
|
||||||
},
|
},
|
||||||
"packages": {
|
"packages": {
|
||||||
|
|
@ -62,6 +63,12 @@
|
||||||
"resolved": "../oh_modules/.ohpm/ctaccount@qccjk9bmoqtng+2vpbi+2wqjznsjx4thqhodhlvlvn0=/oh_modules/ctaccount/library/dlJson.har",
|
"resolved": "../oh_modules/.ohpm/ctaccount@qccjk9bmoqtng+2vpbi+2wqjznsjx4thqhodhlvlvn0=/oh_modules/ctaccount/library/dlJson.har",
|
||||||
"registryType": "local"
|
"registryType": "local"
|
||||||
},
|
},
|
||||||
|
"qcloudfileflash@libs/qcloudfileflash.har": {
|
||||||
|
"name": "qcloudfileflash",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "libs/qcloudfileflash.har",
|
||||||
|
"registryType": "local"
|
||||||
|
},
|
||||||
"unicom_login_harmony@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/unicom_login_harmony_v1.0.4AR001B0214.har": {
|
"unicom_login_harmony@../oh_modules/.ohpm/@getui+gysdk@1.0.10/oh_modules/@getui/gysdk/libs/unicom_login_harmony_v1.0.4AR001B0214.har": {
|
||||||
"name": "unicom_login_harmony",
|
"name": "unicom_login_harmony",
|
||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
|
|
|
||||||
|
|
@ -7,7 +7,8 @@
|
||||||
"license": "",
|
"license": "",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@ohos/axios": "^2.2.6",
|
"@ohos/axios": "^2.2.6",
|
||||||
"@getui/gysdk": "1.0.10"
|
"@getui/gysdk": "1.0.10",
|
||||||
|
"qcloudfileflash": "file:./libs/qcloudfileflash.har"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -16,4 +16,9 @@ export class Constants {
|
||||||
//
|
//
|
||||||
static readonly ENCRYPT = "wE8x4EnIHgyGOyjnoluzI2vk60wz5eNI"
|
static readonly ENCRYPT = "wE8x4EnIHgyGOyjnoluzI2vk60wz5eNI"
|
||||||
static readonly SIGNATURE = "hfLLOtXRjd0e1Ac7O6sAXrECH2E828S9"
|
static readonly SIGNATURE = "hfLLOtXRjd0e1Ac7O6sAXrECH2E828S9"
|
||||||
|
|
||||||
|
//腾讯云
|
||||||
|
static readonly QCLOUD_APP_ID = "1366199074"
|
||||||
|
static readonly QCLOUD_SECRET_ID = "AKIDYGvVCi06ycDk8ZprfFclgNpFer4D9sPi"
|
||||||
|
static readonly QCLOUD_SECRET_KEY = "72iBPPBj390d2PipqhMmyve9QSFpBKEu"
|
||||||
}
|
}
|
||||||
|
|
@ -89,6 +89,16 @@ export class RouterUrls {
|
||||||
*/
|
*/
|
||||||
static readonly IMAGE_MERGE_PAGE = "pages/main/home/tools/ImageMergePage"
|
static readonly IMAGE_MERGE_PAGE = "pages/main/home/tools/ImageMergePage"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 视频转文字页
|
||||||
|
*/
|
||||||
|
static readonly VIDEO_TO_TEXT_PAGE = "pages/main/home/tools/VideoToTextPage"
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 语音转文字页
|
||||||
|
*/
|
||||||
|
static readonly AUDIO_TO_TEXT_PAGE = "pages/main/home/tools/AudioToTextPage"
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 素材详情页
|
* 素材详情页
|
||||||
*/
|
*/
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
import { Type } from "class-transformer";
|
||||||
|
import "reflect-metadata";
|
||||||
|
|
||||||
|
export class VoiceRecognizeResultEntity {
|
||||||
|
code: number = 0;
|
||||||
|
message: string = '';
|
||||||
|
request_id: string = '';
|
||||||
|
@Type(() => FlashResult)
|
||||||
|
flash_result: Array<FlashResult> = [];
|
||||||
|
audio_duration: number = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class FlashResult {
|
||||||
|
channel_id: number = 0;
|
||||||
|
@Type(() => Sentence)
|
||||||
|
sentence_list: Array<Sentence> = [];
|
||||||
|
text: string = '';
|
||||||
|
}
|
||||||
|
|
||||||
|
export class Sentence {
|
||||||
|
emotional_energy: number = 0;
|
||||||
|
end_time: number = 0;
|
||||||
|
speaker_id: number = 0;
|
||||||
|
speech_speed: number = 0;
|
||||||
|
start_time: number = 0;
|
||||||
|
text: string = '';
|
||||||
|
}
|
||||||
|
|
@ -47,7 +47,7 @@ export class LocalMediaManager {
|
||||||
|
|
||||||
static getAllImages(): Array<string> {
|
static getAllImages(): Array<string> {
|
||||||
let array = PrefUtils.getStringArray('local_record')
|
let array = PrefUtils.getStringArray('local_record')
|
||||||
return array.filter(item => item.endsWith('.jpeg'))
|
return array.filter(item => item.endsWith('.jpeg') || item.endsWith('.jpg') || item.endsWith('.png'))
|
||||||
}
|
}
|
||||||
|
|
||||||
static deleteAllImages() {
|
static deleteAllImages() {
|
||||||
|
|
|
||||||
|
|
@ -46,6 +46,7 @@ export class MediaManager {
|
||||||
} else {
|
} else {
|
||||||
console.error('Create AVImageGenerator failed!');
|
console.error('Create AVImageGenerator failed!');
|
||||||
}
|
}
|
||||||
|
FileUtil.closeSync(file)
|
||||||
mediaList.push(record)
|
mediaList.push(record)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
|
|
@ -69,9 +70,10 @@ export class MediaManager {
|
||||||
for (let i = 0; i < imageUri.length; i++) {
|
for (let i = 0; i < imageUri.length; i++) {
|
||||||
try {
|
try {
|
||||||
let uri = imageUri[i]
|
let uri = imageUri[i]
|
||||||
let file = FileUtil.openSync(uri)
|
let file = FileUtil.openSync(uri) //判断图片是否存在 FileUtil.access()无效
|
||||||
let record = new MediaRecordEntity(uri)
|
let record = new MediaRecordEntity(uri)
|
||||||
record.name = FileUtil.getFileName(uri)
|
record.name = FileUtil.getFileName(uri)
|
||||||
|
FileUtil.closeSync(file)
|
||||||
mediaList.push(record)
|
mediaList.push(record)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e)
|
console.error(e)
|
||||||
|
|
|
||||||
|
|
@ -144,13 +144,15 @@ export struct HomePage {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'check_Task': {
|
case 'check_Task': {
|
||||||
|
break
|
||||||
}
|
}
|
||||||
case 'course': {
|
case 'course': {
|
||||||
this.getUIContext().getRouter().pushUrl({url: RouterUrls.COURSE_PAGE})
|
this.getUIContext().getRouter().pushUrl({url: RouterUrls.COURSE_PAGE})
|
||||||
|
break
|
||||||
}
|
}
|
||||||
case 'web_link': {
|
case 'web_link': {
|
||||||
WantUtil.toWebBrowser(Constants.WEB_URL)
|
WantUtil.toWebBrowser(Constants.WEB_URL)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
@ -348,6 +350,7 @@ export struct HomePage {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'videoToText': {
|
case 'videoToText': {
|
||||||
|
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIDEO_TO_TEXT_PAGE})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'longImageMerge': {
|
case 'longImageMerge': {
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ struct AddAudioPage {
|
||||||
let videoFile = FileUtil.openSync(this.videoUri!!, fileIo.OpenMode.READ_ONLY)
|
let videoFile = FileUtil.openSync(this.videoUri!!, fileIo.OpenMode.READ_ONLY)
|
||||||
// 复制视频文件到缓存目录下
|
// 复制视频文件到缓存目录下
|
||||||
FileUtil.copyFileSync(videoFile.fd, cacheVideoPath)
|
FileUtil.copyFileSync(videoFile.fd, cacheVideoPath)
|
||||||
|
FileUtil.closeSync(videoFile)
|
||||||
|
|
||||||
let cacheAudioPath = FileUtil.getCacheDirPath() + FileUtil.separator + `cache_${systemDateTime.getTime()}.mp3`
|
let cacheAudioPath = FileUtil.getCacheDirPath() + FileUtil.separator + `cache_${systemDateTime.getTime()}.mp3`
|
||||||
if (FileUtil.accessSync(cacheAudioPath)) {
|
if (FileUtil.accessSync(cacheAudioPath)) {
|
||||||
|
|
@ -42,6 +43,7 @@ struct AddAudioPage {
|
||||||
let audioFile = FileUtil.openSync(this.audioUri!!, fileIo.OpenMode.READ_ONLY)
|
let audioFile = FileUtil.openSync(this.audioUri!!, fileIo.OpenMode.READ_ONLY)
|
||||||
// 复制音频文件到缓存目录下
|
// 复制音频文件到缓存目录下
|
||||||
FileUtil.copyFileSync(audioFile.fd, cacheAudioPath)
|
FileUtil.copyFileSync(audioFile.fd, cacheAudioPath)
|
||||||
|
FileUtil.closeSync(audioFile)
|
||||||
|
|
||||||
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
|
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
|
||||||
let cmd = `ffmpeg -i ${cacheVideoPath} -stream_loop -1 -i ${cacheAudioPath} -c:v copy -c:a aac -shortest -map 0:v -map 1:a ${outputPath}`
|
let cmd = `ffmpeg -i ${cacheVideoPath} -stream_loop -1 -i ${cacheAudioPath} -c:v copy -c:a aac -shortest -map 0:v -map 1:a ${outputPath}`
|
||||||
|
|
|
||||||
|
|
@ -48,6 +48,7 @@ struct AddWatermarkPage {
|
||||||
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
||||||
// 复制文件到缓存目录下
|
// 复制文件到缓存目录下
|
||||||
FileUtil.copyFileSync(file.fd, cacheVideoPath)
|
FileUtil.copyFileSync(file.fd, cacheVideoPath)
|
||||||
|
FileUtil.closeSync(file)
|
||||||
|
|
||||||
let imageX = (vp2px(this.rect.x) * this.videoSize.width!!) / this.playerSize.width!!
|
let imageX = (vp2px(this.rect.x) * this.videoSize.width!!) / this.playerSize.width!!
|
||||||
let imageY = (vp2px(this.rect.y) * this.videoSize.height!!) / this.playerSize.height!!
|
let imageY = (vp2px(this.rect.y) * this.videoSize.height!!) / this.playerSize.height!!
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,6 @@
|
||||||
|
@ComponentV2
|
||||||
|
@Entry
|
||||||
|
struct AudioToTextPage {
|
||||||
|
build() {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -43,6 +43,7 @@ struct ClipVideoPage {
|
||||||
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
||||||
// 复制文件到缓存目录下
|
// 复制文件到缓存目录下
|
||||||
FileUtil.copyFileSync(file.fd, cacheVideoPath)
|
FileUtil.copyFileSync(file.fd, cacheVideoPath)
|
||||||
|
FileUtil.closeSync(file)
|
||||||
|
|
||||||
let clipWidth: number = 0
|
let clipWidth: number = 0
|
||||||
let clipHeight: number = 0
|
let clipHeight: number = 0
|
||||||
|
|
|
||||||
|
|
@ -1,8 +1,8 @@
|
||||||
import { PhotoHelper } from '@pura/picker_utils'
|
import { PhotoHelper } from '@pura/picker_utils'
|
||||||
import { TitleBar } from '../../../../view/TitleBar'
|
import { TitleBar } from '../../../../view/TitleBar'
|
||||||
import { photoAccessHelper } from '@kit.MediaLibraryKit'
|
import { photoAccessHelper } from '@kit.MediaLibraryKit'
|
||||||
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'
|
import { BusinessError } from '@kit.BasicServicesKit'
|
||||||
import { AppUtil, FileUtil } from '@pura/harmony-utils'
|
import { AppUtil, DisplayUtil, FileUtil } from '@pura/harmony-utils'
|
||||||
import { ToastUtils } from '../../../../utils/ToastUtils'
|
import { ToastUtils } from '../../../../utils/ToastUtils'
|
||||||
import { fileIo } from '@kit.CoreFileKit'
|
import { fileIo } from '@kit.CoreFileKit'
|
||||||
import { SaveUtils } from '../../../../utils/SaveUtils'
|
import { SaveUtils } from '../../../../utils/SaveUtils'
|
||||||
|
|
@ -10,23 +10,74 @@ import { LoadingDialog } from '../../../../dialog/LoadingDialog'
|
||||||
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'
|
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'
|
||||||
import { EventConstants } from '../../../../common/EventConstants'
|
import { EventConstants } from '../../../../common/EventConstants'
|
||||||
import { TipDialog } from '../../../../dialog/TipDialog'
|
import { TipDialog } from '../../../../dialog/TipDialog'
|
||||||
import { avSessionManager } from '../../../../manager/AVSessionManager'
|
import { image } from '@kit.ImageKit'
|
||||||
|
import { ImageUtils } from '../../../../utils/ImageUtils'
|
||||||
|
import { Luban } from '@ark/luban'
|
||||||
|
|
||||||
@Entry
|
@Entry
|
||||||
@ComponentV2
|
@ComponentV2
|
||||||
struct ImageMergePage {
|
struct ImageMergePage {
|
||||||
@Local uri?: string = undefined
|
@Local pixelMap?: image.PixelMap = undefined
|
||||||
@Local selectedImage?: string = undefined
|
@Local selectedImage?: string = undefined
|
||||||
@Local imageUris: Array<string> = []
|
@Local imageUris: Array<string> = []
|
||||||
@Local currentTime: number = 0
|
|
||||||
@Local durationTime: number = 0
|
|
||||||
@Local isPlaying: boolean = false
|
|
||||||
@Local isSuccess: boolean = false
|
@Local isSuccess: boolean = false
|
||||||
|
|
||||||
private selectedImages: Array<string> = []
|
private selectedImages: Array<string> = []
|
||||||
|
|
||||||
mergeImage() {
|
async mergeImage() {
|
||||||
|
LoadingDialog.show(this.getUIContext())
|
||||||
|
try {
|
||||||
|
let pixelArray: Array<image.PixelMap> = []
|
||||||
|
let maxWidth = DisplayUtil.getWidth()
|
||||||
|
for (let i = 0;i < this.imageUris.length;i++) {
|
||||||
|
let compressedUri = await Luban.with(this.imageUris[i]).ignoreBy(100).get()
|
||||||
|
const imageSource: image.ImageSource = image.createImageSource(compressedUri[0])
|
||||||
|
let decodingOptions: image.DecodingOptions = {
|
||||||
|
editable: true,
|
||||||
|
desiredPixelFormat: image.PixelMapFormat.RGB_565,
|
||||||
|
}
|
||||||
|
let pixelMap = imageSource.createPixelMapSync(decodingOptions)
|
||||||
|
if (pixelMap) {
|
||||||
|
let imageInfo = pixelMap.getImageInfoSync()
|
||||||
|
maxWidth = Math.max(imageInfo.size.width)
|
||||||
|
pixelArray.push(pixelMap)
|
||||||
|
} else {
|
||||||
|
ToastUtils.show('处理失败')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let totalHeight = 0
|
||||||
|
let newPixelArray: Array<image.PixelMap> = []
|
||||||
|
for (let i = 0;i < pixelArray.length;i++) {
|
||||||
|
let pixelMap = pixelArray[i]
|
||||||
|
let imageInfo = pixelMap.getImageInfoSync()
|
||||||
|
let height = Math.trunc(imageInfo.size.height * maxWidth / imageInfo.size.width)
|
||||||
|
let newPixel = await ImageUtils.resizeImage(pixelMap, maxWidth, height)
|
||||||
|
newPixelArray.push(newPixel)
|
||||||
|
totalHeight += height
|
||||||
|
}
|
||||||
|
|
||||||
|
let offScreenCanvas = new OffscreenCanvas(maxWidth, totalHeight)
|
||||||
|
let OffScreenContext = offScreenCanvas.getContext('2d')
|
||||||
|
let top = 0
|
||||||
|
newPixelArray.forEach((pixelMap) => {
|
||||||
|
let imageInfo = pixelMap.getImageInfoSync()
|
||||||
|
OffScreenContext.drawImage(pixelMap, 0, top, imageInfo.size.width, imageInfo.size.height)
|
||||||
|
top += imageInfo.size.height
|
||||||
|
})
|
||||||
|
this.pixelMap = OffScreenContext.getPixelMap(0, 0, maxWidth, totalHeight)
|
||||||
|
|
||||||
|
this.selectedImage = undefined
|
||||||
|
this.imageUris = []
|
||||||
|
this.selectedImages = []
|
||||||
|
this.isSuccess = true
|
||||||
|
ToastUtils.show('处理成功')
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
ToastUtils.show('处理失败')
|
||||||
|
}
|
||||||
|
LoadingDialog.dismiss()
|
||||||
}
|
}
|
||||||
|
|
||||||
selectPhotos() {
|
selectPhotos() {
|
||||||
|
|
@ -34,11 +85,12 @@ struct ImageMergePage {
|
||||||
MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE,
|
MIMEType: photoAccessHelper.PhotoViewMIMETypes.IMAGE_TYPE,
|
||||||
maxSelectNumber: 9,
|
maxSelectNumber: 9,
|
||||||
preselectedUris: this.selectedImages,
|
preselectedUris: this.selectedImages,
|
||||||
isOriginalSupported: true,
|
isOriginalSupported: false,
|
||||||
})
|
})
|
||||||
.then((result: photoAccessHelper.PhotoSelectResult) => {
|
.then((result: photoAccessHelper.PhotoSelectResult) => {
|
||||||
if (result.photoUris.length != 0) {
|
if (result.photoUris.length != 0) {
|
||||||
this.isSuccess = false
|
this.isSuccess = false
|
||||||
|
this.pixelMap = undefined
|
||||||
this.selectedImages = result.photoUris
|
this.selectedImages = result.photoUris
|
||||||
this.imageUris = result.photoUris
|
this.imageUris = result.photoUris
|
||||||
this.selectedImage = result.photoUris[0]
|
this.selectedImage = result.photoUris[0]
|
||||||
|
|
@ -75,110 +127,126 @@ struct ImageMergePage {
|
||||||
TitleBar({ title: '长图拼接' })
|
TitleBar({ title: '长图拼接' })
|
||||||
|
|
||||||
Stack() {
|
Stack() {
|
||||||
Stack() {
|
Scroll() {
|
||||||
Stack() {
|
Image(this.pixelMap).width('100%').height('auto')
|
||||||
Column() {
|
|
||||||
Image($r('app.media.ic_add_image')).width(40).height(40)
|
|
||||||
Text('请上传图片').fontColor($r('app.color.color_466afd')).fontSize(15).fontWeight(FontWeight.Medium).margin({ top: 8})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
.width('100%')
|
|
||||||
.height('100%')
|
|
||||||
.onClick(() => {
|
|
||||||
this.selectPhotos()
|
|
||||||
})
|
|
||||||
.visibility(this.imageUris.length !== 0 ? Visibility.None : Visibility.Visible)
|
|
||||||
|
|
||||||
Image(this.selectedImage).width('100%').height('100%')
|
|
||||||
.borderRadius(20)
|
|
||||||
.visibility(this.imageUris.length === 0 ? Visibility.None : Visibility.Visible)
|
|
||||||
}
|
}
|
||||||
.width('100%')
|
.height('100%')
|
||||||
.aspectRatio(1)
|
.scrollBar(BarState.Off)
|
||||||
.borderRadius(20)
|
.visibility(this.pixelMap ? Visibility.Visible : Visibility.None)
|
||||||
.backgroundColor(Color.White)
|
|
||||||
.shadow({radius: 10, color: '#1a9399a1'})
|
|
||||||
}
|
|
||||||
.width('100%')
|
|
||||||
.height('auto')
|
|
||||||
.padding({left: 32, right: 32})
|
|
||||||
.margin({top: 40})
|
|
||||||
|
|
||||||
Blank().layoutWeight(1)
|
Column() {
|
||||||
|
Stack() {
|
||||||
Scroll() {
|
Stack() {
|
||||||
List({space: 8}) {
|
|
||||||
ForEach(this.imageUris, (item: string, index) => {
|
|
||||||
ListItem() {
|
|
||||||
RelativeContainer() {
|
|
||||||
Stack() {
|
|
||||||
Image(item).width('100%').height('100%').borderRadius(6)
|
|
||||||
Text(`${index + 1}`)
|
|
||||||
.width(20)
|
|
||||||
.height(20)
|
|
||||||
.textAlign(TextAlign.Center)
|
|
||||||
.fontColor(Color.White)
|
|
||||||
.fontSize(14)
|
|
||||||
.borderRadius(10)
|
|
||||||
.backgroundColor('#99000000')
|
|
||||||
}
|
|
||||||
.width(80)
|
|
||||||
.height(80)
|
|
||||||
.margin({top: 11, right: 11})
|
|
||||||
|
|
||||||
Image($r('app.media.ic_delete_image')).width(22).height(22)
|
|
||||||
.alignRules({
|
|
||||||
right: {anchor: '__container__', align: HorizontalAlign.End}
|
|
||||||
})
|
|
||||||
.onClick(() => {
|
|
||||||
this.imageUris.splice(index, 1)
|
|
||||||
if (this.imageUris.length === 0) {
|
|
||||||
this.selectedImage = undefined
|
|
||||||
} else {
|
|
||||||
if (item !== this.selectedImage) {
|
|
||||||
this.selectedImage = this.imageUris[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
.height('100%')
|
|
||||||
.aspectRatio(1)
|
|
||||||
}
|
|
||||||
.onClick(() => {
|
|
||||||
this.selectedImage = item
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
if (this.imageUris.length > 0 && this.imageUris.length < 9) {
|
|
||||||
ListItem() {
|
|
||||||
Stack() {
|
Stack() {
|
||||||
Column() {
|
Column() {
|
||||||
Image($r('app.media.ic_add_image')).width(24).height(24)
|
Image($r('app.media.ic_add_image')).width(40).height(40)
|
||||||
Text('请上传图片').fontColor($r('app.color.color_466afd')).fontSize(10).margin({top: 4})
|
Text('请上传图片').fontColor($r('app.color.color_466afd')).fontSize(15).fontWeight(FontWeight.Medium).margin({ top: 8})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
.width(80)
|
.width('100%')
|
||||||
.height(80)
|
.height('100%')
|
||||||
.borderRadius(6)
|
|
||||||
.backgroundColor(Color.White)
|
|
||||||
.margin({top: 11, right: 11})
|
|
||||||
.onClick(() => {
|
.onClick(() => {
|
||||||
this.selectPhotos()
|
this.selectPhotos()
|
||||||
})
|
})
|
||||||
}
|
.visibility(this.imageUris.length !== 0 ? Visibility.None : Visibility.Visible)
|
||||||
}
|
|
||||||
}
|
|
||||||
.width('100%')
|
|
||||||
.scrollBar(BarState.Off)
|
|
||||||
.listDirection(Axis.Horizontal)
|
|
||||||
.padding({left: 32, right: 32})
|
|
||||||
}
|
|
||||||
.width('100%')
|
|
||||||
.height(92)
|
|
||||||
.scrollBar(BarState.Off)
|
|
||||||
.scrollable(ScrollDirection.Horizontal)
|
|
||||||
.margin({bottom: 20})
|
|
||||||
|
|
||||||
|
Image(this.selectedImage).width('100%').height('100%')
|
||||||
|
.borderRadius(20)
|
||||||
|
.visibility(this.imageUris.length === 0 ? Visibility.None : Visibility.Visible)
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
.aspectRatio(1)
|
||||||
|
.borderRadius(20)
|
||||||
|
.backgroundColor(Color.White)
|
||||||
|
.shadow({radius: 10, color: '#1a9399a1'})
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
.height('auto')
|
||||||
|
.padding({left: 32, right: 32})
|
||||||
|
.margin({top: 40})
|
||||||
|
|
||||||
|
Blank().layoutWeight(1)
|
||||||
|
|
||||||
|
Scroll() {
|
||||||
|
List({space: 8}) {
|
||||||
|
ForEach(this.imageUris, (item: string, index) => {
|
||||||
|
ListItem() {
|
||||||
|
RelativeContainer() {
|
||||||
|
Stack() {
|
||||||
|
Image(item).width('100%').height('100%').borderRadius(6)
|
||||||
|
Text(`${index + 1}`)
|
||||||
|
.width(20)
|
||||||
|
.height(20)
|
||||||
|
.textAlign(TextAlign.Center)
|
||||||
|
.fontColor(Color.White)
|
||||||
|
.fontSize(14)
|
||||||
|
.borderRadius(10)
|
||||||
|
.backgroundColor('#99000000')
|
||||||
|
}
|
||||||
|
.width(80)
|
||||||
|
.height(80)
|
||||||
|
.margin({top: 11, right: 11})
|
||||||
|
.borderWidth(1)
|
||||||
|
.borderRadius(6)
|
||||||
|
.borderColor(item === this.selectedImage ? $r('app.color.color_466afd') : Color.Transparent)
|
||||||
|
|
||||||
|
Image($r('app.media.ic_delete_image')).width(22).height(22)
|
||||||
|
.alignRules({
|
||||||
|
right: {anchor: '__container__', align: HorizontalAlign.End}
|
||||||
|
})
|
||||||
|
.onClick(() => {
|
||||||
|
this.imageUris.splice(index, 1)
|
||||||
|
if (this.imageUris.length === 0) {
|
||||||
|
this.selectedImage = undefined
|
||||||
|
} else {
|
||||||
|
if (item !== this.selectedImage) {
|
||||||
|
this.selectedImage = this.imageUris[0]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
.height('100%')
|
||||||
|
.aspectRatio(1)
|
||||||
|
}
|
||||||
|
.margin({left: index === 0 ? 32 : 0, right: index === 8 ? 32 : 0})
|
||||||
|
.onClick(() => {
|
||||||
|
this.selectedImage = item
|
||||||
|
})
|
||||||
|
})
|
||||||
|
|
||||||
|
if (this.imageUris.length > 0 && this.imageUris.length < 9) {
|
||||||
|
ListItem() {
|
||||||
|
Stack() {
|
||||||
|
Column() {
|
||||||
|
Image($r('app.media.ic_add_image')).width(24).height(24)
|
||||||
|
Text('请上传图片').fontColor($r('app.color.color_466afd')).fontSize(10).margin({top: 4})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.width(80)
|
||||||
|
.height(80)
|
||||||
|
.borderRadius(6)
|
||||||
|
.backgroundColor(Color.White)
|
||||||
|
.margin({top: 11, right: 11})
|
||||||
|
}
|
||||||
|
.margin({right: 32})
|
||||||
|
.onClick(() => {
|
||||||
|
this.selectPhotos()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
.scrollBar(BarState.Off)
|
||||||
|
.listDirection(Axis.Horizontal)
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
.height(92)
|
||||||
|
.scrollBar(BarState.Off)
|
||||||
|
.scrollable(ScrollDirection.Horizontal)
|
||||||
|
.margin({bottom: 20})
|
||||||
|
}
|
||||||
|
.visibility(this.pixelMap ? Visibility.None : Visibility.Visible)
|
||||||
|
}
|
||||||
|
.layoutWeight(1)
|
||||||
|
|
||||||
Stack() {
|
Stack() {
|
||||||
Button('确认处理', { type: ButtonType.Capsule, stateEffect: true })
|
Button('确认处理', { type: ButtonType.Capsule, stateEffect: true })
|
||||||
|
|
@ -225,10 +293,13 @@ struct ImageMergePage {
|
||||||
.layoutWeight(1)
|
.layoutWeight(1)
|
||||||
.backgroundColor($r('app.color.color_466afd'))
|
.backgroundColor($r('app.color.color_466afd'))
|
||||||
.onClick(() => {
|
.onClick(() => {
|
||||||
SaveUtils.saveImageVideoToAlbumDialog([this.uri!!])
|
SaveUtils.savePixelMapToAlbum(this.pixelMap!!)
|
||||||
.then((saved) => {
|
.then((saved) => {
|
||||||
if (saved) {
|
if (saved) {
|
||||||
|
this.pixelMap = undefined
|
||||||
|
this.selectedImage = undefined
|
||||||
this.imageUris = []
|
this.imageUris = []
|
||||||
|
this.selectedImages = []
|
||||||
this.showDownloadDialog()
|
this.showDownloadDialog()
|
||||||
} else {
|
} else {
|
||||||
ToastUtils.show('保存失败')
|
ToastUtils.show('保存失败')
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ struct MD5ResetPage {
|
||||||
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
||||||
// 复制文件到缓存目录下
|
// 复制文件到缓存目录下
|
||||||
FileUtil.copyFileSync(file.fd, outputPath)
|
FileUtil.copyFileSync(file.fd, outputPath)
|
||||||
|
FileUtil.closeSync(file)
|
||||||
|
|
||||||
if (FileUtil.accessSync(outputPath)) {
|
if (FileUtil.accessSync(outputPath)) {
|
||||||
this.uri = FileUtil.getUriFromPath(outputPath)
|
this.uri = FileUtil.getUriFromPath(outputPath)
|
||||||
|
|
|
||||||
|
|
@ -33,6 +33,7 @@ struct RemoveAudioPage {
|
||||||
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
||||||
// 复制文件到缓存目录下
|
// 复制文件到缓存目录下
|
||||||
FileUtil.copyFileSync(file.fd, cachePath)
|
FileUtil.copyFileSync(file.fd, cachePath)
|
||||||
|
FileUtil.closeSync(file)
|
||||||
|
|
||||||
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
|
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
|
||||||
let cmd = `ffmpeg -i ${cachePath} -an -c:v copy ${outputPath}`
|
let cmd = `ffmpeg -i ${cachePath} -an -c:v copy ${outputPath}`
|
||||||
|
|
|
||||||
|
|
@ -47,6 +47,7 @@ struct RemoveWatermarkPage {
|
||||||
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
||||||
// 复制文件到缓存目录下
|
// 复制文件到缓存目录下
|
||||||
FileUtil.copyFileSync(file.fd, cacheVideoPath)
|
FileUtil.copyFileSync(file.fd, cacheVideoPath)
|
||||||
|
FileUtil.closeSync(file)
|
||||||
|
|
||||||
let rectX = (vp2px(this.rect.x) * this.videoSize.width!!) / this.playerSize.width!!
|
let rectX = (vp2px(this.rect.x) * this.videoSize.width!!) / this.playerSize.width!!
|
||||||
let rectY = (vp2px(this.rect.y) * this.videoSize.height!!) / this.playerSize.height!!
|
let rectY = (vp2px(this.rect.y) * this.videoSize.height!!) / this.playerSize.height!!
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ struct VideoMirrorPage {
|
||||||
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
||||||
// 复制文件到缓存目录下
|
// 复制文件到缓存目录下
|
||||||
FileUtil.copyFileSync(file.fd, cacheVideoPath)
|
FileUtil.copyFileSync(file.fd, cacheVideoPath)
|
||||||
|
FileUtil.closeSync(file)
|
||||||
|
|
||||||
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
|
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
|
||||||
let cmd = `ffmpeg -i ${cacheVideoPath} -vf ${this.orientation === 1 ? "hflip" : "vflip"} -c:v h264 -pix_fmt yuv420p -y ${outputPath}`
|
let cmd = `ffmpeg -i ${cacheVideoPath} -vf ${this.orientation === 1 ? "hflip" : "vflip"} -c:v h264 -pix_fmt yuv420p -y ${outputPath}`
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ struct VideoReversePage {
|
||||||
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
let file = FileUtil.openSync(this.uri!!, fileIo.OpenMode.READ_ONLY)
|
||||||
// 复制文件到缓存目录下
|
// 复制文件到缓存目录下
|
||||||
FileUtil.copyFileSync(file.fd, cacheVideoPath)
|
FileUtil.copyFileSync(file.fd, cacheVideoPath)
|
||||||
|
FileUtil.closeSync(file)
|
||||||
|
|
||||||
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
|
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp4`
|
||||||
let cmd = `ffmpeg -i ${cacheVideoPath} -vf reverse -af areverse -c:v h264 -pix_fmt yuv420p -y ${outputPath}`
|
let cmd = `ffmpeg -i ${cacheVideoPath} -vf reverse -af areverse -c:v h264 -pix_fmt yuv420p -y ${outputPath}`
|
||||||
|
|
|
||||||
|
|
@ -17,11 +17,11 @@ import { avSessionManager } from '../../../../manager/AVSessionManager'
|
||||||
struct VideoToAudioPage {
|
struct VideoToAudioPage {
|
||||||
private controller: VideoController = new VideoController()
|
private controller: VideoController = new VideoController()
|
||||||
@Local videoUri?: string
|
@Local videoUri?: string
|
||||||
|
@Local audioUri?: string
|
||||||
@Local currentTime: number = 0
|
@Local currentTime: number = 0
|
||||||
@Local durationTime: number = 0
|
@Local durationTime: number = 0
|
||||||
@Local isPlaying: boolean = false
|
@Local isPlaying: boolean = false
|
||||||
@Local isSuccess: boolean = false
|
@Local isSuccess: boolean = false
|
||||||
@Local audioUri?: string
|
|
||||||
|
|
||||||
videoToAudio() {
|
videoToAudio() {
|
||||||
LoadingDialog.show(this.getUIContext())
|
LoadingDialog.show(this.getUIContext())
|
||||||
|
|
@ -33,6 +33,7 @@ struct VideoToAudioPage {
|
||||||
let file = FileUtil.openSync(this.videoUri!!, fileIo.OpenMode.READ_ONLY)
|
let file = FileUtil.openSync(this.videoUri!!, fileIo.OpenMode.READ_ONLY)
|
||||||
// 复制文件到缓存目录下
|
// 复制文件到缓存目录下
|
||||||
FileUtil.copyFileSync(file.fd, cachePath)
|
FileUtil.copyFileSync(file.fd, cachePath)
|
||||||
|
FileUtil.closeSync(file)
|
||||||
|
|
||||||
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp3`
|
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp3`
|
||||||
let cmd = `ffmpeg -i ${cachePath} -vn -c:a mp3 ${outputPath}`
|
let cmd = `ffmpeg -i ${cachePath} -vn -c:a mp3 ${outputPath}`
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,386 @@
|
||||||
|
import { PhotoHelper } from '@pura/picker_utils'
|
||||||
|
import { TitleBar } from '../../../../view/TitleBar'
|
||||||
|
import { photoAccessHelper } from '@kit.MediaLibraryKit'
|
||||||
|
import { BusinessError, systemDateTime } from '@kit.BasicServicesKit'
|
||||||
|
import { AppUtil, FileUtil } from '@pura/harmony-utils'
|
||||||
|
import { ToastUtils } from '../../../../utils/ToastUtils'
|
||||||
|
import { fileIo } from '@kit.CoreFileKit'
|
||||||
|
import { SaveUtils } from '../../../../utils/SaveUtils'
|
||||||
|
import { LoadingDialog } from '../../../../dialog/LoadingDialog'
|
||||||
|
import { DownloadDialog, DownloadStatus } from '../../../../dialog/DownloadDialog'
|
||||||
|
import { EventConstants } from '../../../../common/EventConstants'
|
||||||
|
import { TipDialog } from '../../../../dialog/TipDialog'
|
||||||
|
import { avSessionManager } from '../../../../manager/AVSessionManager'
|
||||||
|
import { MP4Parser } from '@ohos/mp4parser'
|
||||||
|
import { QCloud } from 'qcloudfileflash'
|
||||||
|
import { Constants } from '../../../../common/Constants'
|
||||||
|
import { VoiceRecognizeResultEntity } from '../../../../entity/VoiceRecognizeResultEntity'
|
||||||
|
import { plainToInstance } from 'class-transformer'
|
||||||
|
|
||||||
|
@Entry
|
||||||
|
@ComponentV2
|
||||||
|
struct VideoToTextPage {
|
||||||
|
private controller: VideoController = new VideoController()
|
||||||
|
@Local resultText?: string
|
||||||
|
@Local videoUri?: string
|
||||||
|
@Local currentTime: number = 0
|
||||||
|
@Local durationTime: number = 0
|
||||||
|
@Local isPlaying: boolean = false
|
||||||
|
@Local isSuccess: boolean = false
|
||||||
|
|
||||||
|
videoToAudio() {
|
||||||
|
LoadingDialog.show(this.getUIContext())
|
||||||
|
this.isSuccess = false
|
||||||
|
let cachePath = FileUtil.getCacheDirPath() + FileUtil.separator + `cache_${systemDateTime.getTime()}.mp4`
|
||||||
|
if (FileUtil.accessSync(cachePath)) {
|
||||||
|
FileUtil.unlinkSync(cachePath)
|
||||||
|
}
|
||||||
|
let file = FileUtil.openSync(this.videoUri!!, fileIo.OpenMode.READ_ONLY)
|
||||||
|
// 复制文件到缓存目录下
|
||||||
|
FileUtil.copyFileSync(file.fd, cachePath)
|
||||||
|
FileUtil.closeSync(file)
|
||||||
|
|
||||||
|
let outputPath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.mp3`
|
||||||
|
let cmd = `ffmpeg -i ${cachePath} -vn -c:a mp3 ${outputPath}`
|
||||||
|
MP4Parser.ffmpegCmd(cmd, {
|
||||||
|
callBackResult: (code: number) => {
|
||||||
|
if (code === 0) {
|
||||||
|
this.recognizeAudio(outputPath)
|
||||||
|
.then((result: VoiceRecognizeResultEntity) => {
|
||||||
|
this.resultText = result.flash_result[0].text
|
||||||
|
this.isSuccess = true
|
||||||
|
this.isPlaying = false
|
||||||
|
ToastUtils.show('处理成功')
|
||||||
|
LoadingDialog.dismiss()
|
||||||
|
})
|
||||||
|
.catch((e: BusinessError) => {
|
||||||
|
console.log(e.message)
|
||||||
|
ToastUtils.show('处理失败')
|
||||||
|
LoadingDialog.dismiss()
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
ToastUtils.show('处理失败')
|
||||||
|
LoadingDialog.dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
async recognizeAudio(uri: string): Promise<VoiceRecognizeResultEntity> {
|
||||||
|
let builder = new QCloud.FileFlash.Builder()
|
||||||
|
builder.appID = Constants.QCLOUD_APP_ID
|
||||||
|
builder.secretID = Constants.QCLOUD_SECRET_ID
|
||||||
|
builder.secretKey = Constants.QCLOUD_SECRET_KEY
|
||||||
|
// builder.token = this._token
|
||||||
|
builder.setApiParam(QCloud.FileFlash.kEngineType, '16k_zh')
|
||||||
|
builder.setApiParam(QCloud.FileFlash.kVoiceFormat, 'mp3')
|
||||||
|
builder.setApiParam(QCloud.FileFlash.kFilterDirty, 0)
|
||||||
|
builder.setApiParam(QCloud.FileFlash.kFilterModal, 0)
|
||||||
|
builder.setApiParam(QCloud.FileFlash.kFilterPunc, 0)
|
||||||
|
builder.setApiParam(QCloud.FileFlash.kConvertNumMode, 1)
|
||||||
|
builder.setApiParam(QCloud.FileFlash.kWordInfo, 0)
|
||||||
|
builder.setApiParam(QCloud.FileFlash.kSpeakerDiarization, 1)
|
||||||
|
try {
|
||||||
|
let file = FileUtil.openSync(uri, fileIo.OpenMode.READ_ONLY)
|
||||||
|
const stat = FileUtil.lstatSync(uri)
|
||||||
|
const buffer = new ArrayBuffer(stat.size)
|
||||||
|
FileUtil.readSync(file.fd, buffer)
|
||||||
|
FileUtil.closeSync(file)
|
||||||
|
let result = await builder.build(buffer).task
|
||||||
|
const voiceResult = plainToInstance(VoiceRecognizeResultEntity, result)
|
||||||
|
return Promise.resolve(voiceResult)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
return Promise.reject(e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
selectVideo() {
|
||||||
|
PhotoHelper.selectEasy({
|
||||||
|
MIMEType: photoAccessHelper.PhotoViewMIMETypes.VIDEO_TYPE,
|
||||||
|
maxSelectNumber: 1,
|
||||||
|
isPhotoTakingSupported: false,
|
||||||
|
isEditSupported: false,
|
||||||
|
isOriginalSupported: false
|
||||||
|
})
|
||||||
|
.then((uris) => {
|
||||||
|
if (uris.length != 0) {
|
||||||
|
this.isSuccess = false
|
||||||
|
this.videoUri = uris[0]
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
showDownloadDialog() {
|
||||||
|
DownloadDialog.show(this.getUIContext(), { status: DownloadStatus.COMPLETED, totalSize: 0, progress: 0, totalCount: 1, index: 0, callback: {
|
||||||
|
confirm: () => {
|
||||||
|
AppUtil.getContext().eventHub.emit(EventConstants.JumpToRecordEvent, 0)
|
||||||
|
this.getUIContext().getRouter().back()
|
||||||
|
}
|
||||||
|
} })
|
||||||
|
}
|
||||||
|
|
||||||
|
formatTime(time: number): string {
|
||||||
|
let minute: number = 0
|
||||||
|
let second: number = 0
|
||||||
|
if (time > 60) {
|
||||||
|
minute = Math.trunc(time / 60)
|
||||||
|
second = time % 60
|
||||||
|
if (minute < 10) {
|
||||||
|
if (second < 10) {
|
||||||
|
return `0${minute}:0${second}`
|
||||||
|
} else {
|
||||||
|
return `0${minute}:${second}`
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (second < 10) {
|
||||||
|
return `${minute}:0${second}`
|
||||||
|
} else {
|
||||||
|
return `${minute}:${second}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
second = time
|
||||||
|
if (second < 10) {
|
||||||
|
return `00:0${second}`
|
||||||
|
} else {
|
||||||
|
return `00:${second}`
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
onBackPress(): boolean | void {
|
||||||
|
if (this.isSuccess) {
|
||||||
|
TipDialog.show(this.getUIContext(), {title:'温馨提示', content:'文本尚未保存,是否确定退出?', callback: {
|
||||||
|
confirm: () => {
|
||||||
|
this.getUIContext().getRouter().back()
|
||||||
|
}
|
||||||
|
}})
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
build() {
|
||||||
|
Column() {
|
||||||
|
TitleBar({ title: '视频转文字' })
|
||||||
|
|
||||||
|
Stack() {
|
||||||
|
Stack() {
|
||||||
|
Stack() {
|
||||||
|
Column() {
|
||||||
|
Image($r('app.media.ic_add_video')).width(40).height(40)
|
||||||
|
Text('请上传视频').fontColor($r('app.color.color_466afd')).fontSize(15).fontWeight(FontWeight.Medium).margin({ top: 8})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
.height('100%')
|
||||||
|
.onClick(() => {
|
||||||
|
this.selectVideo()
|
||||||
|
})
|
||||||
|
.visibility(this.videoUri ? Visibility.None : Visibility.Visible)
|
||||||
|
|
||||||
|
RelativeContainer() {
|
||||||
|
Video({
|
||||||
|
src: this.videoUri, // 设置视频源
|
||||||
|
controller: this.controller, //设置视频控制器,可以控制视频的播放状态
|
||||||
|
posterOptions: { showFirstFrame: true }
|
||||||
|
})
|
||||||
|
.width('100%')
|
||||||
|
.height('100%')
|
||||||
|
.borderRadius(20)
|
||||||
|
.backgroundColor(Color.White)
|
||||||
|
.controls(false) // 设置是否显示默认控制条
|
||||||
|
.autoPlay(false) // 设置是否自动播放
|
||||||
|
.loop(false) // 设置是否循环播放
|
||||||
|
.objectFit(ImageFit.Contain) // 设置视频填充模式
|
||||||
|
.onPrepared((event) => {
|
||||||
|
if (event) {
|
||||||
|
this.durationTime = event.duration
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.onUpdate((event) => {
|
||||||
|
if (event) {
|
||||||
|
this.currentTime = event.time
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.onStart(() => {
|
||||||
|
this.isPlaying = true
|
||||||
|
})
|
||||||
|
.onPause(() => {
|
||||||
|
this.isPlaying = false
|
||||||
|
avSessionManager.deactivate()
|
||||||
|
})
|
||||||
|
.onStop(() => {
|
||||||
|
this.isPlaying = false
|
||||||
|
avSessionManager.deactivate()
|
||||||
|
})
|
||||||
|
.onFinish(() => {
|
||||||
|
this.isPlaying = false
|
||||||
|
avSessionManager.deactivate()
|
||||||
|
})
|
||||||
|
.onError(() => {
|
||||||
|
this.isPlaying = false
|
||||||
|
avSessionManager.deactivate()
|
||||||
|
})
|
||||||
|
.onDisAppear(() => {
|
||||||
|
avSessionManager.deactivate()
|
||||||
|
})
|
||||||
|
|
||||||
|
Image($r('app.media.ic_play_video'))
|
||||||
|
.width(50)
|
||||||
|
.height(50)
|
||||||
|
.visibility(this.isPlaying ? Visibility.None : Visibility.Visible)
|
||||||
|
.onClick(async () => {
|
||||||
|
await avSessionManager.activate()
|
||||||
|
this.controller.start()
|
||||||
|
})
|
||||||
|
.alignRules({
|
||||||
|
left: { anchor: '__container__', align: HorizontalAlign.Start },
|
||||||
|
top: { anchor: '__container__', align: VerticalAlign.Top },
|
||||||
|
right: { anchor: '__container__', align: HorizontalAlign.End },
|
||||||
|
bottom: { anchor: '__container__', align: VerticalAlign.Bottom },
|
||||||
|
})
|
||||||
|
|
||||||
|
Row() {
|
||||||
|
Image(this.isPlaying ? $r('app.media.ic_player_controls_pause') : $r('app.media.ic_player_controls_play'))
|
||||||
|
.width(20)
|
||||||
|
.height(20)
|
||||||
|
.margin({ right: 20 })
|
||||||
|
.onClick(async () => {
|
||||||
|
if (this.isPlaying) {
|
||||||
|
this.controller.pause()
|
||||||
|
} else {
|
||||||
|
await avSessionManager.activate()
|
||||||
|
this.controller.start()
|
||||||
|
}
|
||||||
|
})
|
||||||
|
Text(this.formatTime(this.currentTime)).width(35).fontColor(Color.White).fontSize(12)
|
||||||
|
Slider({
|
||||||
|
value: this.currentTime,
|
||||||
|
min: 0,
|
||||||
|
max: this.durationTime
|
||||||
|
})
|
||||||
|
.blockColor(Color.White)
|
||||||
|
.trackColor($r('app.color.color_60ffffff'))
|
||||||
|
.onChange((value: number, mode: SliderChangeMode) => {
|
||||||
|
this.controller.setCurrentTime(value); // 设置视频播放的进度跳转到value处
|
||||||
|
})
|
||||||
|
.layoutWeight(1)
|
||||||
|
Text(this.formatTime(this.durationTime)).width(35).fontColor(Color.White).fontSize(12)
|
||||||
|
}
|
||||||
|
.opacity(0.8)
|
||||||
|
.width("100%")
|
||||||
|
.borderRadius({bottomLeft: 20, bottomRight: 20})
|
||||||
|
.backgroundColor('#1A000000')
|
||||||
|
.padding({ left: 30, right: 30 })
|
||||||
|
.alignRules({
|
||||||
|
bottom: { anchor: '__container__', align: VerticalAlign.Bottom }
|
||||||
|
})
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
.height('100%')
|
||||||
|
.visibility(this.videoUri ? Visibility.Visible : Visibility.None)
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
.aspectRatio(1)
|
||||||
|
.borderRadius(20)
|
||||||
|
.backgroundColor(Color.White)
|
||||||
|
.shadow({radius: 10, color: '#1a9399a1'})
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
.height('auto')
|
||||||
|
.padding({left: 32, right: 32})
|
||||||
|
.margin({top: 40})
|
||||||
|
|
||||||
|
Column() {
|
||||||
|
Row() {
|
||||||
|
Image($r('app.media.ic_star')).width(22).height(22)
|
||||||
|
Text('文本结果').fontColor($r('app.color.color_212226')).fontSize(15).fontWeight(FontWeight.Medium).margin({left: 4})
|
||||||
|
}
|
||||||
|
Divider().strokeWidth(1).color($r('app.color.color_eeeeee')).margin({top: 12})
|
||||||
|
Text(this.resultText).width('100%').height('auto').fontColor($r('app.color.color_212226')).fontSize(14).margin({top: 14})
|
||||||
|
}
|
||||||
|
.width('90%')
|
||||||
|
.layoutWeight(1)
|
||||||
|
.borderRadius(10)
|
||||||
|
.borderWidth(1)
|
||||||
|
.borderColor('#DADEE5')
|
||||||
|
.backgroundColor(Color.White)
|
||||||
|
.margin({top: 30, bottom: 20})
|
||||||
|
.padding(12)
|
||||||
|
.visibility(this.resultText ? Visibility.Visible : Visibility.None)
|
||||||
|
|
||||||
|
Blank().layoutWeight(1).visibility(this.resultText ? Visibility.None : Visibility.Visible)
|
||||||
|
|
||||||
|
Stack() {
|
||||||
|
Button('确认处理', { type: ButtonType.Capsule, stateEffect: true })
|
||||||
|
.width('100%')
|
||||||
|
.height(46)
|
||||||
|
.fontColor(Color.White)
|
||||||
|
.fontSize(15)
|
||||||
|
.fontWeight(FontWeight.Medium)
|
||||||
|
.backgroundColor($r('app.color.color_466afd'))
|
||||||
|
.onClick(() => {
|
||||||
|
if (this.videoUri) {
|
||||||
|
this.videoToAudio()
|
||||||
|
} else {
|
||||||
|
ToastUtils.show('请上传视频')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.visibility(!this.isSuccess ? Visibility.Visible : Visibility.None)
|
||||||
|
|
||||||
|
Row() {
|
||||||
|
Button({ type: ButtonType.Capsule, stateEffect: true }) {
|
||||||
|
Row() {
|
||||||
|
Image($r('app.media.ic_reupload')).width(20).height(20)
|
||||||
|
Text('重新上传').fontColor($r('app.color.color_466afd')).fontSize(15).fontWeight(FontWeight.Medium)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.height(46)
|
||||||
|
.layoutWeight(1)
|
||||||
|
.borderWidth(1)
|
||||||
|
.borderColor($r('app.color.color_466afd'))
|
||||||
|
.backgroundColor(Color.Transparent)
|
||||||
|
.onClick(() => {
|
||||||
|
this.controller.stop()
|
||||||
|
this.selectVideo()
|
||||||
|
})
|
||||||
|
|
||||||
|
Blank().width(9)
|
||||||
|
|
||||||
|
Button({ type: ButtonType.Capsule, stateEffect: true }) {
|
||||||
|
Row() {
|
||||||
|
Image($r('app.media.ic_copy_text')).width(20).height(20)
|
||||||
|
Text('复制文本').fontColor(Color.White).fontSize(15).fontWeight(FontWeight.Medium)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.height(46)
|
||||||
|
.layoutWeight(1)
|
||||||
|
.backgroundColor($r('app.color.color_466afd'))
|
||||||
|
.onClick(() => {
|
||||||
|
this.controller.stop()
|
||||||
|
SaveUtils.saveImageVideoToAlbumDialog([this.videoUri!!])
|
||||||
|
.then((saved) => {
|
||||||
|
if (saved) {
|
||||||
|
this.videoUri = undefined
|
||||||
|
this.showDownloadDialog()
|
||||||
|
} else {
|
||||||
|
ToastUtils.show('保存失败')
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((e: BusinessError) => {
|
||||||
|
ToastUtils.show('保存失败:' + e.message)
|
||||||
|
})
|
||||||
|
})
|
||||||
|
}
|
||||||
|
.visibility(this.isSuccess ? Visibility.Visible : Visibility.None)
|
||||||
|
}
|
||||||
|
.padding({left: 16, top: 9, right: 16, bottom: 30 })
|
||||||
|
.backgroundColor(Color.White)
|
||||||
|
}
|
||||||
|
.width('100%')
|
||||||
|
.height('100%')
|
||||||
|
.backgroundColor($r('app.color.window_background'))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -21,6 +21,7 @@ export struct ToolsPage {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'videoToText': {
|
case 'videoToText': {
|
||||||
|
this.getUIContext().getRouter().pushUrl({url: RouterUrls.VIDEO_TO_TEXT_PAGE})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'videoToAudio': {
|
case 'videoToAudio': {
|
||||||
|
|
@ -28,6 +29,7 @@ export struct ToolsPage {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'audioToText': {
|
case 'audioToText': {
|
||||||
|
this.getUIContext().getRouter().pushUrl({url: RouterUrls.AUDIO_TO_TEXT_PAGE})
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
case 'addWatermark': {
|
case 'addWatermark': {
|
||||||
|
|
|
||||||
|
|
@ -1,4 +1,9 @@
|
||||||
|
import { DisplayUtil } from '@pura/harmony-utils';
|
||||||
|
import { ImagePreview } from '@rv/image-preview';
|
||||||
import { TitleBar } from '../../view/TitleBar'
|
import { TitleBar } from '../../view/TitleBar'
|
||||||
|
import { media } from '@kit.MediaKit';
|
||||||
|
import image from '@ohos.multimedia.image';
|
||||||
|
import { fileIo } from '@kit.CoreFileKit';
|
||||||
|
|
||||||
@Entry
|
@Entry
|
||||||
@ComponentV2
|
@ComponentV2
|
||||||
|
|
@ -6,8 +11,11 @@ struct PhotoViewPage {
|
||||||
@Local title: string = ''
|
@Local title: string = ''
|
||||||
@Local uri?: string = ''
|
@Local uri?: string = ''
|
||||||
|
|
||||||
|
private imageSize: media.PixelMapParams = {}
|
||||||
|
|
||||||
aboutToAppear(): void {
|
aboutToAppear(): void {
|
||||||
this.initParams()
|
this.initParams()
|
||||||
|
this.initImageSize()
|
||||||
}
|
}
|
||||||
|
|
||||||
initParams() {
|
initParams() {
|
||||||
|
|
@ -18,12 +26,31 @@ struct PhotoViewPage {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
initImageSize() {
|
||||||
|
let file = fileIo.openSync(this.uri, fileIo.OpenMode.READ_ONLY)
|
||||||
|
let imageSource = image.createImageSource(file.fd)
|
||||||
|
let imageInfo = imageSource.getImageInfoSync()
|
||||||
|
this.imageSize.width = imageInfo.size.width
|
||||||
|
this.imageSize.height = imageInfo.size.height
|
||||||
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
Column() {
|
Column() {
|
||||||
TitleBar({title: this.title}).width('100%')
|
TitleBar({title: this.title}).width('100%')
|
||||||
Image(this.uri).width('100%').layoutWeight(1)
|
Stack() {
|
||||||
.margin({bottom: 50})
|
ImagePreview() {
|
||||||
.objectFit(ImageFit.Contain)
|
Image(this.uri)
|
||||||
|
.width('100%')
|
||||||
|
.objectFit(ImageFit.Contain)
|
||||||
|
.draggable(false)
|
||||||
|
.sourceSize({
|
||||||
|
width: px2vp(DisplayUtil.getWidth()),
|
||||||
|
height: px2vp(Math.round(this.imageSize.height!! * DisplayUtil.getWidth() / this.imageSize.width!!))
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.layoutWeight(1)
|
||||||
|
.margin({bottom: 50})
|
||||||
}
|
}
|
||||||
.width('100%')
|
.width('100%')
|
||||||
.height('100%')
|
.height('100%')
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,53 @@
|
||||||
|
import { common2D, drawing } from "@kit.ArkGraphics2D";
|
||||||
|
import { image } from "@kit.ImageKit";
|
||||||
|
|
||||||
|
export class ImageUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 调整图片分辨率
|
||||||
|
* @param bitmap
|
||||||
|
* @param w
|
||||||
|
* @param h
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
static async resizeImage(bitmap: PixelMap, w: number, h: number): Promise<image.PixelMap> {
|
||||||
|
// 获取图像像素信息
|
||||||
|
const imageInfo = await bitmap.getImageInfo();
|
||||||
|
const width: number = imageInfo.size.width;
|
||||||
|
const height: number = imageInfo.size.height;
|
||||||
|
const scaleWidth: number = w / width;
|
||||||
|
const scaleHeight: number = h / height;
|
||||||
|
const pixelMapColor: ArrayBuffer = new ArrayBuffer(w * h * 2);
|
||||||
|
const options: image.InitializationOptions = {
|
||||||
|
editable: true,
|
||||||
|
pixelFormat: image.PixelMapFormat.RGB_565,
|
||||||
|
size: { height: h, width: w }
|
||||||
|
};
|
||||||
|
// 采用RGB_565格式创建画布PixelMap
|
||||||
|
const canvasPixelMap = await image.createPixelMap(pixelMapColor, options);
|
||||||
|
// 创建一个以PixelMap作为绘制目标的Canvas对象
|
||||||
|
const canvas = new drawing.Canvas(canvasPixelMap);
|
||||||
|
// 构造矩阵对象
|
||||||
|
const matrix = new drawing.Matrix();
|
||||||
|
// 构造画笔对象
|
||||||
|
let pen = new drawing.Pen();
|
||||||
|
// 绑定画笔到画布上,在画布上进行绘制时,将使用画笔的样式去绘制图形形状的轮廓
|
||||||
|
canvas.attachPen(pen);
|
||||||
|
// 矩形区域
|
||||||
|
let rect: common2D.Rect = {
|
||||||
|
left: 0,
|
||||||
|
top: 0,
|
||||||
|
right: w,
|
||||||
|
bottom: h
|
||||||
|
};
|
||||||
|
// 将图片绘制到画布的指定区域上
|
||||||
|
canvas.drawImageRect(bitmap, rect);
|
||||||
|
// 将矩阵设置为矩阵右乘围绕轴心点按一定缩放系数缩放后的单位矩阵后得到的矩阵
|
||||||
|
matrix.postScale(scaleWidth, scaleHeight, 0, 0);
|
||||||
|
// 设置矩阵对象参数
|
||||||
|
canvas.setMatrix(matrix);
|
||||||
|
// 将画笔与画布解绑
|
||||||
|
canvas.detachPen();
|
||||||
|
return Promise.resolve(canvasPixelMap)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -13,6 +13,7 @@ export class MediaUtils {
|
||||||
let metadata = await avMetaDataExtractor.fetchMetadata()
|
let metadata = await avMetaDataExtractor.fetchMetadata()
|
||||||
videoSize.width = parseInt(metadata.videoWidth as string);
|
videoSize.width = parseInt(metadata.videoWidth as string);
|
||||||
videoSize.height = parseInt(metadata.videoHeight as string);
|
videoSize.height = parseInt(metadata.videoHeight as string);
|
||||||
|
FileUtil.closeSync(file)
|
||||||
return Promise.resolve(videoSize)
|
return Promise.resolve(videoSize)
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
let cacheFilePath = FileUtil.getCacheDirPath() + '/' + FileUtil.getFileName(uri)
|
let cacheFilePath = FileUtil.getCacheDirPath() + '/' + FileUtil.getFileName(uri)
|
||||||
|
|
@ -20,6 +21,7 @@ export class MediaUtils {
|
||||||
let file = FileUtil.openSync(uri, fileIo.OpenMode.READ_ONLY);
|
let file = FileUtil.openSync(uri, fileIo.OpenMode.READ_ONLY);
|
||||||
// 复制文件到缓存目录下
|
// 复制文件到缓存目录下
|
||||||
FileUtil.copyFileSync(file.fd, cacheFilePath)
|
FileUtil.copyFileSync(file.fd, cacheFilePath)
|
||||||
|
FileUtil.closeSync(file)
|
||||||
|
|
||||||
avMetaDataExtractor.fdSrc = FileUtil.openSync(cacheFilePath);
|
avMetaDataExtractor.fdSrc = FileUtil.openSync(cacheFilePath);
|
||||||
let metadata = await avMetaDataExtractor.fetchMetadata()
|
let metadata = await avMetaDataExtractor.fetchMetadata()
|
||||||
|
|
|
||||||
|
|
@ -6,9 +6,39 @@ import { EventConstants } from '../common/EventConstants';
|
||||||
import { MediaAction, MediaType } from '../manager/MediaManager';
|
import { MediaAction, MediaType } from '../manager/MediaManager';
|
||||||
import { LocalMediaManager } from '../manager/LocalMediaManager';
|
import { LocalMediaManager } from '../manager/LocalMediaManager';
|
||||||
import { systemDateTime } from '@kit.BasicServicesKit';
|
import { systemDateTime } from '@kit.BasicServicesKit';
|
||||||
|
import { image } from '@kit.ImageKit';
|
||||||
|
|
||||||
export class SaveUtils {
|
export class SaveUtils {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 保存pixelMap到相册
|
||||||
|
* @param pixelMap
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
|
static async savePixelMapToAlbum(pixelMap: image.PixelMap): Promise<boolean> {
|
||||||
|
try {
|
||||||
|
const packOptions: image.PackingOption = {
|
||||||
|
format: 'image/jpeg',
|
||||||
|
quality: 80
|
||||||
|
}
|
||||||
|
let buffer = await image.createImagePacker().packToData(pixelMap, packOptions)
|
||||||
|
// 应用沙箱路径
|
||||||
|
let cachePath = FileUtil.getCacheDirPath() + FileUtil.separator + `scmf_${systemDateTime.getTime()}.jpeg`
|
||||||
|
// 在沙箱新建并打开文件
|
||||||
|
let file = fileIo.openSync(cachePath, fileIo.OpenMode.READ_WRITE | fileIo.OpenMode.CREATE)
|
||||||
|
// 写入pixelMap图片内容
|
||||||
|
fileIo.writeSync(file.fd, buffer)
|
||||||
|
// 关闭文件
|
||||||
|
fileIo.closeSync(file.fd)
|
||||||
|
// 使用showAssetsCreationDialog保存沙箱中的图片
|
||||||
|
let saved = await SaveUtils.saveImageVideoToAlbumDialog([cachePath])
|
||||||
|
return Promise.resolve(saved)
|
||||||
|
} catch (e) {
|
||||||
|
console.error(e)
|
||||||
|
return Promise.resolve(false)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 保存视频和图片到相册, 弹窗授权
|
* 保存视频和图片到相册, 弹窗授权
|
||||||
* @param path
|
* @param path
|
||||||
|
|
|
||||||
|
|
@ -1,12 +1,15 @@
|
||||||
import { RouterUrls } from '../common/RouterUrls';
|
import { RouterUrls } from '../common/RouterUrls';
|
||||||
import { MediaRecordEntity } from '../entity/MediaRecordEntity';
|
import { MediaRecordEntity } from '../entity/MediaRecordEntity';
|
||||||
import { router } from '@kit.ArkUI';
|
import { router } from '@kit.ArkUI';
|
||||||
import { AppUtil, DateUtil, StrUtil } from '@pura/harmony-utils';
|
import { AppUtil, DateUtil, DisplayUtil, StrUtil } from '@pura/harmony-utils';
|
||||||
import { ShareManager } from '../manager/ShareManager';
|
import { ShareManager } from '../manager/ShareManager';
|
||||||
import { Want } from '@kit.AbilityKit';
|
import { Want } from '@kit.AbilityKit';
|
||||||
import { SimpleTipDialog } from '../dialog/SimpleTipDialog';
|
import { SimpleTipDialog } from '../dialog/SimpleTipDialog';
|
||||||
import { PrefUtils } from '../utils/PrefUtils';
|
import { PrefUtils } from '../utils/PrefUtils';
|
||||||
import { WantUtils } from '../utils/WantUtils';
|
import { WantUtils } from '../utils/WantUtils';
|
||||||
|
import { media } from '@kit.MediaKit';
|
||||||
|
import { fileIo } from '@kit.CoreFileKit';
|
||||||
|
import { image } from '@kit.ImageKit';
|
||||||
|
|
||||||
@ComponentV2
|
@ComponentV2
|
||||||
export struct VideoRecordItemView {
|
export struct VideoRecordItemView {
|
||||||
|
|
@ -85,6 +88,20 @@ export struct ImageRecordItemView {
|
||||||
@Param media?: MediaRecordEntity = undefined;
|
@Param media?: MediaRecordEntity = undefined;
|
||||||
@Param rowCount: number = 1;
|
@Param rowCount: number = 1;
|
||||||
|
|
||||||
|
private imageSize: media.PixelMapParams = {}
|
||||||
|
|
||||||
|
aboutToAppear(): void {
|
||||||
|
this.initImageSize()
|
||||||
|
}
|
||||||
|
|
||||||
|
initImageSize() {
|
||||||
|
let file = fileIo.openSync(this.media?.uri, fileIo.OpenMode.READ_ONLY)
|
||||||
|
let imageSource = image.createImageSource(file.fd)
|
||||||
|
let imageInfo = imageSource.getImageInfoSync()
|
||||||
|
this.imageSize.width = imageInfo.size.width
|
||||||
|
this.imageSize.height = imageInfo.size.height
|
||||||
|
}
|
||||||
|
|
||||||
build() {
|
build() {
|
||||||
RelativeContainer() {
|
RelativeContainer() {
|
||||||
Image(this.media?.uri)
|
Image(this.media?.uri)
|
||||||
|
|
@ -92,6 +109,10 @@ export struct ImageRecordItemView {
|
||||||
.height('100%')
|
.height('100%')
|
||||||
.borderRadius(6)
|
.borderRadius(6)
|
||||||
.backgroundColor($r('app.color.color_222222'))
|
.backgroundColor($r('app.color.color_222222'))
|
||||||
|
.sourceSize({
|
||||||
|
width: px2vp(DisplayUtil.getWidth() / 2),
|
||||||
|
height: px2vp(Math.round(this.imageSize.height!! * DisplayUtil.getWidth() / 2 / this.imageSize.width!!))
|
||||||
|
})
|
||||||
.onClick(() => {
|
.onClick(() => {
|
||||||
this.getUIContext().getRouter().pushUrl({ url: RouterUrls.PHOTO_VIEW_PAGE, params: { uri : this.media?.uri } })
|
this.getUIContext().getRouter().pushUrl({ url: RouterUrls.PHOTO_VIEW_PAGE, params: { uri : this.media?.uri } })
|
||||||
})
|
})
|
||||||
|
|
|
||||||
Binary file not shown.
|
After Width: | Height: | Size: 398 B |
Binary file not shown.
|
After Width: | Height: | Size: 1.1 KiB |
|
|
@ -19,6 +19,8 @@
|
||||||
"pages/main/home/tools/AddAudioPage",
|
"pages/main/home/tools/AddAudioPage",
|
||||||
"pages/main/home/tools/VideoToAudioPage",
|
"pages/main/home/tools/VideoToAudioPage",
|
||||||
"pages/main/home/tools/ImageMergePage",
|
"pages/main/home/tools/ImageMergePage",
|
||||||
|
"pages/main/home/tools/VideoToTextPage",
|
||||||
|
"pages/main/home/tools/AudioToTextPage",
|
||||||
"pages/main/home/material/MaterialDetailPage",
|
"pages/main/home/material/MaterialDetailPage",
|
||||||
"pages/main/mine/user/UserSettingsPage",
|
"pages/main/mine/user/UserSettingsPage",
|
||||||
"pages/main/mine/vip/VipPage",
|
"pages/main/mine/vip/VipPage",
|
||||||
|
|
|
||||||
|
|
@ -7,6 +7,7 @@
|
||||||
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
"ATTENTION": "THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY.",
|
||||||
"specifiers": {
|
"specifiers": {
|
||||||
"@alipay/blueshieldsdk@oh_modules/.ohpm/@cashier_alipay+cashiersdk@15.8.36/oh_modules/@cashier_alipay/cashiersdk/lib/blueshieldsdk-1.0.29.har": "@alipay/blueshieldsdk@oh_modules/.ohpm/@cashier_alipay+cashiersdk@15.8.36/oh_modules/@cashier_alipay/cashiersdk/lib/blueshieldsdk-1.0.29.har",
|
"@alipay/blueshieldsdk@oh_modules/.ohpm/@cashier_alipay+cashiersdk@15.8.36/oh_modules/@cashier_alipay/cashiersdk/lib/blueshieldsdk-1.0.29.har": "@alipay/blueshieldsdk@oh_modules/.ohpm/@cashier_alipay+cashiersdk@15.8.36/oh_modules/@cashier_alipay/cashiersdk/lib/blueshieldsdk-1.0.29.har",
|
||||||
|
"@ark/luban@^1.0.2": "@ark/luban@1.0.2",
|
||||||
"@cashier_alipay/cashiersdk@^15.8.36": "@cashier_alipay/cashiersdk@15.8.36",
|
"@cashier_alipay/cashiersdk@^15.8.36": "@cashier_alipay/cashiersdk@15.8.36",
|
||||||
"@ohos/crypto-js@^2.0.4": "@ohos/crypto-js@2.0.4",
|
"@ohos/crypto-js@^2.0.4": "@ohos/crypto-js@2.0.4",
|
||||||
"@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
|
"@ohos/hamock@1.0.0": "@ohos/hamock@1.0.0",
|
||||||
|
|
@ -38,6 +39,13 @@
|
||||||
"libblueshield.so": "file:./src/main/cpp/types/libblueshield"
|
"libblueshield.so": "file:./src/main/cpp/types/libblueshield"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@ark/luban@1.0.2": {
|
||||||
|
"name": "@ark/luban",
|
||||||
|
"version": "1.0.2",
|
||||||
|
"integrity": "sha512-p5YLHNVi8sSE2b3GxeXXg88bmP16qtGv8QRrNfxDSt9aKgt9PZ6xuPKY6+ORrXIbih0n9t97qHRfMlinqv6UdA==",
|
||||||
|
"resolved": "https://repo.harmonyos.com/ohpm/@ark/luban/-/luban-1.0.2.har",
|
||||||
|
"registryType": "ohpm"
|
||||||
|
},
|
||||||
"@cashier_alipay/cashiersdk@15.8.36": {
|
"@cashier_alipay/cashiersdk@15.8.36": {
|
||||||
"name": "@cashier_alipay/cashiersdk",
|
"name": "@cashier_alipay/cashiersdk",
|
||||||
"version": "15.8.36",
|
"version": "15.8.36",
|
||||||
|
|
|
||||||
|
|
@ -11,7 +11,8 @@
|
||||||
"@tencent/libpag": "^4.4.31",
|
"@tencent/libpag": "^4.4.31",
|
||||||
"@ohos/mp4parser": "^2.0.7",
|
"@ohos/mp4parser": "^2.0.7",
|
||||||
"@ohos/imageknifepro": "^1.0.12",
|
"@ohos/imageknifepro": "^1.0.12",
|
||||||
"@rv/image-preview": "^2.1.2"
|
"@rv/image-preview": "^2.1.2",
|
||||||
|
"@ark/luban": "^1.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@ohos/hypium": "1.0.21",
|
"@ohos/hypium": "1.0.21",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue