Skip to content

Instantly share code, notes, and snippets.

@zored
Last active September 12, 2021 16:42
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zored/affd83622ccba7c77e00c9b432dee417 to your computer and use it in GitHub Desktop.
Save zored/affd83622ccba7c77e00c9b432dee417 to your computer and use it in GitHub Desktop.
Video rename (with Deno) and convertion from h.265 to h.264 (with ffmpeg)

How I move files from iPhone to Google Drive

  • Copy files to computer using 3uTools.
  • Rename files with for c in save-renames rename; do deno run -A --unstable rename.ts $c; done.
  • Remove .webp files because they are trash.
  • Move video files in ./video directory (.mp4, .mov).
  • Create ./video_x264 and run ./convert.sh.
  • Wait for million years.
  • Check ./video_x264 and remove ./video.
  • Review media collection with Filter UI.
  • Send results to Google Drive.
#!/bin/bash
set -e
pushd video
for f in *; do
ffmpeg -i "${f}" -c:v libx264 -crf 18 -c:a copy "../video_x264/${f}"
done
import { walkSync } from "https://deno.land/std@0.106.0/fs/mod.ts";
const renamesFile = "renames.json";
let renames: [string, string][];
function fillId(id: ImageId | null, d: Date | null, p: string): null | ImageId {
if (!d) {
return id;
}
if (id == null) {
return null;
}
const zero = (v: number): string => (v < 10 ? "0" : "") + v;
const extensionMatches = p.match(/.*\.(?<ext>.*)$/i);
return {
path: p,
year: id?.year || d.getFullYear() + "",
month: id?.month || zero(d.getMonth() + 1),
date: id?.date || zero(d.getDate()),
hours: id?.hours || zero(d.getHours()),
minutes: id?.minutes || zero(d.getMinutes()),
version: id?.version || "0000",
extension: id?.extension || (extensionMatches?.groups?.ext ?? ""),
};
}
interface ImageId {
path: string;
year: string;
month: string;
date: string;
hours: string;
minutes: string;
version: string;
extension: string;
}
function getImageId(p: string): null | ImageId {
const patterns = [
// My iPhone:
/(?<year>\d{4})_(?<month>\d{2})_(?<date>\d{2})_(?<hours>\d{2})_(?<minutes>\d{2})_IMG_(?<version>\d{4})\.(?<ext>[^.]*)$/i,
// Others:
/(img|vid)_(?<year>\d{4})(?<month>\d{2})(?<date>\d{2})_(?<hours>\d{2})(?<minutes>\d{2})(?<version>\d{2}(_\d+)?)\.(?<ext>[^.]*)$/i,
/(img|vid)_(?<version>\d+)\.(?<ext>[^.]+)$/i,
];
const g = patterns.map((v) => p.match(v)).find((v) => !!v)?.groups;
if (!g) {
return null;
}
return {
path: p,
year: g.year || "",
month: g.month || "",
date: g.date || "",
hours: g.hours || "",
minutes: g.minutes || "",
version: g.version || "",
extension: g.extension || "",
};
}
switch (Deno.args[0]) {
case "save-renames":
renames = [...walkSync(".")]
.map((e) => e.path)
.map((p): null | ImageId =>
fillId(getImageId(p), Deno.statSync(p).birthtime, p)
)
.filter((id): id is ImageId => id !== null)
.map((
{ year, month, date, hours, minutes, version, extension, path },
) => [
path,
`${year}-${month}-${date} ${hours}-${minutes} ${version}.${extension.toUpperCase()}`,
]);
await Deno.writeTextFile(renamesFile, JSON.stringify(renames));
console.log(`Saved to ${renamesFile}.`);
break;
case "rename":
renames = JSON.parse(await Deno.readTextFile(renamesFile));
renames.forEach(([before, after]) => Deno.renameSync(before, after));
console.log(`Renamed ${renames.length} file(s).`);
break;
default:
console.log("?");
Deno.exit(1);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment