Run this notebook

Use Livebook to open this notebook and explore new ideas.

It is easy to get started, on your machine or the cloud.

Click below to open and run it in your Livebook at .

(or change your Livebook location)

# Google Drive 3gp to mp4 converter ## Section ```elixir defmodule GoogleDrive3gpToMp4 do @moduledoc """ - Lazily traverses google drive path to find .3gp files - Processes each file immediately when discovered (no sorting, no concurrency) - converts it to .mp4 using ffmpeg, preserves timestamps - removes the .3gp file on success. NOTE: Uses 'touch -r' (Unix-like) to copy timestamps. On Windows, you may need a Unix-like environment (Git Bash, Cygwin, WSL) or adapt the logic. **When reuploaded to Google Drive, files loose their timestamps.** """ @drive_path Path.expand("<TODO: your Google Drive path here>") def run do IO.puts("Scanning lazily for .3gp files in: #{@drive_path}") stream_3gp_files(@drive_path) |> Stream.each(&process_file/1) |> Stream.run() end defp stream_3gp_files(base_path) do # If the base path doesn't exist, return an empty stream if not File.exists?(base_path) do Stream.map([], & &1) else Stream.resource( fn -> [base_path] end, fn [] -> {:halt, []} [current | rest] -> cond do File.dir?(current) -> case File.ls(current) do {:ok, entries} -> subpaths = Enum.map(entries, &Path.join(current, &1)) {[], rest ++ subpaths} {:error, _} -> {[], rest} end Path.extname(current) == ".3gp" -> {[current], rest} true -> {[], rest} end end, fn _ -> :ok end ) end end defp process_file(file_path) do mp4_path = Path.rootname(file_path) <> ".mp4" IO.puts(""" Found .3gp file: - #{file_path} Converting to: - #{mp4_path} """) case convert_to_mp4(file_path, mp4_path) do :ok -> # Copy original timestamps to the new .mp4 case preserve_timestamps(file_path, mp4_path) do :ok -> File.rm(file_path) IO.puts( "✔ Conversion & timestamp preservation successful. Removed original: #{file_path}\n" ) {:error, reason} -> IO.puts("⚠ Could not preserve timestamps for #{mp4_path}: #{reason}") # Decide if you still remove the original if preserving fails File.rm(file_path) end {:error, reason} -> IO.puts("✘ Conversion failed for #{file_path}:\n#{reason}\n") end end defp convert_to_mp4(input_file, output_file) do args = [ # Overwrite output if it exists "-y", "-i", input_file, "-c:v", "libx264", "-preset", "slow", "-crf", "23", "-c:a", "aac", "-b:a", "128k", output_file ] {output, exit_code} = System.cmd("/opt/homebrew/bin/ffmpeg", args, stderr_to_stdout: true) if exit_code == 0 do :ok else {:error, output} end end defp preserve_timestamps(original, new_file) do case System.cmd("touch", ["-r", original, new_file]) do {_, 0} -> :ok {error_msg, code} -> {:error, "touch exited with code #{code}: #{error_msg}"} end end end GoogleDrive3gpToMp4.run() ```
See source

Have you already installed Livebook?

If you already installed Livebook, you can configure the default Livebook location where you want to open notebooks.
Livebook up Checking status We can't reach this Livebook (but we saved your preference anyway)
Run notebook

Not yet? Install Livebook in just a minute

Livebook is open source, free, and ready to run anywhere.

Run on your machine

with Livebook Desktop

Run in the cloud

on select platforms

To run on Linux, Docker, embedded devices, or Elixir’s Mix, check our README.

PLATINUM SPONSORS
SPONSORS
Code navigation with go to definition of modules and functions Read More ×