package main import ( "encoding/csv" "fmt" "github.com/manifoldco/promptui" "golang.org/x/text/encoding/simplifiedchinese" "golang.org/x/text/transform" "os" "strings" ) func getCsvInfo(dir string) (dataMap []map[string]string, title []string, files []string) { fp := fmt.Sprintf("%s/%s/", dir, "csvfile") if _, err := os.Stat(fp); os.IsNotExist(err) { // 文件夹不存在,创建它 err := os.Mkdir(fp, 0755) // 0755 是常见的目录权限 if err != nil { fatal("无法创建目录 %s: %v", fp, err) } } entries, err := os.ReadDir(fp) if err != nil { fatal("获取文件目录失败 %s: %v", fp, err) } if len(entries) == 0 { warning("请将需导入文件放入%s目录下", fp) exit() } var csvFiles []string for _, entry := range entries { if !entry.IsDir() && strings.HasSuffix(strings.ToLower(entry.Name()), ".csv") { csvFiles = append(csvFiles, entry.Name()) } } for { prompt := promptui.Select{ Label: "请选择需要导入的csv文件: ", Items: append([]string{"全选", "导入非`已导入_`开头的文件"}, csvFiles...), Size: len(csvFiles) + 2, } _, f, err := prompt.Run() if err != nil { warning("Prompt failed %v\n", err) continue } f = strings.TrimSpace(f) switch f { case "全选": for _, s := range csvFiles { files = append(files, fmt.Sprintf("%s%s", fp, s)) } case "导入非`已导入_`开头的文件": for _, s := range csvFiles { if !strings.HasPrefix(s, "已导入_") { files = append(files, fmt.Sprintf("%s%s", fp, s)) } } default: files = append(files, fmt.Sprintf("%s%s", fp, f)) } break } if len(files) == 0 { warning("未找到符合条件的文件") finish(dir) } for _, v := range files { data, fileTitle := ReadCsvData(v) if title == nil { title = fileTitle } dataMap = append(dataMap, data...) } return dataMap, title, files } func ReadCsvData(fp string) (dataMap []map[string]string, title []string) { log("正在读取CSV文件,请稍等...") // 打开CSV文件 file, err := os.Open(fp) if err != nil { fatal("无法打开文件: %v", err) } defer file.Close() decoder := simplifiedchinese.GBK.NewDecoder() // 创建CSV读取器 reader := csv.NewReader(transform.NewReader(file, decoder)) // 可选:设置更宽松的解析选项 reader.LazyQuotes = true // 允许非引号包裹的字段中包含引号 // 读取所有记录 records, err := reader.ReadAll() if err != nil { fatal("读取CSV记录出错: %v", err) } if len(records) < 2 { fatal("CSV文件至少需要两行,第一行是标题,第二行是数据") } // 创建map来存储数据 dataMap = make([]map[string]string, len(records)) title = records[0] for i := 1; i < len(records); i++ { dataMap[i-1] = make(map[string]string) for j := 0; j < len(records[i]); j++ { // 假设第一列是唯一标识符 dataMap[i-1][title[j]] = records[i][j] } } log("文件读取完毕") return } func desc(video *Video) { var d strings.Builder tip("描述信息,请输入一段描述文字,描述文字越多,生成视频越精彩。") input("请设置描述信息: ") text, _ := reader.ReadString('\n') d.WriteString(fmt.Sprintf("%s ", strings.TrimSpace(text))) d.WriteString("--watermark ") d.WriteString("false ") for { prompt := promptui.Select{ Label: "分辨率: ", Items: []string{"480p", "720p"}, } _, r, err := prompt.Run() if err != nil { warning("Prompt failed %v\n", err) continue } d.WriteString("--resolution ") d.WriteString(r) d.WriteString(" ") break } for { prompt := promptui.Select{ Label: "视频时长(秒): ", Items: []string{"5", "10"}, } _, r, err := prompt.Run() if err != nil { warning("Prompt failed %v\n", err) continue } d.WriteString("--dur ") d.WriteString(r) d.WriteString(" ") break } tip("adaptive:根据所上传图片的比例,自动选择最合适的宽高比。") for { prompt := promptui.Select{ Label: "视频的宽高比例: ", Items: []string{"adaptive", "16:9", "9:16", "4:3", "3:4", "21:9", "9:21", "1:1"}, } _, r, err := prompt.Run() if err != nil { warning("Prompt failed %v\n", err) continue } d.WriteString("--ratio ") d.WriteString(r) d.WriteString(" ") break } for { prompt := promptui.Select{ Label: "帧率: ", Items: []string{"16", "24"}, } _, r, err := prompt.Run() if err != nil { warning("Prompt failed %v\n", err) continue } d.WriteString("--framepersecond ") d.WriteString(r) d.WriteString(" ") break } for { prompt := promptui.Select{ Label: "是否固定摄像头: ", Items: []string{"false", "true"}, } _, r, err := prompt.Run() if err != nil { warning("Prompt failed %v\n", err) continue } d.WriteString("--camerafixed ") d.WriteString(r) d.WriteString(" ") break } video.Text = d.String() }